diff options
41 files changed, 745 insertions, 235 deletions
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index fe9dd568fc..31e73fbecc 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -200,7 +200,7 @@ static const TracingCategory k_categories[] = { { REQ, "events/vmscan/mm_vmscan_direct_reclaim_end/enable" }, { REQ, "events/vmscan/mm_vmscan_kswapd_wake/enable" }, { REQ, "events/vmscan/mm_vmscan_kswapd_sleep/enable" }, - { REQ, "events/lowmemorykiller/enable" }, + { OPT, "events/lowmemorykiller/enable" }, } }, { "regulators", "Voltage and Current Regulators", 0, { { REQ, "events/regulator/enable" }, diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index be3bbf7494..4896f68f06 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -149,12 +149,13 @@ public: const bool isVendorService = strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; const long timeout = uptimeMillis() + 5000; - if (!gSystemBootCompleted) { + if (!gSystemBootCompleted && !isVendorService) { + // Vendor code can't access system properties char bootCompleted[PROPERTY_VALUE_MAX]; property_get("sys.boot_completed", bootCompleted, "0"); gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; } - // retry interval in millisecond. + // retry interval in millisecond; note that vendor services stay at 100ms const long sleepTime = gSystemBootCompleted ? 1000 : 100; int n = 0; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index c8021e4d54..c96a2dd6a3 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -381,7 +381,6 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou { // Autolock scope Mutex::Autolock lock(mCore->mMutex); - mCore->waitWhileAllocatingLocked(); if (format == 0) { format = mCore->mDefaultBufferFormat; @@ -1345,7 +1344,9 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, return; } - newBufferCount = mCore->mFreeSlots.size(); + // Only allocate one buffer at a time to reduce risks of overlapping an allocation from + // both allocateBuffers and dequeueBuffer. + newBufferCount = mCore->mFreeSlots.empty() ? 0 : 1; if (newBufferCount == 0) { return; } @@ -1360,7 +1361,7 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height, } // Autolock scope Vector<sp<GraphicBuffer>> buffers; - for (size_t i = 0; i < newBufferCount; ++i) { + for (size_t i = 0; i < newBufferCount; ++i) { sp<GraphicBuffer> graphicBuffer = new GraphicBuffer( allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT, allocUsage, allocName); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 0749fde1ad..0b3796056d 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -355,7 +355,7 @@ public: data.writeUint32(height); data.writeInt32(static_cast<int32_t>(format)); data.writeUint64(usage); - status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply); + status_t result = remote()->transact(ALLOCATE_BUFFERS, data, &reply, TF_ONE_WAY); if (result != NO_ERROR) { ALOGE("allocateBuffers failed to transact: %d", result); } diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index e22bc708c9..d2d27e8239 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -332,6 +332,34 @@ public: return result; } + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + Parcel data, reply; + status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeInterfaceToken: %d", result); + return result; + } + result = data.writeStrongBinder(display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to writeStrongBinder: %d", result); + return result; + } + result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_VIEWPORT, data, &reply); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to transact: %d", result); + return result; + } + result = reply.readInt32(); + if (result == NO_ERROR) { + result = reply.read(*outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to read: %d", result); + return result; + } + } + return result; + } + virtual int getActiveConfig(const sp<IBinder>& display) { Parcel data, reply; @@ -724,6 +752,26 @@ status_t BnSurfaceComposer::onTransact( } return NO_ERROR; } + case GET_DISPLAY_VIEWPORT: { + CHECK_INTERFACE(ISurfaceComposer, data, reply); + Rect outViewport; + sp<IBinder> display = nullptr; + status_t result = data.readStrongBinder(&display); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to readStrongBinder: %d", result); + return result; + } + result = getDisplayViewport(display, &outViewport); + result = reply->writeInt32(result); + if (result == NO_ERROR) { + result = reply->write(outViewport); + if (result != NO_ERROR) { + ALOGE("getDisplayViewport failed to write: %d", result); + return result; + } + } + return NO_ERROR; + } case GET_ACTIVE_CONFIG: { CHECK_INTERFACE(ISurfaceComposer, data, reply); sp<IBinder> display = data.readStrongBinder(); diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index 339bd0fa4e..2de14c8846 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -464,8 +464,12 @@ int Surface::setSwapInterval(int interval) { if (interval > maxSwapInterval) interval = maxSwapInterval; + const bool wasSwapIntervalZero = mSwapIntervalZero; mSwapIntervalZero = (interval == 0); - mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero); + + if (mSwapIntervalZero != wasSwapIntervalZero) { + mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero); + } return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 63560c4b89..f3c6fd2f87 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -718,6 +718,10 @@ status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display, return NO_ERROR; } +status_t SurfaceComposerClient::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + return ComposerService::getComposerService()->getDisplayViewport(display, outViewport); +} + int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) { return ComposerService::getComposerService()->getActiveConfig(display); } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e40157206d..99a3a75502 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -157,6 +157,9 @@ public: virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) = 0; + /* returns display viewport information of the given display */ + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) = 0; + /* indicates which of the configurations returned by getDisplayInfo is * currently active */ virtual int getActiveConfig(const sp<IBinder>& display) = 0; @@ -250,7 +253,8 @@ public: ENABLE_VSYNC_INJECTIONS, INJECT_VSYNC, GET_LAYER_DEBUG_INFO, - CREATE_SCOPED_CONNECTION + CREATE_SCOPED_CONNECTION, + GET_DISPLAY_VIEWPORT }; virtual status_t onTransact(uint32_t code, const Parcel& data, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 377fe68c41..ad8a8b09d0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -79,6 +79,9 @@ public: static status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info); + // Get the display viewport for the given display + static status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport); + // Get the index of the current active configuration (relative to the list // returned by getDisplayInfo) static int getActiveConfig(const sp<IBinder>& display); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 2c02ba657d..6e196bfac8 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -581,6 +581,9 @@ public: Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; } status_t getDisplayStats(const sp<IBinder>& /*display*/, DisplayStatInfo* /*stats*/) override { return NO_ERROR; } + status_t getDisplayViewport(const sp<IBinder>& /*display*/, Rect* /*outViewport*/) override { + return NO_ERROR; + } int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; } status_t setActiveConfig(const sp<IBinder>& /*display*/, int /*id*/) override { diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index e0cd8a005a..0b7e850452 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -3089,6 +3089,7 @@ TouchInputMapper::TouchInputMapper(InputDevice* device) : InputMapper(device), mSource(0), mDeviceMode(DEVICE_MODE_DISABLED), mSurfaceWidth(-1), mSurfaceHeight(-1), mSurfaceLeft(0), mSurfaceTop(0), + mPhysicalWidth(-1), mPhysicalHeight(-1), mPhysicalLeft(0), mPhysicalTop(0), mSurfaceOrientation(DISPLAY_ORIENTATION_0) { } @@ -3596,6 +3597,11 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { break; } + mPhysicalWidth = naturalPhysicalWidth; + mPhysicalHeight = naturalPhysicalHeight; + mPhysicalLeft = naturalPhysicalLeft; + mPhysicalTop = naturalPhysicalTop; + mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth; mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight; mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth; @@ -3604,6 +3610,11 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) { mSurfaceOrientation = mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0; } else { + mPhysicalWidth = rawWidth; + mPhysicalHeight = rawHeight; + mPhysicalLeft = 0; + mPhysicalTop = 0; + mSurfaceWidth = rawWidth; mSurfaceHeight = rawHeight; mSurfaceLeft = 0; @@ -3914,6 +3925,10 @@ void TouchInputMapper::dumpSurface(std::string& dump) { dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight); dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft); dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop); + dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth); + dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight); + dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft); + dump += StringPrintf(INDENT3 "PhysicalTop: %d\n", mPhysicalTop); dump += StringPrintf(INDENT3 "SurfaceOrientation: %d\n", mSurfaceOrientation); } @@ -5118,10 +5133,10 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_180: - x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate; + x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale; y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; - left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate; - right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate; + left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale; + right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale; bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; orientation -= M_PI; @@ -5130,10 +5145,10 @@ void TouchInputMapper::cookPointerData() { } break; case DISPLAY_ORIENTATION_270: - x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate; + x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale; y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; - left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate; - right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate; + left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale; + right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale; bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate; orientation += M_PI_2; @@ -6531,8 +6546,12 @@ void TouchInputMapper::cancelTouch(nsecs_t when) { } bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) { + const float scaledX = x * mXScale; + const float scaledY = y * mYScale; return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue - && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue; + && scaledX >= mPhysicalLeft && scaledX <= mPhysicalLeft + mPhysicalWidth + && y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue + && scaledY >= mPhysicalTop && scaledY <= mPhysicalTop + mPhysicalHeight; } const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit( diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index cef3212684..2f98e69800 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -1517,13 +1517,21 @@ private: // in the natural orientation. // The surface origin specifies how the surface coordinates should be translated // to align with the logical display coordinate space. - // The orientation may be different from the viewport orientation as it specifies - // the rotation of the surface coordinates required to produce the viewport's - // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceWidth; int32_t mSurfaceHeight; int32_t mSurfaceLeft; int32_t mSurfaceTop; + + // Similar to the surface coordinates, but in the raw display coordinate space rather than in + // the logical coordinate space. + int32_t mPhysicalWidth; + int32_t mPhysicalHeight; + int32_t mPhysicalLeft; + int32_t mPhysicalTop; + + // The orientation may be different from the viewport orientation as it specifies + // the rotation of the surface coordinates required to produce the viewport's + // requested orientation, so it will depend on whether the device is orientation aware. int32_t mSurfaceOrientation; // Translation and scaling factors, orientation-independent. diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index c2bb6ad6b4..320e11f7eb 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -27,6 +27,7 @@ cc_defaults { "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", "android.hardware.power@1.0", + "android.hardware.power@1.3", "libbase", "libbinder", "libbufferhubqueue", @@ -69,6 +70,7 @@ cc_defaults { "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", + "android.hardware.power@1.3", "libhidlbase", "libhidltransport", "libhwbinder", @@ -96,6 +98,7 @@ filegroup { "DisplayHardware/HWC2.cpp", "DisplayHardware/HWComposer.cpp", "DisplayHardware/HWComposerBufferCache.cpp", + "DisplayHardware/PowerAdvisor.cpp", "DisplayHardware/VirtualDisplaySurface.cpp", "DispSync.cpp", "Effects/Daltonizer.cpp", diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fda7906744..7ac1432198 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -63,7 +63,7 @@ BufferLayer::BufferLayer(SurfaceFlinger* flinger, const sp<Client>& client, cons mRefreshPending(false) { ALOGV("Creating Layer %s", name.string()); - mFlinger->getRenderEngine().genTextures(1, &mTextureName); + mTextureName = mFlinger->getNewTexture(); mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName); if (flags & ISurfaceComposerClient::eNonPremultiplied) mPremultipliedAlpha = false; @@ -701,13 +701,19 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } void BufferLayer::onFirstRef() { + Layer::onFirstRef(); + // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); - mConsumer = new BufferLayerConsumer(consumer, - mFlinger->getRenderEngine(), mTextureName, this); + { + // Grab the SF state lock during this since it's the only safe way to access RenderEngine + Mutex::Autolock lock(mFlinger->mStateLock); + mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, + this); + } mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 077469b5e1..0b59147c5a 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -170,48 +170,8 @@ status_t Client::createSurface( } } - /* - * createSurface must be called from the GL thread so that it can - * have access to the GL context. - */ - class MessageCreateLayer : public MessageBase { - SurfaceFlinger* flinger; - Client* client; - sp<IBinder>* handle; - sp<IGraphicBufferProducer>* gbp; - status_t result; - const String8& name; - uint32_t w, h; - PixelFormat format; - uint32_t flags; - sp<Layer>* parent; - int32_t windowType; - int32_t ownerUid; - public: - MessageCreateLayer(SurfaceFlinger* flinger, - const String8& name, Client* client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp<IBinder>* handle, int32_t windowType, int32_t ownerUid, - sp<IGraphicBufferProducer>* gbp, - sp<Layer>* parent) - : flinger(flinger), client(client), - handle(handle), gbp(gbp), result(NO_ERROR), - name(name), w(w), h(h), format(format), flags(flags), - parent(parent), windowType(windowType), ownerUid(ownerUid) { - } - status_t getResult() const { return result; } - virtual bool handler() { - result = flinger->createLayer(name, client, w, h, format, flags, - windowType, ownerUid, handle, gbp, parent); - return true; - } - }; - - sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), - name, this, w, h, format, flags, handle, - windowType, ownerUid, gbp, &parent); - mFlinger->postMessageSync(msg); - return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); + return mFlinger->createLayer(name, this, w, h, format, flags, windowType, + ownerUid, handle, gbp, &parent); } status_t Client::destroySurface(const sp<IBinder>& handle) { diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 543f60a624..b352b96762 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -35,6 +35,8 @@ public: bool isVisible() const override; void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override; + + bool isCreatedFromMainThread() const override { return true; } }; } // namespace android diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp index 7acbd11bc5..37dc27d80d 100644 --- a/services/surfaceflinger/DispSync.cpp +++ b/services/surfaceflinger/DispSync.cpp @@ -222,7 +222,13 @@ public: // Pretend that the last time this event was handled at the same frame but with the // new offset to allow for a seamless offset change without double-firing or // skipping. - listener.mLastEventTime -= (oldPhase - phase); + nsecs_t diff = oldPhase - phase; + if (diff > mPeriod / 2) { + diff -= mPeriod; + } else if (diff < -mPeriod / 2) { + diff += mPeriod; + } + listener.mLastEventTime -= diff; mCond.signal(); return NO_ERROR; } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 61758b63f1..1a60c83b01 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -138,7 +138,7 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height, } auto display = std::make_unique<Display>( - *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual); + *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, DisplayType::Virtual); display->setConnected(true); *outDisplay = display.get(); mDisplays.emplace(displayId, std::move(display)); @@ -177,7 +177,7 @@ void Device::onHotplug(hwc2_display_t displayId, Connection connection) { } auto newDisplay = std::make_unique<Display>( - *mComposer.get(), mCapabilities, displayId, displayType); + *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType); newDisplay->setConnected(true); mDisplays.emplace(displayId, std::move(newDisplay)); } else if (connection == Connection::Disconnected) { @@ -219,10 +219,11 @@ Error Device::flushCommands() // Display methods -Display::Display(android::Hwc2::Composer& composer, +Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor, const std::unordered_set<Capability>& capabilities, hwc2_display_t id, DisplayType type) : mComposer(composer), + mPowerAdvisor(advisor), mCapabilities(capabilities), mId(id), mIsConnected(false), @@ -605,6 +606,12 @@ Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target, Error Display::setColorMode(ColorMode mode, RenderIntent renderIntent) { + // When the color mode is switched to DISPLAY_P3, we want to boost the GPU frequency + // so that GPU composition can finish in time. When color mode is switched from + // DISPLAY_P3, we want to reset GPU frequency. + const bool expensiveRenderingExpected = (mode == ColorMode::DISPLAY_P3); + mPowerAdvisor.setExpensiveRenderingExpected(mId, expensiveRenderingExpected); + auto intError = mComposer.setColorMode(mId, mode, renderIntent); return static_cast<Error>(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 29d7a47ad8..e423167a28 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -37,6 +37,8 @@ #include <unordered_set> #include <vector> +#include "PowerAdvisor.h" + namespace android { class Fence; class FloatRect; @@ -119,6 +121,7 @@ private: std::unique_ptr<android::Hwc2::Composer> mComposer; std::unordered_set<Capability> mCapabilities; std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays; + android::Hwc2::impl::PowerAdvisor mPowerAdvisor; bool mRegisteredCallback = false; }; @@ -126,7 +129,8 @@ private: class Display { public: - Display(android::Hwc2::Composer& composer, const std::unordered_set<Capability>& capabilities, + Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor, + const std::unordered_set<Capability>& capabilities, hwc2_display_t id, DisplayType type); ~Display(); @@ -282,6 +286,7 @@ private: // this HWC2::Display, so these references are guaranteed to be valid for // the lifetime of this object. android::Hwc2::Composer& mComposer; + android::Hwc2::PowerAdvisor& mPowerAdvisor; const std::unordered_set<Capability>& mCapabilities; hwc2_display_t mId; diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp new file mode 100644 index 0000000000..12bbae207b --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp @@ -0,0 +1,99 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "PowerAdvisor" + +#include <cinttypes> + +#include <utils/Log.h> +#include <utils/Mutex.h> + +#include "PowerAdvisor.h" + +namespace android { +namespace Hwc2 { + +PowerAdvisor::~PowerAdvisor() = default; + +namespace impl { + +namespace V1_0 = android::hardware::power::V1_0; +using V1_3::PowerHint; + +PowerAdvisor::~PowerAdvisor() = default; + +PowerAdvisor::PowerAdvisor() = default; + +void PowerAdvisor::setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) { + if (expected) { + mExpensiveDisplays.insert(displayId); + } else { + mExpensiveDisplays.erase(displayId); + } + + const bool expectsExpensiveRendering = !mExpensiveDisplays.empty(); + if (mNotifiedExpensiveRendering != expectsExpensiveRendering) { + const sp<V1_3::IPower> powerHal = getPowerHal(); + if (powerHal == nullptr) { + return; + } + auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, + expectsExpensiveRendering); + // If Power HAL 1.3 was available previously but now fails, + // it may restart, so attempt to reconnect next time + if (!ret.isOk()) { + mReconnectPowerHal = true; + return; + } + mNotifiedExpensiveRendering = expectsExpensiveRendering; + } +} + +sp<V1_3::IPower> PowerAdvisor::getPowerHal() { + static sp<V1_3::IPower> sPowerHal_1_3 = nullptr; + static bool sHasPowerHal_1_3 = true; + + if (mReconnectPowerHal) { + sPowerHal_1_3 = nullptr; + mReconnectPowerHal = false; + } + + // Power HAL 1.3 is not guaranteed to be available, thus we need to query + // Power HAL 1.0 first and try to cast it to Power HAL 1.3. + // Power HAL 1.0 is always available, thus if we fail to query it, it means + // Power HAL is not available temporarily and we should retry later. However, + // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3, + // it means Power HAL 1.3 is not available at all, so we should stop trying. + if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) { + sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService(); + if (powerHal_1_0 != nullptr) { + // Try to cast to Power HAL 1.3 + sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0); + if (sPowerHal_1_3 == nullptr) { + ALOGW("No Power HAL 1.3 service in system"); + sHasPowerHal_1_3 = false; + } else { + ALOGI("Loaded Power HAL 1.3 service"); + } + } + } + return sPowerHal_1_3; +} + +} // namespace impl +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h new file mode 100644 index 0000000000..573a1a9ad3 --- /dev/null +++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h @@ -0,0 +1,63 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include <hardware/hwcomposer2.h> +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +#include <android/hardware/power/1.3/IPower.h> +#include <utils/StrongPointer.h> + +#include <unordered_set> + +namespace android { +namespace Hwc2 { + +class PowerAdvisor { +public: + virtual ~PowerAdvisor(); + + virtual void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) = 0; +}; + +namespace impl { + +namespace V1_3 = android::hardware::power::V1_3; + +// PowerAdvisor is a wrapper around IPower HAL which takes into account the +// full state of the system when sending out power hints to things like the GPU. +class PowerAdvisor final : public Hwc2::PowerAdvisor { +public: + PowerAdvisor(); + ~PowerAdvisor() override; + + void setExpensiveRenderingExpected(hwc2_display_t displayId, bool expected) override; + +private: + sp<V1_3::IPower> getPowerHal(); + + std::unordered_set<hwc2_display_t> mExpensiveDisplays; + bool mNotifiedExpensiveRendering = false; + bool mReconnectPowerHal = false; +}; + +} // namespace impl +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2595ec1a05..a14bb98d8d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -130,17 +130,26 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& n // drawing state & current state are identical mDrawingState = mCurrentState; - const auto& hwc = flinger->getHwComposer(); - const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); - nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); - mFrameTracker.setDisplayRefreshPeriod(displayPeriod); - CompositorTiming compositorTiming; flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); } -void Layer::onFirstRef() {} +void Layer::onFirstRef() NO_THREAD_SAFETY_ANALYSIS { + if (!isCreatedFromMainThread()) { + // Grab the SF state lock during this since it's the only way to safely access HWC + mFlinger->mStateLock.lock(); + } + + const auto& hwc = mFlinger->getHwComposer(); + const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY); + nsecs_t displayPeriod = activeConfig->getVsyncPeriod(); + mFrameTracker.setDisplayRefreshPeriod(displayPeriod); + + if (!isCreatedFromMainThread()) { + mFlinger->mStateLock.unlock(); + } +} Layer::~Layer() { sp<Client> c(mClientRef.promote()); @@ -345,20 +354,25 @@ FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { win.intersect(s.crop, &win); } - Rect bounds = win; const auto& p = mDrawingParent.promote(); + FloatRect floatWin = win.toFloatRect(); + FloatRect parentBounds = floatWin; if (p != nullptr) { - // Look in computeScreenBounds recursive call for explanation of - // why we pass false here. - bounds = p->computeScreenBounds(false /* reduceTransparentRegion */); + // We pass an empty Region here for reasons mirroring that of the case described in + // the computeScreenBounds reduceTransparentRegion=false case. + parentBounds = p->computeBounds(Region()); } - Transform t = getTransform(); + Transform t = s.active.transform; - FloatRect floatWin = win.toFloatRect(); - if (p != nullptr) { + + if (p != nullptr || !s.finalCrop.isEmpty()) { floatWin = t.transform(floatWin); - floatWin = floatWin.intersect(bounds.toFloatRect()); + floatWin = floatWin.intersect(parentBounds); + + if (!s.finalCrop.isEmpty()) { + floatWin = floatWin.intersect(s.finalCrop.toFloatRect()); + } floatWin = t.inverse().transform(floatWin); } @@ -1249,7 +1263,15 @@ bool Layer::setColor(const half3& color) { return true; } -bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { +bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored"); + return false; + } mCurrentState.sequence++; mCurrentState.requested.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); mCurrentState.modified = true; @@ -1974,6 +1996,16 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_window_type(state.type); layerInfo->set_app_id(state.appId); + layerInfo->set_curr_frame(mCurrentFrameNumber); + + for (const auto& pendingState : mPendingStates) { + auto barrierLayer = pendingState.barrierLayer.promote(); + if (barrierLayer != nullptr) { + BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); + barrierLayerProto->set_id(barrierLayer->sequence); + barrierLayerProto->set_frame_number(pendingState.frameNumber); + } + } } void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 34811fb152..22396796ed 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -258,7 +258,7 @@ public: // Set a 2x2 transformation matrix on the layer. This transform // will be applied after parent transforms, but before any final // producer specified transform. - bool setMatrix(const layer_state_t::matrix22_t& matrix); + bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms); // This second set of geometry attributes are controlled by // setGeometryAppliesWithResize, and their default mode is to be @@ -360,6 +360,11 @@ public: */ virtual bool isFixedSize() const { return true; } + // Most layers aren't created from the main thread, and therefore need to + // grab the SF state lock to access HWC, but ContainerLayer does, so we need + // to avoid grabbing the lock again to avoid deadlock + virtual bool isCreatedFromMainThread() const { return false; } + bool isPendingRemoval() const { return mPendingRemoval; } diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp index 09414fd56d..c218e4da50 100644 --- a/services/surfaceflinger/RenderEngine/Description.cpp +++ b/services/surfaceflinger/RenderEngine/Description.cpp @@ -51,10 +51,6 @@ void Description::setProjectionMatrix(const mat4& mtx) { mProjectionMatrix = mtx; } -void Description::setSaturationMatrix(const mat4& mtx) { - mSaturationMatrix = mtx; -} - void Description::setColorMatrix(const mat4& mtx) { mColorMatrix = mtx; } @@ -82,11 +78,6 @@ bool Description::hasColorMatrix() const { return mColorMatrix != identity; } -bool Description::hasSaturationMatrix() const { - const mat4 identity; - return mSaturationMatrix != identity; -} - const mat4& Description::getColorMatrix() const { return mColorMatrix; } diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h index 06eaf35125..6ebb34018d 100644 --- a/services/surfaceflinger/RenderEngine/Description.h +++ b/services/surfaceflinger/RenderEngine/Description.h @@ -42,14 +42,12 @@ public: void disableTexture(); void setColor(const half4& color); void setProjectionMatrix(const mat4& mtx); - void setSaturationMatrix(const mat4& mtx); void setColorMatrix(const mat4& mtx); void setInputTransformMatrix(const mat3& matrix); void setOutputTransformMatrix(const mat4& matrix); bool hasInputTransformMatrix() const; bool hasOutputTransformMatrix() const; bool hasColorMatrix() const; - bool hasSaturationMatrix() const; const mat4& getColorMatrix() const; void setY410BT2020(bool enable); @@ -92,7 +90,6 @@ private: // projection matrix mat4 mProjectionMatrix; mat4 mColorMatrix; - mat4 mSaturationMatrix; mat3 mInputTransformMatrix; mat4 mOutputTransformMatrix; }; diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp index 0048000847..744a70c66c 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp @@ -267,10 +267,6 @@ void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) { mState.setColorMatrix(colorTransform); } -void GLES20RenderEngine::setSaturationMatrix(const mat4& saturationMatrix) { - mState.setSaturationMatrix(saturationMatrix); -} - void GLES20RenderEngine::disableTexturing() { mState.disableTexture(); } @@ -383,11 +379,10 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { // we need to convert the RGB value to linear space and convert it back when: // - there is a color matrix that is not an identity matrix, or - // - there is a saturation matrix that is not an identity matrix, or // - there is an output transform matrix that is not an identity matrix, or // - the input transfer function doesn't match the output transfer function. - if (wideColorState.hasColorMatrix() || wideColorState.hasSaturationMatrix() || - wideColorState.hasOutputTransformMatrix() || inputTransfer != outputTransfer) { + if (wideColorState.hasColorMatrix() || wideColorState.hasOutputTransformMatrix() || + inputTransfer != outputTransfer) { switch (inputTransfer) { case Dataspace::TRANSFER_ST2084: wideColorState.setInputTransferFunction(Description::TransferFunction::ST2084); diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h index de5761b9b0..cc8eb1dfab 100644 --- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h @@ -81,7 +81,6 @@ protected: virtual void setupLayerBlackedOut(); virtual void setupFillWithColor(float r, float g, float b, float a); virtual void setupColorTransform(const mat4& colorTransform); - virtual void setSaturationMatrix(const mat4& saturationMatrix); virtual void disableTexturing(); virtual void disableBlending(); diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp index 95adaca73b..fe536f0c7c 100644 --- a/services/surfaceflinger/RenderEngine/Program.cpp +++ b/services/surfaceflinger/RenderEngine/Program.cpp @@ -135,22 +135,13 @@ void Program::setUniforms(const Description& desc) { glUniform4fv(mColorLoc, 1, color); } if (mInputTransformMatrixLoc >= 0) { - // If the input transform matrix is not identity matrix, we want to merge - // the saturation matrix with input transform matrix so that the saturation - // matrix is applied at the correct stage. - mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix) * desc.mSaturationMatrix; + mat4 inputTransformMatrix = mat4(desc.mInputTransformMatrix); glUniformMatrix4fv(mInputTransformMatrixLoc, 1, GL_FALSE, inputTransformMatrix.asArray()); } if (mOutputTransformMatrixLoc >= 0) { // The output transform matrix and color matrix can be combined as one matrix // that is applied right before applying OETF. mat4 outputTransformMatrix = desc.mColorMatrix * desc.mOutputTransformMatrix; - // If there is no input transform matrix, we want to merge the saturation - // matrix with output transform matrix to avoid extra matrix multiplication - // in shader. - if (mInputTransformMatrixLoc < 0) { - outputTransformMatrix *= desc.mSaturationMatrix; - } glUniformMatrix4fv(mOutputTransformMatrixLoc, 1, GL_FALSE, outputTransformMatrix.asArray()); } diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp index 796901a2bd..9dc6858566 100644 --- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp +++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp @@ -149,8 +149,7 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) { description.hasInputTransformMatrix() ? Key::INPUT_TRANSFORM_MATRIX_ON : Key::INPUT_TRANSFORM_MATRIX_OFF) .set(Key::Key::OUTPUT_TRANSFORM_MATRIX_MASK, - description.hasOutputTransformMatrix() || description.hasColorMatrix() || - (!description.hasInputTransformMatrix() && description.hasSaturationMatrix()) ? + description.hasOutputTransformMatrix() || description.hasColorMatrix() ? Key::OUTPUT_TRANSFORM_MATRIX_ON : Key::OUTPUT_TRANSFORM_MATRIX_OFF); needs.set(Key::Y410_BT2020_MASK, diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h index 1196216cbf..1786155486 100644 --- a/services/surfaceflinger/RenderEngine/RenderEngine.h +++ b/services/surfaceflinger/RenderEngine/RenderEngine.h @@ -113,7 +113,6 @@ public: virtual void setupFillWithColor(float r, float g, float b, float a) = 0; virtual void setupColorTransform(const mat4& /* colorTransform */) = 0; - virtual void setSaturationMatrix(const mat4& /* saturationMatrix */) = 0; virtual void disableTexturing() = 0; virtual void disableBlending() = 0; @@ -228,7 +227,6 @@ public: void checkErrors() const override; void setupColorTransform(const mat4& /* colorTransform */) override {} - void setSaturationMatrix(const mat4& /* saturationMatrix */) override {} // internal to RenderEngine EGLDisplay getEGLDisplay() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 87baf8c8a8..28b447f7aa 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -37,6 +37,7 @@ #include <dvr/vr_flinger.h> +#include <ui/ColorSpace.h> #include <ui/DebugUtils.h> #include <ui/DisplayInfo.h> #include <ui/DisplayStatInfo.h> @@ -222,6 +223,7 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mVisibleRegionsDirty(false), mGeometryInvalid(false), mAnimCompositionPending(false), + mBootStage(BootStage::BOOTLOADER), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), @@ -230,7 +232,6 @@ SurfaceFlinger::SurfaceFlinger(SurfaceFlinger::SkipInitializationTag) mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), - mBootFinished(false), mForceFullDamage(false), mPrimaryDispSync("PrimaryDispSync"), mPrimaryHWVsyncEnabled(false), @@ -331,11 +332,26 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; - property_get("debug.sf.early_phase_offset_ns", value, "0"); - const int earlyWakeupOffsetOffsetNs = atoi(value); - ALOGI_IF(earlyWakeupOffsetOffsetNs != 0, "Enabling separate early offset"); - mVsyncModulator.setPhaseOffsets(sfVsyncPhaseOffsetNs - earlyWakeupOffsetOffsetNs, - sfVsyncPhaseOffsetNs); + property_get("debug.sf.early_phase_offset_ns", value, "-1"); + const int earlySfOffsetNs = atoi(value); + + property_get("debug.sf.early_gl_phase_offset_ns", value, "-1"); + const int earlyGlSfOffsetNs = atoi(value); + + property_get("debug.sf.early_app_phase_offset_ns", value, "-1"); + const int earlyAppOffsetNs = atoi(value); + + property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1"); + const int earlyGlAppOffsetNs = atoi(value); + + const VSyncModulator::Offsets earlyOffsets = + {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs, + earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs}; + const VSyncModulator::Offsets earlyGlOffsets = + {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs, + earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs}; + mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets, + {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}); // We should be reading 'persist.sys.sf.color_saturation' here // but since /data may be encrypted, we need to wait until after vold @@ -482,10 +498,32 @@ void SurfaceFlinger::bootFinished() sp<LambdaMessage> readProperties = new LambdaMessage([&]() { readPersistentProperties(); + mBootStage = BootStage::FINISHED; }); postMessageAsync(readProperties); } +uint32_t SurfaceFlinger::getNewTexture() { + { + std::lock_guard lock(mTexturePoolMutex); + if (!mTexturePool.empty()) { + uint32_t name = mTexturePool.back(); + mTexturePool.pop_back(); + ATRACE_INT("TexturePoolSize", mTexturePool.size()); + return name; + } + + // The pool was too small, so increase it for the future + ++mTexturePoolSize; + } + + // The pool was empty, so we need to get a new texture name directly using a + // blocking call to the main thread + uint32_t name = 0; + postMessageSync(new LambdaMessage([&]() { getRenderEngine().genTextures(1, &name); })); + return name; +} + void SurfaceFlinger::deleteTextureAsync(uint32_t texture) { class MessageDestroyGLTexture : public MessageBase { RE::RenderEngine& engine; @@ -662,7 +700,7 @@ void SurfaceFlinger::init() { }, "sfEventThread"); mEventQueue->setEventThread(mSFEventThread.get()); - mVsyncModulator.setEventThread(mSFEventThread.get()); + mVsyncModulator.setEventThreads(mSFEventThread.get(), mEventThread.get()); // Get a RenderEngine for the given display / config (can't fail) getBE().mRenderEngine = @@ -732,9 +770,24 @@ void SurfaceFlinger::init() { ALOGE("Run StartPropertySetThread failed!"); } - mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY, + // This is a hack. Per definition of getDataspaceSaturationMatrix, the returned matrix + // is used to saturate legacy sRGB content. However, to make sure the same color under + // Display P3 will be saturated to the same color, we intentionally break the API spec + // and apply this saturation matrix on Display P3 content. Unless the risk of applying + // such saturation matrix on Display P3 is understood fully, the API should always return + // identify matrix. + mEnhancedSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY, Dataspace::SRGB_LINEAR); + // we will apply this on Display P3. + if (mEnhancedSaturationMatrix != mat4()) { + ColorSpace srgb(ColorSpace::sRGB()); + ColorSpace displayP3(ColorSpace::DisplayP3()); + mat4 srgbToP3 = mat4(ColorSpaceConnector(srgb, displayP3).getTransform()); + mat4 p3ToSrgb = mat4(ColorSpaceConnector(displayP3, srgb).getTransform()); + mEnhancedSaturationMatrix = srgbToP3 * mEnhancedSaturationMatrix * p3ToSrgb; + } + ALOGV("Done initializing"); } @@ -928,6 +981,21 @@ status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */, return NO_ERROR; } +status_t SurfaceFlinger::getDisplayViewport(const sp<IBinder>& display, Rect* outViewport) { + if (outViewport == nullptr || display.get() == nullptr) { + return BAD_VALUE; + } + + sp<const DisplayDevice> device(getDisplayDevice(display)); + if (device == nullptr) { + return BAD_VALUE; + } + + *outViewport = device->getViewport(); + + return NO_ERROR; +} + int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) { if (display == nullptr) { ALOGE("%s : display is nullptr", __func__); @@ -1496,7 +1564,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); refreshNeeded |= mRepaintEverything; - if (refreshNeeded) { + if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint @@ -1809,6 +1877,17 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime) getBE().mTotalTime += elapsedTime; } getBE().mLastSwapTime = currentTime; + + { + std::lock_guard lock(mTexturePoolMutex); + const size_t refillCount = mTexturePoolSize - mTexturePool.size(); + if (refillCount > 0) { + const size_t offset = mTexturePool.size(); + mTexturePool.resize(mTexturePoolSize); + getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset); + ATRACE_INT("TexturePoolSize", mTexturePool.size()); + } + } } void SurfaceFlinger::rebuildLayerStacks() { @@ -2116,11 +2195,15 @@ void SurfaceFlinger::postFramebuffer() displayDevice->onSwapBuffersCompleted(); displayDevice->makeCurrent(); for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { + sp<Fence> releaseFence = Fence::NO_FENCE; + // The layer buffer from the previous frame (if any) is released // by HWC only when the release fence from this frame (if any) is // signaled. Always get the release fence from HWC first. auto hwcLayer = layer->getHwcLayer(hwcId); - sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + if (hwcId >= 0) { + releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer); + } // If the layer was client composited in the previous frame, we // need to merge with the previous client target acquire fence. @@ -2267,8 +2350,10 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) { bool hasWideColorGamut = false; std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes; + HdrCapabilities hdrCapabilities; + int32_t supportedPerFrameMetadata = 0; - if (hasWideColorDisplay) { + if (hasWideColorDisplay && hwcId >= 0) { std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId); for (ColorMode colorMode : modes) { switch (colorMode) { @@ -2287,8 +2372,10 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( } } - HdrCapabilities hdrCapabilities; - getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + if (hwcId >= 0) { + getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities); + supportedPerFrameMetadata = getHwComposer().getSupportedPerFrameMetadata(hwcId); + } auto nativeWindowSurface = mCreateNativeWindowSurface(producer); auto nativeWindow = nativeWindowSurface->getNativeWindow(); @@ -2322,8 +2409,7 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow, dispSurface, std::move(renderSurface), displayWidth, displayHeight, hasWideColorGamut, hdrCapabilities, - getHwComposer().getSupportedPerFrameMetadata(hwcId), - hwcColorModes, initialPowerMode); + supportedPerFrameMetadata, hwcColorModes, initialPowerMode); if (maxFrameBufferAcquiredBuffers >= 3) { nativeWindowSurface->preallocateBuffers(); @@ -2855,6 +2941,12 @@ bool SurfaceFlinger::handlePageFlip() signalLayerUpdate(); } + // enter boot animation on first buffer latch + if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) { + ALOGI("Enter boot animation"); + mBootStage = BootStage::BOOTANIMATION; + } + // Only continue with the refresh if there is actually new work to do return !mLayersWithQueuedFrames.empty() && newDataLatched; } @@ -2897,8 +2989,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev ATRACE_INT("hasClientComposition", hasClientComposition); bool applyColorMatrix = false; - bool needsLegacyColorMatrix = false; - bool legacyColorMatrixApplied = false; + bool needsEnhancedColorMatrix = false; if (hasClientComposition) { ALOGV("hasClientComposition"); @@ -2915,15 +3006,23 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev const bool skipClientColorTransform = getBE().mHwc->hasCapability( HWC2::Capability::SkipClientColorTransform); + mat4 colorMatrix; applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; if (applyColorMatrix) { - getRenderEngine().setupColorTransform(mDrawingState.colorMatrix); + colorMatrix = mDrawingState.colorMatrix; } - needsLegacyColorMatrix = + // The current enhanced saturation matrix is designed to enhance Display P3, + // thus we only apply this matrix when the render intent is not colorimetric + // and the output color space is Display P3. + needsEnhancedColorMatrix = (displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE && - outputDataspace != Dataspace::UNKNOWN && - outputDataspace != Dataspace::SRGB); + outputDataspace == Dataspace::DISPLAY_P3); + if (needsEnhancedColorMatrix) { + colorMatrix *= mEnhancedSaturationMatrix; + } + + getRenderEngine().setupColorTransform(colorMatrix); if (!displayDevice->makeCurrent()) { ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s", @@ -2961,22 +3060,17 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev } } - if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) { - // just to be on the safe side, we don't set the - // scissor on the main display. It should never be needed - // anyways (though in theory it could since the API allows it). - const Rect& bounds(displayDevice->getBounds()); - const Rect& scissor(displayDevice->getScissor()); - if (scissor != bounds) { - // scissor doesn't match the screen's dimensions, so we - // need to clear everything outside of it and enable - // the GL scissor so we don't draw anything where we shouldn't - - // enable scissor for this frame - const uint32_t height = displayDevice->getHeight(); - getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, - scissor.getWidth(), scissor.getHeight()); - } + const Rect& bounds(displayDevice->getBounds()); + const Rect& scissor(displayDevice->getScissor()); + if (scissor != bounds) { + // scissor doesn't match the screen's dimensions, so we + // need to clear everything outside of it and enable + // the GL scissor so we don't draw anything where we shouldn't + + // enable scissor for this frame + const uint32_t height = displayDevice->getHeight(); + getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom, + scissor.getWidth(), scissor.getHeight()); } } @@ -3010,17 +3104,6 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev break; } case HWC2::Composition::Client: { - // switch color matrices lazily - if (layer->isLegacyDataSpace() && needsLegacyColorMatrix) { - if (!legacyColorMatrixApplied) { - getRenderEngine().setSaturationMatrix(mLegacySrgbSaturationMatrix); - legacyColorMatrixApplied = true; - } - } else if (legacyColorMatrixApplied) { - getRenderEngine().setSaturationMatrix(mat4()); - legacyColorMatrixApplied = false; - } - layer->draw(renderArea, clip); break; } @@ -3033,12 +3116,9 @@ bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDev firstLayer = false; } - if (applyColorMatrix) { + if (applyColorMatrix || needsEnhancedColorMatrix) { getRenderEngine().setupColorTransform(mat4()); } - if (needsLegacyColorMatrix && legacyColorMatrixApplied) { - getRenderEngine().setSaturationMatrix(mat4()); - } // disable scissor at the end of the frame getBE().mRenderEngine->disableScissor(); @@ -3327,6 +3407,18 @@ uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) return flags; } +bool callingThreadHasUnscopedSurfaceFlingerAccess() { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + + if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) && + !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) { + return false; + } + return true; +} + uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState) { const layer_state_t& s = composerState.state; sp<Client> client(static_cast<Client*>(composerState.client.get())); @@ -3408,7 +3500,22 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState flags |= eTraversalNeeded; } if (what & layer_state_t::eMatrixChanged) { - if (layer->setMatrix(s.matrix)) + // TODO: b/109894387 + // + // SurfaceFlinger's renderer is not prepared to handle cropping in the face of arbitrary + // rotation. To see the problem observe that if we have a square parent, and a child + // of the same size, then we rotate the child 45 degrees around it's center, the child + // must now be cropped to a non rectangular 8 sided region. + // + // Of course we can fix this in the future. For now, we are lucky, SurfaceControl is + // private API, and the WindowManager only uses rotation in one case, which is on a top + // level layer in which cropping is not an issue. + // + // However given that abuse of rotation matrices could lead to surfaces extending outside + // of cropped areas, we need to prevent non-root clients without permission ACCESS_SURFACE_FLINGER + // (a.k.a. everyone except WindowManager and tests) from setting non rectangle preserving + // transformations. + if (layer->setMatrix(s.matrix, callingThreadHasUnscopedSurfaceFlingerAccess())) flags |= eTraversalNeeded; } if (what & layer_state_t::eTransparentRegionChanged) { @@ -3574,10 +3681,13 @@ String8 SurfaceFlinger::getUniqueLayerName(const String8& name) // Tack on our counter whether there is a hit or not, so everyone gets a tag String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str()); + // Grab the state lock since we're accessing mCurrentState + Mutex::Autolock lock(mStateLock); + // Loop over layers until we're sure there is no matching name while (matchFound) { matchFound = false; - mDrawingState.traverseInZOrder([&](Layer* layer) { + mCurrentState.traverseInZOrder([&](Layer* layer) { if (layer->getName() == uniqueName) { matchFound = true; uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str()); @@ -4207,9 +4317,22 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, colorizer.bold(result); result.append("DispSync configuration: "); colorizer.reset(result); - result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, early sf phase %" PRId64 - " ns, present offset %" PRId64 " ns (refresh %" PRId64 " ns)", - vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, mVsyncModulator.getEarlyPhaseOffset(), + const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets(); + const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets(); + result.appendFormat( + "app phase %" PRId64 " ns, " + "sf phase %" PRId64 " ns, " + "early app phase %" PRId64 " ns, " + "early sf phase %" PRId64 " ns, " + "early app gl phase %" PRId64 " ns, " + "early sf gl phase %" PRId64 " ns, " + "present offset %" PRId64 " ns (refresh %" PRId64 " ns)", + vsyncPhaseOffsetNs, + sfVsyncPhaseOffsetNs, + appEarlyOffset, + sfEarlyOffset, + appEarlyGlOffset, + sfEarlyOffset, dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod()); result.append("\n"); @@ -4412,12 +4535,10 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { case INJECT_VSYNC: { // codes that require permission check - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) && - !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) { - ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", pid, uid); + if (!callingThreadHasUnscopedSurfaceFlingerAccess()) { + IPCThreadState* ipc = IPCThreadState::self(); + ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d", + ipc->getCallingPid(), ipc->getCallingUid()); return PERMISSION_DENIED; } break; @@ -4717,6 +4838,16 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuf const sp<const DisplayDevice> device(getDisplayDeviceLocked(display)); if (CC_UNLIKELY(device == 0)) return BAD_VALUE; + const Rect& dispScissor = device->getScissor(); + if (!dispScissor.isEmpty()) { + sourceCrop.set(dispScissor); + // adb shell screencap will default reqWidth and reqHeight to zeros. + if (reqWidth == 0 || reqHeight == 0) { + reqWidth = uint32_t(device->getViewport().width()); + reqHeight = uint32_t(device->getViewport().height()); + } + } + DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8566b0387c..0148ab6754 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -320,6 +320,10 @@ public: return getDefaultDisplayDeviceLocked(); } + // Obtains a name from the texture pool, or, if the pool is empty, posts a + // synchronous message to the main thread to obtain one on the fly + uint32_t getNewTexture(); + // utility function to delete a texture on the main thread void deleteTextureAsync(uint32_t texture); @@ -425,6 +429,7 @@ private: const Rect& sourceCrop, float frameScale, bool childrenOnly); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); + virtual status_t getDisplayViewport(const sp<IBinder>& display, Rect* outViewport); virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayInfo>* configs); virtual int getActiveConfig(const sp<IBinder>& display); @@ -808,6 +813,13 @@ private: sp<Fence> mPreviousPresentFence = Fence::NO_FENCE; bool mHadClientComposition = false; + enum class BootStage { + BOOTLOADER, + BOOTANIMATION, + FINISHED, + }; + BootStage mBootStage; + struct HotplugEvent { hwc2_display_t display; HWC2::Connection connection = HWC2::Connection::Invalid; @@ -828,7 +840,6 @@ private: nsecs_t mLastSwapBufferTime; volatile nsecs_t mDebugInTransaction; nsecs_t mLastTransactionTime; - bool mBootFinished; bool mForceFullDamage; bool mPropagateBackpressure = true; std::unique_ptr<SurfaceInterceptor> mInterceptor = @@ -858,6 +869,13 @@ private: std::atomic<bool> mRefreshPending{false}; + // We maintain a pool of pre-generated texture names to hand out to avoid + // layer creation needing to run on the main thread (which it would + // otherwise need to do to access RenderEngine). + std::mutex mTexturePoolMutex; + uint32_t mTexturePoolSize = 0; + std::vector<uint32_t> mTexturePool; + /* ------------------------------------------------------------------------ * Feature prototyping */ @@ -878,9 +896,9 @@ private: static bool useVrFlinger; std::thread::id mMainThreadId; - DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED; - // Applied on sRGB layers when the render intent is non-colorimetric. - mat4 mLegacySrgbSaturationMatrix; + DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::ENHANCED; + // Applied on Display P3 layers when the render intent is non-colorimetric. + mat4 mEnhancedSaturationMatrix; using CreateBufferQueueFunction = std::function<void(sp<IGraphicBufferProducer>* /* outProducer */, diff --git a/services/surfaceflinger/VSyncModulator.h b/services/surfaceflinger/VSyncModulator.h index d526313994..e071a599c9 100644 --- a/services/surfaceflinger/VSyncModulator.h +++ b/services/surfaceflinger/VSyncModulator.h @@ -36,6 +36,11 @@ private: public: + struct Offsets { + nsecs_t sf; + nsecs_t app; + }; + enum TransactionStart { EARLY, NORMAL @@ -43,21 +48,32 @@ public: // Sets the phase offsets // - // early: the phase offset when waking up early. May be the same as late, in which case we don't - // shift offsets. - // late: the regular sf phase offset. - void setPhaseOffsets(nsecs_t early, nsecs_t late) { - mEarlyPhaseOffset = early; - mLatePhaseOffset = late; - mPhaseOffset = late; + // sfEarly: The phase offset when waking up SF early, which happens when marking a transaction + // as early. May be the same as late, in which case we don't shift offsets. + // sfEarlyGl: Like sfEarly, but only if we used GL composition. If we use both GL composition + // and the transaction was marked as early, we'll use sfEarly. + // sfLate: The regular SF vsync phase offset. + // appEarly: Like sfEarly, but for the app-vsync + // appEarlyGl: Like sfEarlyGl, but for the app-vsync. + // appLate: The regular app vsync phase offset. + void setPhaseOffsets(Offsets early, Offsets earlyGl, Offsets late) { + mEarlyOffsets = early; + mEarlyGlOffsets = earlyGl; + mLateOffsets = late; + mOffsets = late; + } + + Offsets getEarlyOffsets() const { + return mEarlyOffsets; } - nsecs_t getEarlyPhaseOffset() const { - return mEarlyPhaseOffset; + Offsets getEarlyGlOffsets() const { + return mEarlyGlOffsets; } - void setEventThread(EventThread* eventThread) { - mEventThread = eventThread; + void setEventThreads(EventThread* sfEventThread, EventThread* appEventThread) { + mSfEventThread = sfEventThread; + mAppEventThread = appEventThread; } void setTransactionStart(TransactionStart transactionStart) { @@ -71,63 +87,70 @@ public: return; } mTransactionStart = transactionStart; - updatePhaseOffsets(); + updateOffsets(); } void onTransactionHandled() { if (mTransactionStart == TransactionStart::NORMAL) return; mTransactionStart = TransactionStart::NORMAL; - updatePhaseOffsets(); + updateOffsets(); } void onRefreshed(bool usedRenderEngine) { - bool updatePhaseOffsetsNeeded = false; + bool updateOffsetsNeeded = false; if (mRemainingEarlyFrameCount > 0) { mRemainingEarlyFrameCount--; - updatePhaseOffsetsNeeded = true; + updateOffsetsNeeded = true; } if (usedRenderEngine != mLastFrameUsedRenderEngine) { mLastFrameUsedRenderEngine = usedRenderEngine; - updatePhaseOffsetsNeeded = true; + updateOffsetsNeeded = true; } - if (updatePhaseOffsetsNeeded) { - updatePhaseOffsets(); + if (updateOffsetsNeeded) { + updateOffsets(); } } private: - void updatePhaseOffsets() { + void updateOffsets() { + const Offsets desired = getOffsets(); + const Offsets current = mOffsets; + + bool changed = false; + if (desired.sf != current.sf) { + mSfEventThread->setPhaseOffset(desired.sf); + changed = true; + } + if (desired.app != current.app) { + mAppEventThread->setPhaseOffset(desired.app); + changed = true; + } - // Do not change phase offsets if disabled. - if (mEarlyPhaseOffset == mLatePhaseOffset) return; + if (changed) { + mOffsets = desired; + } + } - if (shouldUseEarlyOffset()) { - if (mPhaseOffset != mEarlyPhaseOffset) { - if (mEventThread) { - mEventThread->setPhaseOffset(mEarlyPhaseOffset); - } - mPhaseOffset = mEarlyPhaseOffset; - } + Offsets getOffsets() { + if (mTransactionStart == TransactionStart::EARLY || mRemainingEarlyFrameCount > 0) { + return mEarlyOffsets; + } else if (mLastFrameUsedRenderEngine) { + return mEarlyGlOffsets; } else { - if (mPhaseOffset != mLatePhaseOffset) { - if (mEventThread) { - mEventThread->setPhaseOffset(mLatePhaseOffset); - } - mPhaseOffset = mLatePhaseOffset; - } + return mLateOffsets; } } - bool shouldUseEarlyOffset() { - return mTransactionStart == TransactionStart::EARLY || mLastFrameUsedRenderEngine - || mRemainingEarlyFrameCount > 0; - } + Offsets mLateOffsets; + Offsets mEarlyOffsets; + Offsets mEarlyGlOffsets; + + EventThread* mSfEventThread = nullptr; + EventThread* mAppEventThread = nullptr; + + std::atomic<Offsets> mOffsets; - nsecs_t mLatePhaseOffset = 0; - nsecs_t mEarlyPhaseOffset = 0; - EventThread* mEventThread = nullptr; - std::atomic<nsecs_t> mPhaseOffset = 0; std::atomic<TransactionStart> mTransactionStart = TransactionStart::NORMAL; std::atomic<bool> mLastFrameUsedRenderEngine = false; std::atomic<int> mRemainingEarlyFrameCount = 0; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index 77c6675b7f..edf56abc4a 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -80,6 +80,10 @@ message LayerProto { optional int32 hwc_composition_type = 35; // If it's a buffer layer, indicate if the content is protected optional bool is_protected = 36; + // Current frame number being rendered. + optional uint64 curr_frame = 37; + // A list of barriers that the layer is waiting to update state. + repeated BarrierLayerProto barrier_layer = 38; } message PositionProto { @@ -131,3 +135,10 @@ message ColorProto { optional float b = 3; optional float a = 4; } + +message BarrierLayerProto { + // layer id the barrier is waiting on. + optional int32 id = 1; + // frame number the barrier is waiting on. + optional uint64 frame_number = 2; +} diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index 8255b41596..b1ff522de6 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -102,7 +102,7 @@ int main(int, char**) { // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false, - IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); + IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO); // publish GpuService sp<GpuService> gpuservice = new GpuService(); diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 520df2d63f..5fa8a09bab 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -12,6 +12,7 @@ cc_test { shared_libs: [ "android.hardware.graphics.composer@2.1", "android.hardware.graphics.mapper@2.0", + "android.hardware.power@1.3", "libbase", "libbinder", "libcutils", diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 39761dd9ad..4a92780521 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -24,6 +24,7 @@ cc_test { "EventThreadTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplaySurface.cpp", + "mock/DisplayHardware/MockPowerAdvisor.cpp", "mock/gui/MockGraphicBufferConsumer.cpp", "mock/gui/MockGraphicBufferProducer.cpp", "mock/MockEventControlThread.cpp", diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 9b308bfcc8..9ac5f3b73e 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -658,8 +658,7 @@ using NonHwcVirtualDisplayCase = using SimpleHwcVirtualDisplayVariant = HwcVirtualDisplayVariant<1024, 768, Secure::TRUE>; using HwcVirtualDisplayCase = Case<SimpleHwcVirtualDisplayVariant, WideColorSupportNotConfiguredVariant, - HdrNotSupportedVariant<SimpleHwcVirtualDisplayVariant>, - NoPerFrameMetadataSupportVariant<SimpleHwcVirtualDisplayVariant>>; + NonHwcDisplayHdrSupportVariant, NonHwcPerFrameMetadataSupportVariant>; using WideColorP3ColorimetricDisplayCase = Case<PrimaryDisplayVariant, WideColorP3ColorimetricSupportedVariant<PrimaryDisplayVariant>, HdrNotSupportedVariant<PrimaryDisplayVariant>, diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index f1556d8bc7..acd16fe650 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -149,12 +149,18 @@ public: * Wrapper classes for Read-write access to private data to set up * preconditions and assert post-conditions. */ + class FakePowerAdvisor : public Hwc2::PowerAdvisor { + public: + FakePowerAdvisor() = default; + ~FakePowerAdvisor() override = default; + void setExpensiveRenderingExpected(hwc2_display_t, bool) override { } + }; struct HWC2Display : public HWC2::Display { - HWC2Display(Hwc2::Composer& composer, + HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor, const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id, HWC2::DisplayType type) - : HWC2::Display(composer, capabilities, id, type) {} + : HWC2::Display(composer, advisor, capabilities, id, type) {} ~HWC2Display() { // Prevents a call to disable vsyncs. mType = HWC2::DisplayType::Invalid; @@ -217,8 +223,8 @@ public: } void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) { - auto display = std::make_unique<HWC2Display>(*composer, mCapabilities, mHwcDisplayId, - mHwcDisplayType); + auto display = std::make_unique<HWC2Display>(*composer, mPowerAdvisor, mCapabilities, + mHwcDisplayId, mHwcDisplayType); auto config = HWC2::Display::Config::Builder(*display, mActiveConfig); config.setWidth(mWidth); @@ -248,6 +254,7 @@ public: int32_t mDpiY = DEFAULT_DPI; int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; std::unordered_set<HWC2::Capability> mCapabilities; + FakePowerAdvisor mPowerAdvisor; }; class FakeDisplayDeviceInjector { diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp new file mode 100644 index 0000000000..8be707750b --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MockPowerAdvisor.h" + +namespace android { +namespace Hwc2 { +namespace mock { + +// Explicit default instantiation is recommended. +PowerAdvisor::PowerAdvisor() = default; +PowerAdvisor::~PowerAdvisor() = default; + +} // namespace mock +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h new file mode 100644 index 0000000000..dc6d83b0fd --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h @@ -0,0 +1,37 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <gmock/gmock.h> + +#include "DisplayHardware/PowerAdvisor.h" + +namespace android { +namespace Hwc2 { +namespace mock { + +class PowerAdvisor : public android::Hwc2::PowerAdvisor { +public: + PowerAdvisor(); + ~PowerAdvisor() override; + + MOCK_METHOD2(setExpensiveRenderingExpected, void(hwc2_display_t displayId, bool expected)); +}; + +} // namespace mock +} // namespace Hwc2 +} // namespace android |