From f527548dd751bd62b1302cf357fdb4840bc115a9 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 29 Jan 2019 18:42:42 -0800 Subject: SF: Move/Refactor Layer::setPerFrameData Moves functionality out of ColorLayer, BufferLayer, BufferStateLayer and BufferQueueLayer related to setting the per-frame data. Instead each of the front-end classes now implements a minimal function to set the per-frame state into the LayerFECompositionState structure. compositionengine::OutputLayer now takes care of sending the state to the HWC, and in particular with detecting when client composition needs to be forced due to lack of HWC support (though the front-end can also set a flag to force client composition for a few things it knows about). SurfaceFlinger::calculateWorkingSet is also refactored to work with the changes made, and prepare it to be moved over to CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Bug: 121291683 Change-Id: I2cb0442f68ec5c5f65f5b4cb418dda4c42e5dc39 --- services/surfaceflinger/BufferLayer.cpp | 91 ++++----------------------------- 1 file changed, 11 insertions(+), 80 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f51fbb45f6..c3b171847c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -253,90 +254,20 @@ bool BufferLayer::isHdrY410() const { mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::setPerFrameData(const sp& displayDevice, - const ui::Transform& transform, const Rect& viewport, - int32_t supportedPerFrameMetadata, - const ui::Dataspace targetDataspace) { - RETURN_IF_NO_HWC_LAYER(displayDevice); - - // Apply this display's projection's viewport to the visible region - // before giving it to the HWC HAL. - Region visible = transform.transform(visibleRegion.intersect(viewport)); - - const auto outputLayer = findOutputLayerForDisplay(displayDevice); - LOG_FATAL_IF(!outputLayer || !outputLayer->getState().hwc); - - auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer; - auto error = hwcLayer->setVisibleRegion(visible); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - visible.dump(LOG_TAG); - } - outputLayer->editState().visibleRegion = visible; - - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - - error = hwcLayer->setSurfaceDamage(surfaceDamageRegion); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - surfaceDamageRegion.dump(LOG_TAG); - } - layerCompositionState.surfaceDamage = surfaceDamageRegion; +void BufferLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + Layer::latchPerFrameState(compositionState); // Sideband layers - if (layerCompositionState.sidebandStream.get()) { - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::SIDEBAND); - ALOGV("[%s] Requesting Sideband composition", mName.string()); - error = hwcLayer->setSidebandStream(layerCompositionState.sidebandStream->handle()); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set sideband stream %p: %s (%d)", mName.string(), - layerCompositionState.sidebandStream->handle(), to_string(error).c_str(), - static_cast(error)); - } - layerCompositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; - return; - } - - // Device or Cursor layers - if (mPotentialCursor) { - ALOGV("[%s] Requesting Cursor composition", mName.string()); - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CURSOR); + if (compositionState.sidebandStream.get()) { + compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { - ALOGV("[%s] Requesting Device composition", mName.string()); - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::DEVICE); + // Normal buffer layers + compositionState.hdrMetadata = getDrawingHdrMetadata(); + compositionState.compositionType = mPotentialCursor + ? Hwc2::IComposerClient::Composition::CURSOR + : Hwc2::IComposerClient::Composition::DEVICE; } - - ui::Dataspace dataspace = isColorSpaceAgnostic() && targetDataspace != ui::Dataspace::UNKNOWN - ? targetDataspace - : mCurrentDataSpace; - error = hwcLayer->setDataspace(dataspace); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set dataspace %d: %s (%d)", mName.string(), dataspace, - to_string(error).c_str(), static_cast(error)); - } - - const HdrMetadata& metadata = getDrawingHdrMetadata(); - error = hwcLayer->setPerFrameMetadata(supportedPerFrameMetadata, metadata); - if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) { - ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - - error = hwcLayer->setColorTransform(getColorTransform()); - if (error == HWC2::Error::Unsupported) { - // If per layer color transform is not supported, we use GPU composition. - setCompositionType(displayDevice, Hwc2::IComposerClient::Composition::CLIENT); - } else if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to setColorTransform: %s (%d)", mName.string(), - to_string(error).c_str(), static_cast(error)); - } - layerCompositionState.dataspace = mCurrentDataSpace; - layerCompositionState.colorTransform = getColorTransform(); - layerCompositionState.hdrMetadata = metadata; - - setHwcLayerBuffer(displayDevice); } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { -- cgit v1.2.3-59-g8ed1b From a8955dd64c0c7fd355a7a3973403c3ba916d6f27 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Wed, 10 Jul 2019 10:19:09 -0700 Subject: SF: Factor out expected present time computation Compute expected present time once and pass it to traversed layers instead of calling back into SF for each layer. This will simplify synchronization for per-display refresh. Also, recompute on Binder transaction, since the cached value computed on invalidate may be stale. Bug: 130554049 Bug: 123715322 Test: go/wm-smoke Change-Id: I7153a728360e789dc4f97d2c39c4bdaa14183624 --- services/surfaceflinger/BufferLayer.cpp | 21 +++++++------ services/surfaceflinger/BufferLayer.h | 16 +++++----- services/surfaceflinger/BufferQueueLayer.cpp | 15 ++++----- services/surfaceflinger/BufferQueueLayer.h | 7 +++-- services/surfaceflinger/BufferStateLayer.cpp | 17 +++++----- services/surfaceflinger/BufferStateLayer.h | 7 +++-- services/surfaceflinger/Layer.h | 7 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 36 ++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 21 ++++++------- .../tests/unittests/CompositionTest.cpp | 2 +- 10 files changed, 81 insertions(+), 68 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f51fbb45f6..4cf37a4d30 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -395,7 +395,8 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, return true; } -bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { +bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) { ATRACE_CALL(); bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); @@ -430,12 +431,12 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) const bool oldOpacity = isOpaque(s); sp oldBuffer = mActiveBuffer; - if (!allTransactionsSignaled()) { + if (!allTransactionsSignaled(expectedPresentTime)) { mFlinger->setTransactionFlags(eTraversalNeeded); return false; } - status_t err = updateTexImage(recomputeVisibleRegions, latchTime); + status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime); if (err != NO_ERROR) { return false; } @@ -540,10 +541,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) } // transaction -void BufferLayer::notifyAvailableFrames() { - const auto headFrameNumber = getHeadFrameNumber(); +void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) { + const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); const bool headFenceSignaled = fenceHasSignaled(); - const bool presentTimeIsCurrent = framePresentTimeIsCurrent(); + const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime); Mutex::Autolock lock(mLocalSyncPointMutex); for (auto& point : mLocalSyncPoints) { if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled && @@ -591,8 +592,8 @@ bool BufferLayer::latchUnsignaledBuffers() { } // h/w composer set-up -bool BufferLayer::allTransactionsSignaled() { - auto headFrameNumber = getHeadFrameNumber(); +bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) { + const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); bool matchingFramesFound = false; bool allTransactionsApplied = true; Mutex::Autolock lock(mLocalSyncPointMutex); @@ -658,9 +659,9 @@ bool BufferLayer::needsFiltering(const sp& displayDevice) c sourceCrop.getWidth() != displayFrame.getWidth(); } -uint64_t BufferLayer::getHeadFrameNumber() const { +uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const { if (hasFrameUpdate()) { - return getFrameNumber(); + return getFrameNumber(expectedPresentTime); } else { return mCurrentFrameNumber; } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b679380b79..c793550625 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -96,11 +96,12 @@ public: // the visible regions need to be recomputed (this is a fairly heavy // operation, so this should be set only if needed). Typically this is used // to figure out if the content or size of a surface has changed. - bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; bool isBufferLatched() const override { return mRefreshPending; } - void notifyAvailableFrames() override; + void notifyAvailableFrames(nsecs_t expectedPresentTime) override; bool hasReadyFrame() const override; @@ -114,7 +115,7 @@ public: // ----------------------------------------------------------------------- private: virtual bool fenceHasSignaled() const = 0; - virtual bool framePresentTimeIsCurrent() const = 0; + virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; virtual nsecs_t getDesiredPresentTime() = 0; virtual std::shared_ptr getCurrentFenceTime() const = 0; @@ -129,7 +130,7 @@ private: virtual int getDrawingApi() const = 0; virtual PixelFormat getPixelFormat() const = 0; - virtual uint64_t getFrameNumber() const = 0; + virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; virtual bool getAutoRefresh() const = 0; virtual bool getSidebandStreamChanged() const = 0; @@ -142,7 +143,8 @@ private: virtual void setFilteringEnabled(bool enabled) = 0; virtual status_t bindTextureImage() = 0; - virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; + virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) = 0; virtual status_t updateActiveBuffer() = 0; virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; @@ -156,7 +158,7 @@ protected: // Check all of the local sync points to ensure that all transactions // which need to have been applied prior to the frame which is about to // be latched have signaled - bool allTransactionsSignaled(); + bool allTransactionsSignaled(nsecs_t expectedPresentTime); static bool getOpacityForFormat(uint32_t format); @@ -175,7 +177,7 @@ private: // Returns true if this layer requires filtering bool needsFiltering(const sp& displayDevice) const; - uint64_t getHeadFrameNumber() const; + uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d6853661a5..fe9edfe895 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -137,13 +137,13 @@ bool BufferQueueLayer::fenceHasSignaled() const { return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; } -bool BufferQueueLayer::framePresentTimeIsCurrent() const { +bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { if (!hasFrameUpdate() || isRemovedFromCurrentState()) { return true; } Mutex::Autolock lock(mQueueItemLock); - return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime(); + return mQueueItems[0].mTimestamp <= expectedPresentTime; } nsecs_t BufferQueueLayer::getDesiredPresentTime() { @@ -196,13 +196,11 @@ PixelFormat BufferQueueLayer::getPixelFormat() const { return mFormat; } -uint64_t BufferQueueLayer::getFrameNumber() const { +uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); uint64_t frameNumber = mQueueItems[0].mFrameNumber; // The head of the queue will be dropped if there are signaled and timely frames behind it - nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime(); - if (isRemovedFromCurrentState()) { expectedPresentTime = 0; } @@ -268,7 +266,8 @@ status_t BufferQueueLayer::bindTextureImage() { return mConsumer->bindTextureImage(); } -status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) { +status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) { // This boolean is used to make sure that SurfaceFlinger's shadow copy // of the buffer queue isn't modified when the buffer queue is returning // BufferItem's that weren't actually queued. This can happen in shared @@ -279,8 +278,6 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, getTransformToDisplayInverse(), mFreezeGeometryUpdates); - nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime(); - if (isRemovedFromCurrentState()) { expectedPresentTime = 0; } @@ -432,7 +429,7 @@ void BufferQueueLayer::setHwcLayerBuffer(const sp& display) void BufferQueueLayer::fakeVsync() { mRefreshPending = false; bool ignored = false; - latchBuffer(ignored, systemTime()); + latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); usleep(16000); releasePendingBuffer(systemTime()); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 7def33ad78..e60a083cff 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -61,7 +61,7 @@ public: // ----------------------------------------------------------------------- public: bool fenceHasSignaled() const override; - bool framePresentTimeIsCurrent() const override; + bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: nsecs_t getDesiredPresentTime() override; @@ -77,7 +77,7 @@ private: int getDrawingApi() const override; PixelFormat getPixelFormat() const override; - uint64_t getFrameNumber() const override; + uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; bool getSidebandStreamChanged() const override; @@ -89,7 +89,8 @@ private: void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() override; - status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4b01301467..06b2364bcf 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -216,7 +216,7 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime); + mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime); mDesiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -369,12 +369,12 @@ bool BufferStateLayer::fenceHasSignaled() const { return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; } -bool BufferStateLayer::framePresentTimeIsCurrent() const { +bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { if (!hasFrameUpdate() || isRemovedFromCurrentState()) { return true; } - return mDesiredPresentTime <= mFlinger->getExpectedPresentTime(); + return mDesiredPresentTime <= expectedPresentTime; } nsecs_t BufferStateLayer::getDesiredPresentTime() { @@ -446,7 +446,7 @@ PixelFormat BufferStateLayer::getPixelFormat() const { return mActiveBuffer->format; } -uint64_t BufferStateLayer::getFrameNumber() const { +uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mFrameNumber; } @@ -494,7 +494,8 @@ status_t BufferStateLayer::bindTextureImage() { return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence); } -status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) { +status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, + nsecs_t /*expectedPresentTime*/) { const State& s(getDrawingState()); if (!s.buffer) { @@ -528,7 +529,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber()); + mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); return BAD_VALUE; } @@ -550,8 +551,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } - mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime()); - mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime); + mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); + mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); mCurrentStateModified = false; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index db8ae0d337..18e8cfa481 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -100,7 +100,7 @@ public: // Interface implementation for BufferLayer // ----------------------------------------------------------------------- bool fenceHasSignaled() const override; - bool framePresentTimeIsCurrent() const override; + bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; // Inherit from ClientCache::ErasedRecipient void bufferErased(const client_cache_t& clientCacheId) override; @@ -119,7 +119,7 @@ private: int getDrawingApi() const override; PixelFormat getPixelFormat() const override; - uint64_t getFrameNumber() const override; + uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; bool getSidebandStreamChanged() const override; @@ -131,7 +131,8 @@ private: void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() override; - status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b693a47f39..f7e188f3ec 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -561,8 +561,9 @@ public: * operation, so this should be set only if needed). Typically this is used * to figure out if the content or size of a surface has changed. */ - virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) { - return {}; + virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/, + nsecs_t /*expectedPresentTime*/) { + return false; } virtual bool isBufferLatched() const { return false; } @@ -812,7 +813,7 @@ public: // this to be called once. sp getHandle(); const String8& getName() const; - virtual void notifyAvailableFrames() {} + virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 99440a6d5e..cd80f2b359 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1693,15 +1693,15 @@ bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS { return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled); } -void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS { +void SurfaceFlinger::populateExpectedPresentTime() { DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(); // Inflate the expected present time if we're targetting the next vsync. - mExpectedPresentTime = - mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync() - ? presentTime - : presentTime + stats.vsyncPeriod; + mExpectedPresentTime.store(mVsyncModulator.getOffsets().sf < + mPhaseOffsets->getOffsetThresholdForNextVsync() + ? presentTime + : presentTime + stats.vsyncPeriod); } void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { @@ -2856,9 +2856,11 @@ void SurfaceFlinger::processDisplayChangesLocked() { void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); + // Notify all layers of available frames - mCurrentState.traverseInZOrder([](Layer* layer) { - layer->notifyAvailableFrames(); + mCurrentState.traverseInZOrder([expectedPresentTime](Layer* layer) { + layer->notifyAvailableFrames(expectedPresentTime); }); /* @@ -3057,7 +3059,7 @@ void SurfaceFlinger::updateCursorAsync() void SurfaceFlinger::latchAndReleaseBuffer(const sp& layer) { if (layer->hasReadyFrame()) { bool ignored = false; - layer->latchBuffer(ignored, systemTime()); + layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); } layer->releasePendingBuffer(systemTime()); } @@ -3305,6 +3307,8 @@ bool SurfaceFlinger::handlePageFlip() bool frameQueued = false; bool newDataLatched = false; + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); + // Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. // Example: Two producers share the same command stream and: @@ -3317,7 +3321,6 @@ bool SurfaceFlinger::handlePageFlip() mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->hasReadyFrame()) { frameQueued = true; - const nsecs_t expectedPresentTime = getExpectedPresentTime(); if (layer->shouldPresentNow(expectedPresentTime)) { mLayersWithQueuedFrames.push_back(layer); } else { @@ -3335,7 +3338,7 @@ bool SurfaceFlinger::handlePageFlip() Mutex::Autolock lock(mStateLock); for (auto& layer : mLayersWithQueuedFrames) { - if (layer->latchBuffer(visibleRegions, latchTime)) { + if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) { mLayersPendingRefresh.push_back(layer); } layer->useSurfaceDamage(); @@ -3656,6 +3659,7 @@ bool SurfaceFlinger::flushTransactionQueues() { while (!transactionQueue.empty()) { const auto& transaction = transactionQueue.front(); if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime, + true /* useCachedExpectedPresentTime */, transaction.states)) { setTransactionFlags(eTransactionFlushNeeded); break; @@ -3708,8 +3712,12 @@ bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& } bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, + bool useCachedExpectedPresentTime, const Vector& states) { - nsecs_t expectedPresentTime = getExpectedPresentTime(); + if (!useCachedExpectedPresentTime) + populateExpectedPresentTime(); + + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second // in the future. We ignore timestamps more than 1 second in the future for stability reasons. if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime && @@ -3764,8 +3772,10 @@ void SurfaceFlinger::setTransactionState(const Vector& states, itr = mTransactionQueues.find(applyToken); } } - if (itr != mTransactionQueues.end() || - !transactionIsReadyToBeApplied(desiredPresentTime, states)) { + + // Expected present time is computed and cached on invalidate, so it may be stale. + if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied( + desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime, privileged); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0e6eacf72b..099ba723ee 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -295,18 +295,13 @@ public: // main thread function to enable/disable h/w composer event void setPrimaryVsyncEnabledInternal(bool enabled); + void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled); // called on the main thread by MessageQueue when an internal message // is received // TODO: this should be made accessible only to MessageQueue void onMessageReceived(int32_t what); - // populates the expected present time for this frame. - // When we are in negative offsets, we perform a correction so that the - // predicted vsync for the *next* frame is used instead. - void populateExpectedPresentTime(); - nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; } - // for debugging only // TODO: this should be made accessible only to HWComposer const Vector>& getLayerSortedByZForHwcDisplay(DisplayId displayId); @@ -585,6 +580,7 @@ private: void commitOffscreenLayers(); bool containsAnyInvalidClientState(const Vector& states); bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, + bool useCachedExpectedPresentTime, const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState, int64_t desiredPresentTime, const std::vector& listenerCallbacks, @@ -816,6 +812,12 @@ private: bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock); + bool previousFrameMissed(); + + // Populates the expected present time for this frame. For negative offsets, performs a + // correction using the predicted vsync for the next frame instead. + void populateExpectedPresentTime(); + /* * Display identification */ @@ -844,9 +846,6 @@ private: return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; } - bool previousFrameMissed(); - void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled); - /* * Debugging & dumpsys */ @@ -1135,6 +1134,8 @@ private: scheduler::RefreshRateConfigs mRefreshRateConfigs; scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats}; + std::atomic mExpectedPresentTime = 0; + // All configs are allowed if the set is empty. using DisplayConfigs = std::set; DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock); @@ -1188,8 +1189,6 @@ private: // Flags to capture the state of Vsync in HWC HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable; HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable; - - nsecs_t mExpectedPresentTime; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index e6211c488e..ce67a19c3b 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -502,7 +502,7 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); bool ignoredRecomputeVisibleRegions; - layer->latchBuffer(ignoredRecomputeVisibleRegions, 0); + layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0); Mock::VerifyAndClear(test->mRenderEngine); } -- cgit v1.2.3-59-g8ed1b From f16688fcebb22193b555e24c329155f6f0a2f372 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 19 Feb 2019 17:47:57 -0800 Subject: SF: Introduce LayerFE::prepareClientComposition Renames Layer::prepareClientLayer, and alters it to not take a RenderArea. Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: I6da6005c2e34e6e44692043cdc7adf9c4aa57cf5 --- services/surfaceflinger/BufferLayer.cpp | 42 ++++++++-------- services/surfaceflinger/BufferLayer.h | 17 +++---- services/surfaceflinger/ColorLayer.cpp | 18 +++---- services/surfaceflinger/ColorLayer.h | 13 ++--- .../include/compositionengine/LayerFE.h | 31 ++++++++++++ .../include/compositionengine/mock/LayerFE.h | 3 ++ services/surfaceflinger/ContainerLayer.cpp | 5 -- services/surfaceflinger/ContainerLayer.h | 8 --- services/surfaceflinger/Layer.cpp | 57 ++++++++-------------- services/surfaceflinger/Layer.h | 21 ++------ services/surfaceflinger/SurfaceFlinger.cpp | 56 ++++++++++++++------- 11 files changed, 141 insertions(+), 130 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 59ea9afa97..87bec11609 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -132,13 +132,15 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { return inverse(tr); } -bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) { +std::optional BufferLayer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { ATRACE_CALL(); - Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, - supportProtectedContent, layer); + + auto result = Layer::prepareClientComposition(targetSettings); + if (!result) { + return result; + } + if (CC_UNLIKELY(mActiveBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with @@ -159,15 +161,16 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& under.orSelf(layer->visibleRegion); }); // if not everything below us is covered, we plug the holes! - Region holes(clip.subtract(under)); + Region holes(targetSettings.clip.subtract(under)); if (!holes.isEmpty()) { - clearRegion.orSelf(holes); + targetSettings.clearRegion.orSelf(holes); } - return false; + return std::nullopt; } - bool blackOutLayer = - (isProtected() && !supportProtectedContent) || (isSecure() && !renderArea.isSecure()); + bool blackOutLayer = (isProtected() && !targetSettings.supportProtectedContent) || + (isSecure() && !targetSettings.isSecure); const State& s(getDrawingState()); + auto& layer = *result; if (!blackOutLayer) { layer.source.buffer.buffer = mActiveBuffer; layer.source.buffer.isOpaque = isOpaque(s); @@ -176,8 +179,7 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); // TODO: we could be more subtle with isFixedSize() - const bool useFiltering = needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering() || isFixedSize(); + const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || isFixedSize(); // Query the texture matrix given our current filtering mode. float textureMatrix[16]; @@ -244,7 +246,7 @@ bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& layer.alpha = 1.0; } - return true; + return result; } bool BufferLayer::isHdrY410() const { @@ -572,21 +574,23 @@ bool BufferLayer::getOpacityForFormat(uint32_t format) { } bool BufferLayer::needsFiltering(const sp& displayDevice) const { - // If we are not capturing based on the state of a known display device, we - // only return mNeedsFiltering + // If we are not capturing based on the state of a known display device, + // just return false. if (displayDevice == nullptr) { - return mNeedsFiltering; + return false; } const auto outputLayer = findOutputLayerForDisplay(displayDevice); if (outputLayer == nullptr) { - return mNeedsFiltering; + return false; } + // We need filtering if the sourceCrop rectangle size does not match the + // displayframe rectangle size (not a 1:1 render) const auto& compositionState = outputLayer->getState(); const auto displayFrame = compositionState.displayFrame; const auto sourceCrop = compositionState.sourceCrop; - return mNeedsFiltering || sourceCrop.getHeight() != displayFrame.getHeight() || + return sourceCrop.getHeight() != displayFrame.getHeight() || sourceCrop.getWidth() != displayFrame.getWidth(); } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index bb0205de3e..c86acf08f8 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -82,7 +82,6 @@ public: bool isHdrY410() const override; - bool onPreComposition(nsecs_t refreshStartTime) override; bool onPostComposition(const std::optional& displayId, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, @@ -146,7 +145,13 @@ private: virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; protected: - void latchPerFrameState(compositionengine::LayerFECompositionState& outState) const override; + /* + * compositionengine::LayerFE overrides + */ + bool onPreComposition(nsecs_t) override; + void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; // Loads the corresponding system property once per process static bool latchUnsignaledBuffers(); @@ -163,15 +168,9 @@ protected: bool mRefreshPending{false}; - // prepareClientLayer - constructs a RenderEngine layer for GPU composition. - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) override; - private: // Returns true if this layer requires filtering - bool needsFiltering(const sp& displayDevice) const; + bool needsFiltering(const sp& displayDevice) const override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index f15957adf9..b65d351263 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -50,16 +50,14 @@ ColorLayer::ColorLayer(const LayerCreationArgs& args) ColorLayer::~ColorLayer() = default; -bool ColorLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, - supportProtectedContent, layer); - half4 color(getColor()); - half3 solidColor(color.r, color.g, color.b); - layer.source.solidColor = solidColor; - return true; +std::optional ColorLayer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + auto result = Layer::prepareClientComposition(targetSettings); + if (!result) { + return result; + } + result->source.solidColor = getColor().rgb; + return result; } bool ColorLayer::isVisible() const { diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 2483ff0bfb..015b939457 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -39,16 +39,13 @@ public: void commitTransaction(const State& stateToCommit) override; - bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } - protected: - virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer); - -private: + /* + * compositionengine::LayerFE overrides + */ void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; std::shared_ptr mCompositionLayer; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 1f2cae9c2b..94fab1fdf6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,6 +16,9 @@ #pragma once +#include + +#include #include #include @@ -40,6 +43,34 @@ public: // geometry state can be skipped. virtual void latchCompositionState(LayerFECompositionState&, bool includeGeometry) const = 0; + struct ClientCompositionTargetSettings { + // The clip region, or visible region that is being rendered to + const Region& clip; + + // If true, the layer should use an identity transform for its position + // transform. Used only by the captureScreen API call. + const bool useIdentityTransform; + + // If set to true, the layer should enable filtering when rendering. + const bool needsFiltering; + + // If set to true, the buffer is being sent to a destination that is + // expected to treat the buffer contents as secure. + const bool isSecure; + + // If set to true, the target buffer has protected content support. + const bool supportProtectedContent; + + // Modified by each call to prepareClientComposition to indicate the + // region of the target buffer that should be cleared. + Region& clearRegion; + }; + + // Returns the LayerSettings to pass to RenderEngine::drawLayers, or + // nullopt_t if the layer does not render + virtual std::optional prepareClientComposition( + ClientCompositionTargetSettings&) = 0; + // Called after the layer is displayed to update the presentation fence virtual void onLayerDisplayed(const sp&) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 952f702e1c..48c2dbf3d6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -33,6 +33,9 @@ public: MOCK_METHOD1(onPreComposition, bool(nsecs_t)); MOCK_CONST_METHOD2(latchCompositionState, void(LayerFECompositionState&, bool)); + MOCK_METHOD1(prepareClientComposition, + std::optional( + compositionengine::LayerFE::ClientCompositionTargetSettings&)); MOCK_METHOD1(onLayerDisplayed, void(const sp&)); MOCK_CONST_METHOD0(getDebugName, const char*()); diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 3a5f3faa20..d40a38c811 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -26,11 +26,6 @@ ContainerLayer::ContainerLayer(const LayerCreationArgs& args) : Layer(args) {} ContainerLayer::~ContainerLayer() = default; -bool ContainerLayer::prepareClientLayer(const RenderArea&, const Region&, bool, Region&, const bool, - renderengine::LayerSettings&) { - return false; -} - bool ContainerLayer::isVisible() const { return false; } diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index 57267c70c8..a1607ffabb 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -34,14 +34,6 @@ public: bool canReceiveInput() const override; bool isCreatedFromMainThread() const override { return true; } - - bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; } - -protected: - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer) override; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 8150ca7dfc..a2eeea545b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -458,6 +458,10 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo } } +bool Layer::onPreComposition(nsecs_t) { + return false; +} + void Layer::latchCompositionState(compositionengine::LayerFECompositionState& compositionState, bool includeGeometry) const { if (includeGeometry) { @@ -507,54 +511,33 @@ void Layer::updateCursorPosition(const sp& display) { // drawing... // --------------------------------------------------------------------------- -bool Layer::prepareClientLayer(const RenderArea& renderArea, const Region& clip, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, clip, false, clearRegion, supportProtectedContent, layer); -} - -bool Layer::prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer) { - return prepareClientLayer(renderArea, Region(renderArea.getBounds()), useIdentityTransform, - clearRegion, supportProtectedContent, layer); -} +std::optional Layer::prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { + if (!getCompositionLayer()) { + return {}; + } -bool Layer::prepareClientLayer(const RenderArea& /*renderArea*/, const Region& /*clip*/, - bool useIdentityTransform, Region& /*clearRegion*/, - const bool /*supportProtectedContent*/, - renderengine::LayerSettings& layer) { FloatRect bounds = getBounds(); half alpha = getAlpha(); - layer.geometry.boundaries = bounds; - if (useIdentityTransform) { - layer.geometry.positionTransform = mat4(); + renderengine::LayerSettings layerSettings; + layerSettings.geometry.boundaries = bounds; + if (targetSettings.useIdentityTransform) { + layerSettings.geometry.positionTransform = mat4(); } else { - const ui::Transform transform = getTransform(); - mat4 m; - m[0][0] = transform[0][0]; - m[0][1] = transform[0][1]; - m[0][3] = transform[0][2]; - m[1][0] = transform[1][0]; - m[1][1] = transform[1][1]; - m[1][3] = transform[1][2]; - m[3][0] = transform[2][0]; - m[3][1] = transform[2][1]; - m[3][3] = transform[2][2]; - layer.geometry.positionTransform = m; + layerSettings.geometry.positionTransform = getTransform().asMatrix4(); } if (hasColorTransform()) { - layer.colorTransform = getColorTransform(); + layerSettings.colorTransform = getColorTransform(); } const auto roundedCornerState = getRoundedCornerState(); - layer.geometry.roundedCornersRadius = roundedCornerState.radius; - layer.geometry.roundedCornersCrop = roundedCornerState.cropRect; + layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius; + layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; - layer.alpha = alpha; - layer.sourceDataspace = mCurrentDataSpace; - return true; + layerSettings.alpha = alpha; + layerSettings.sourceDataspace = mCurrentDataSpace; + return layerSettings; } Hwc2::IComposerClient::Composition Layer::getCompositionType( diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index aa7e2f1ec3..953f25ddf1 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -461,19 +461,17 @@ public: return s.activeTransparentRegion_legacy; } virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } - -protected: - virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, - bool useIdentityTransform, Region& clearRegion, - const bool supportProtectedContent, - renderengine::LayerSettings& layer); + virtual bool needsFiltering(const sp&) const { return false; } public: /* * compositionengine::LayerFE overrides */ + bool onPreComposition(nsecs_t) override; void latchCompositionState(compositionengine::LayerFECompositionState&, bool includeGeometry) const override; + std::optional prepareClientComposition( + compositionengine::LayerFE::ClientCompositionTargetSettings&) override; void onLayerDisplayed(const sp& releaseFence) override; const char* getDebugName() const override; @@ -508,17 +506,6 @@ public: // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } - /* - * prepareClientLayer - populates a renderengine::LayerSettings to passed to - * RenderEngine::drawLayers. Returns true if the layer can be used, and - * false otherwise. - */ - bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, Region& clearRegion, - const bool supportProtectedContent, renderengine::LayerSettings& layer); - bool prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform, - Region& clearRegion, const bool supportProtectedContent, - renderengine::LayerSettings& layer); - /* * doTransaction - process the transaction. This is a good place to figure * out which attributes of the surface have changed. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 1aec0c5389..d877e77832 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3319,6 +3319,7 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, */ ALOGV("Rendering client layers"); + const bool useIdentityTransform = false; bool firstLayer = true; Region clearRegion = Region::INVALID_REGION; for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { @@ -3339,13 +3340,20 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) { // never clear the very first layer since we're // guaranteed the FB is already cleared - renderengine::LayerSettings layerSettings; Region dummyRegion; - bool prepared = - layer->prepareClientLayer(renderArea, clip, dummyRegion, - supportProtectedContent, layerSettings); - - if (prepared) { + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || + renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + dummyRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + + if (result) { + auto& layerSettings = *result; layerSettings.source.buffer.buffer = nullptr; layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); layerSettings.alpha = half(0.0); @@ -3356,12 +3364,18 @@ bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, break; } case Hwc2::IComposerClient::Composition::CLIENT: { - renderengine::LayerSettings layerSettings; - bool prepared = - layer->prepareClientLayer(renderArea, clip, clearRegion, - supportProtectedContent, layerSettings); - if (prepared) { - clientCompositionLayers.push_back(layerSettings); + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || + renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + clearRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + if (result) { + clientCompositionLayers.push_back(*result); } break; } @@ -5902,11 +5916,19 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, Region clearRegion = Region::INVALID_REGION; traverseLayers([&](Layer* layer) { - renderengine::LayerSettings layerSettings; - bool prepared = layer->prepareClientLayer(renderArea, useIdentityTransform, clearRegion, - false, layerSettings); - if (prepared) { - clientCompositionLayers.push_back(layerSettings); + const bool supportProtectedContent = false; + Region clip(renderArea.getBounds()); + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering(renderArea.getDisplayDevice()) || renderArea.needsFiltering(), + renderArea.isSecure(), + supportProtectedContent, + clearRegion, + }; + auto result = layer->prepareClientComposition(targetSettings); + if (result) { + clientCompositionLayers.push_back(*result); } }); -- cgit v1.2.3-59-g8ed1b From 688abd459a80ad7ec491eae024c330265f8fcc16 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Fri, 15 Feb 2019 15:42:24 -0800 Subject: SF: Move doComposeSurfaces to CompositionEngine Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: Iae3377a5ea018f9ec53c5a76ed6a86620f39b731 --- services/surfaceflinger/BufferLayer.cpp | 2 +- .../surfaceflinger/CompositionEngine/Android.bp | 1 + .../compositionengine/DisplayCreationArgs.h | 9 + .../include/compositionengine/LayerFE.h | 2 +- .../compositionengine/LayerFECompositionState.h | 6 + .../include/compositionengine/Output.h | 14 ++ .../include/compositionengine/OutputLayer.h | 3 + .../include/compositionengine/impl/Display.h | 5 + .../include/compositionengine/impl/Output.h | 7 + .../include/compositionengine/impl/OutputLayer.h | 1 + .../include/compositionengine/mock/Output.h | 9 + .../include/compositionengine/mock/OutputLayer.h | 1 + .../CompositionEngine/src/Display.cpp | 21 ++- .../src/LayerCompositionState.cpp | 2 + .../CompositionEngine/src/Output.cpp | 188 +++++++++++++++++++- .../CompositionEngine/src/OutputLayer.cpp | 7 + .../CompositionEngine/tests/DisplayTest.cpp | 37 +++- .../CompositionEngine/tests/MockPowerAdvisor.cpp | 34 ++++ .../CompositionEngine/tests/MockPowerAdvisor.h | 37 ++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 18 ++ services/surfaceflinger/DisplayDevice.cpp | 2 +- services/surfaceflinger/DisplayDevice.h | 2 + services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 194 +-------------------- services/surfaceflinger/SurfaceFlinger.h | 6 - 25 files changed, 411 insertions(+), 205 deletions(-) create mode 100644 services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp create mode 100644 services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 87bec11609..13c748f24c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -167,7 +167,7 @@ std::optional BufferLayer::prepareClientComposition } return std::nullopt; } - bool blackOutLayer = (isProtected() && !targetSettings.supportProtectedContent) || + bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const State& s(getDrawingState()); auto& layer = *result; diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 6f076ad11f..ae6bdbce60 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -94,6 +94,7 @@ cc_test { "tests/LayerTest.cpp", "tests/MockHWC2.cpp", "tests/MockHWComposer.cpp", + "tests/MockPowerAdvisor.cpp", "tests/OutputTest.cpp", "tests/OutputLayerTest.cpp", "tests/RenderSurfaceTest.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 0b6b4e4f0f..0778936d24 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -20,6 +20,7 @@ #include #include "DisplayHardware/DisplayIdentification.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine { @@ -37,6 +38,10 @@ struct DisplayCreationArgs { // Identifies the display to the HWC, if composition is supported by it std::optional displayId; + + // Optional pointer to the power advisor interface, if one is needed for + // this display. + Hwc2::PowerAdvisor* powerAdvisor = nullptr; }; /** @@ -68,6 +73,10 @@ public: mArgs.displayId = displayId; return *this; } + DisplayCreationArgsBuilder& setPowerAdvisor(Hwc2::PowerAdvisor* powerAdvisor) { + mArgs.powerAdvisor = powerAdvisor; + return *this; + } private: DisplayCreationArgs mArgs; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 94fab1fdf6..2a901ae68b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -59,7 +59,7 @@ public: const bool isSecure; // If set to true, the target buffer has protected content support. - const bool supportProtectedContent; + const bool supportsProtectedContent; // Modified by each call to prepareClientComposition to indicate the // region of the target buffer that should be cleared. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index d96d58c1fa..d5763d5611 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -116,6 +116,12 @@ struct LayerFECompositionState { // The color transform mat4 colorTransform; bool colorTransformIsIdentity{true}; + + // True if the layer is completely opaque + bool isOpaque{true}; + + // True if the layer has protected content + bool hasProtectedContent{false}; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 4dfcfa4593..f73304d211 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -156,6 +157,12 @@ public: // Prepares a frame for display virtual void prepareFrame() = 0; + // Performs client composition as needed for layers on the output. The + // output fence is set to a fence to signal when client composition is + // finished. + // Returns false if client composition cannot be performed. + virtual bool composeSurfaces(const Region& debugFence, base::unique_fd* outReadyFence) = 0; + // Posts the new frame, and sets release fences. virtual void postFramebuffer() = 0; @@ -163,7 +170,14 @@ protected: virtual void setDisplayColorProfile(std::unique_ptr) = 0; virtual void setRenderSurface(std::unique_ptr) = 0; virtual void chooseCompositionStrategy() = 0; + virtual bool getSkipColorTransform() const = 0; virtual FrameFences presentAndGetFrameFences() = 0; + virtual std::vector generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) = 0; + virtual void appendRegionFlashRequests( + const Region& flashRegion, + std::vector& clientCompositionLayers) = 0; + virtual void setExpensiveRenderingExpected(bool enabled) = 0; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index d7f00a978a..5f62b32c9a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -93,6 +93,9 @@ public: // Applies a HWC device layer request virtual void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) = 0; + // Returns true if the composition settings scale pixels + virtual bool needsFiltering() const = 0; + // Debugging virtual void dump(std::string& result) const = 0; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 795061af28..36e4aac76e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -23,6 +23,7 @@ #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine { @@ -42,7 +43,9 @@ public: void setColorTransform(const mat4&) override; void setColorMode(ui::ColorMode, ui::Dataspace, ui::RenderIntent, ui::Dataspace) override; void chooseCompositionStrategy() override; + bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; + void setExpensiveRenderingExpected(bool) override; // compositionengine::Display overrides const std::optional& getId() const override; @@ -65,9 +68,11 @@ public: private: const bool mIsVirtual; std::optional mId; + Hwc2::PowerAdvisor* const mPowerAdvisor{nullptr}; }; std::shared_ptr createDisplay(const compositionengine::CompositionEngine&, compositionengine::DisplayCreationArgs&&); + } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 5f4a76440c..3972f2bcf4 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -77,6 +77,7 @@ public: void beginFrame() override; void prepareFrame() override; + bool composeSurfaces(const Region&, base::unique_fd*) override; void postFramebuffer() override; // Testing @@ -86,7 +87,13 @@ public: protected: const CompositionEngine& getCompositionEngine() const; void chooseCompositionStrategy() override; + bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; + std::vector generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) override; + void appendRegionFlashRequests(const Region&, + std::vector&) override; + void setExpensiveRenderingExpected(bool enabled) override; void dumpBase(std::string&) const; private: diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index d8ad02aca3..4c3f9359b0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -55,6 +55,7 @@ public: void applyDeviceCompositionTypeChange(Hwc2::IComposerClient::Composition) override; void prepareForDeviceLayerRequests() override; void applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest request) override; + bool needsFiltering() const override; void dump(std::string& result) const override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index d494413af5..c944becd22 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -77,8 +77,17 @@ public: MOCK_METHOD0(prepareFrame, void()); MOCK_METHOD0(chooseCompositionStrategy, void()); + MOCK_METHOD2(composeSurfaces, bool(const Region&, base::unique_fd*)); + MOCK_CONST_METHOD0(getSkipColorTransform, bool()); + MOCK_METHOD0(postFramebuffer, void()); MOCK_METHOD0(presentAndGetFrameFences, compositionengine::Output::FrameFences()); + + MOCK_METHOD2(generateClientCompositionRequests, + std::vector(bool, Region&)); + MOCK_METHOD2(appendRegionFlashRequests, + void(const Region&, std::vector&)); + MOCK_METHOD1(setExpensiveRenderingExpected, void(bool)); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 195648ff7c..d8d637d302 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -46,6 +46,7 @@ public: MOCK_METHOD1(applyDeviceCompositionTypeChange, void(Hwc2::IComposerClient::Composition)); MOCK_METHOD0(prepareForDeviceLayerRequests, void()); MOCK_METHOD1(applyDeviceLayerRequest, void(Hwc2::IComposerClient::LayerRequest request)); + MOCK_CONST_METHOD0(needsFiltering, bool()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 68319013d7..6cd392eabd 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -26,6 +26,7 @@ #include #include "DisplayHardware/HWComposer.h" +#include "DisplayHardware/PowerAdvisor.h" namespace android::compositionengine::impl { @@ -38,7 +39,8 @@ std::shared_ptr createDisplay( Display::Display(const CompositionEngine& compositionEngine, DisplayCreationArgs&& args) : compositionengine::impl::Output(compositionEngine), mIsVirtual(args.isVirtual), - mId(args.displayId) { + mId(args.displayId), + mPowerAdvisor(args.powerAdvisor) { editState().isSecure = args.isSecure; } @@ -160,6 +162,15 @@ void Display::chooseCompositionStrategy() { state.usesDeviceComposition = !allLayersRequireClientComposition(); } +bool Display::getSkipColorTransform() const { + if (!mId) { + return false; + } + + auto& hwc = getCompositionEngine().getHwComposer(); + return hwc.hasDisplayCapability(*mId, HWC2::DisplayCapability::SkipClientColorTransform); +} + bool Display::anyLayersRequireClientComposition() const { const auto& layers = getOutputLayersOrderedByZ(); return std::any_of(layers.cbegin(), layers.cend(), @@ -240,4 +251,12 @@ compositionengine::Output::FrameFences Display::presentAndGetFrameFences() { return result; } +void Display::setExpensiveRenderingExpected(bool enabled) { + Output::setExpensiveRenderingExpected(enabled); + + if (mPowerAdvisor && mId) { + mPowerAdvisor->setExpensiveRenderingExpected(*mId, enabled); + } +} + } // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp index 37d6eaa2f2..0dc4bf1559 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp @@ -71,6 +71,8 @@ void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { dumpVal(out, "color", state.color); out.append("\n "); + dumpVal(out, "isOpaque", state.isOpaque); + dumpVal(out, "hasProtectedContent", state.hasProtectedContent); dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 6878e99b72..fb576e06f8 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -17,13 +17,20 @@ #include #include #include +#include #include #include +#include #include #include +#include +#include #include +#include #include +#include "TracedOrdinal.h" + namespace android::compositionengine { Output::~Output() = default; @@ -73,10 +80,10 @@ void Output::setProjection(const ui::Transform& transform, int32_t orientation, dirtyEntireOutput(); } -// TODO(lpique): Rename setSize() once more is moved. +// TODO(b/121291683): Rename setSize() once more is moved. void Output::setBounds(const ui::Size& size) { mRenderSurface->setDisplaySize(size); - // TODO(lpique): Rename mState.size once more is moved. + // TODO(b/121291683): Rename mState.size once more is moved. mState.bounds = Rect(mRenderSurface->getSize()); dirtyEntireOutput(); @@ -292,6 +299,179 @@ void Output::prepareFrame() { mRenderSurface->prepareFrame(mState.usesClientComposition, mState.usesDeviceComposition); } +bool Output::composeSurfaces(const Region& debugRegion, base::unique_fd* readyFence) { + ATRACE_CALL(); + ALOGV(__FUNCTION__); + + const TracedOrdinal hasClientComposition = {"hasClientComposition", + mState.usesClientComposition}; + if (!hasClientComposition) { + return true; + } + + ALOGV("hasClientComposition"); + + auto& renderEngine = mCompositionEngine.getRenderEngine(); + const bool supportsProtectedContent = renderEngine.supportsProtectedContent(); + + renderengine::DisplaySettings clientCompositionDisplay; + clientCompositionDisplay.physicalDisplay = mState.frame; + clientCompositionDisplay.clip = mState.scissor; + clientCompositionDisplay.globalTransform = mState.transform.asMatrix4(); + clientCompositionDisplay.orientation = mState.orientation; + clientCompositionDisplay.outputDataspace = + mDisplayColorProfile->hasWideColorGamut() ? mState.dataspace : ui::Dataspace::UNKNOWN; + clientCompositionDisplay.maxLuminance = + mDisplayColorProfile->getHdrCapabilities().getDesiredMaxLuminance(); + + // Compute the global color transform matrix. + if (!mState.usesDeviceComposition && !getSkipColorTransform()) { + clientCompositionDisplay.colorTransform = mState.colorTransformMat; + } + + // Note: Updated by generateClientCompositionRequests + clientCompositionDisplay.clearRegion = Region::INVALID_REGION; + + // Generate the client composition requests for the layers on this output. + std::vector clientCompositionLayers = + generateClientCompositionRequests(supportsProtectedContent, + clientCompositionDisplay.clearRegion); + appendRegionFlashRequests(debugRegion, clientCompositionLayers); + + // If we the display is secure, protected content support is enabled, and at + // least one layer has protected content, we need to use a secure back + // buffer. + if (mState.isSecure && supportsProtectedContent) { + bool needsProtected = + std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(), + [](auto& layer) { + return layer->getLayer().getState().frontEnd.hasProtectedContent; + }); + if (needsProtected != renderEngine.isProtected()) { + renderEngine.useProtectedContext(needsProtected); + } + if (needsProtected != mRenderSurface->isProtected() && + needsProtected == renderEngine.isProtected()) { + mRenderSurface->setProtected(needsProtected); + } + } + + base::unique_fd fd; + sp buf = mRenderSurface->dequeueBuffer(&fd); + if (buf == nullptr) { + ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " + "client composition for this frame", + mName.c_str()); + return false; + } + + // We boost GPU frequency here because there will be color spaces conversion + // and it's expensive. We boost the GPU frequency so that GPU composition can + // finish in time. We must reset GPU frequency afterwards, because high frequency + // consumes extra battery. + const bool expensiveRenderingExpected = + clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3; + if (expensiveRenderingExpected) { + setExpensiveRenderingExpected(true); + } + + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers, + buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd), + readyFence); + + if (expensiveRenderingExpected) { + setExpensiveRenderingExpected(false); + } + + return true; +} + +std::vector Output::generateClientCompositionRequests( + bool supportsProtectedContent, Region& clearRegion) { + std::vector clientCompositionLayers; + ALOGV("Rendering client layers"); + + const Region viewportRegion(mState.viewport); + const bool useIdentityTransform = false; + bool firstLayer = true; + // Used when a layer clears part of the buffer. + Region dummyRegion; + + for (auto& layer : mOutputLayersOrderedByZ) { + const auto& layerState = layer->getState(); + const auto& layerFEState = layer->getLayer().getState().frontEnd; + auto& layerFE = layer->getLayerFE(); + + const Region clip(viewportRegion.intersect(layer->getState().visibleRegion)); + ALOGV("Layer: %s", layerFE.getDebugName()); + if (clip.isEmpty()) { + ALOGV(" Skipping for empty clip"); + firstLayer = false; + continue; + } + + bool clientComposition = layer->requiresClientComposition(); + + // We clear the client target for non-client composed layers if + // requested by the HWC. We skip this if the layer is not an opaque + // rectangle, as by definition the layer must blend with whatever is + // underneath. We also skip the first layer as the buffer target is + // guaranteed to start out cleared. + bool clearClientComposition = + layerState.clearClientTarget && layerFEState.isOpaque && !firstLayer; + + ALOGV(" Composition type: client %d clear %d", clientComposition, clearClientComposition); + + if (clientComposition || clearClientComposition) { + compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ + clip, + useIdentityTransform, + layer->needsFiltering() || mState.needsFiltering, + mState.isSecure, + supportsProtectedContent, + clientComposition ? clearRegion : dummyRegion, + }; + if (auto result = layerFE.prepareClientComposition(targetSettings)) { + if (clearClientComposition) { + auto& layerSettings = *result; + layerSettings.source.buffer.buffer = nullptr; + layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); + layerSettings.alpha = half(0.0); + layerSettings.disableBlending = true; + } + + clientCompositionLayers.push_back(*result); + } + } + + firstLayer = false; + } + + return clientCompositionLayers; +} + +void Output::appendRegionFlashRequests( + const Region& flashRegion, + std::vector& clientCompositionLayers) { + if (flashRegion.isEmpty()) { + return; + } + + renderengine::LayerSettings layerSettings; + layerSettings.source.buffer.buffer = nullptr; + layerSettings.source.solidColor = half3(1.0, 0.0, 1.0); + layerSettings.alpha = half(1.0); + + for (const auto& rect : flashRegion) { + layerSettings.geometry.boundaries = rect.toFloatRect(); + clientCompositionLayers.push_back(layerSettings); + } +} + +void Output::setExpensiveRenderingExpected(bool) { + // The base class does nothing with this call. +} + void Output::postFramebuffer() { ATRACE_CALL(); ALOGV(__FUNCTION__); @@ -353,6 +533,10 @@ void Output::chooseCompositionStrategy() { mState.usesDeviceComposition = false; } +bool Output::getSkipColorTransform() const { + return true; +} + compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { compositionengine::Output::FrameFences result; if (mState.usesClientComposition) { diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 6e744b948f..e721cf5375 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -614,6 +614,13 @@ void OutputLayer::applyDeviceLayerRequest(Hwc2::IComposerClient::LayerRequest re } } +bool OutputLayer::needsFiltering() const { + const auto& displayFrame = mState.displayFrame; + const auto& sourceCrop = mState.sourceCrop; + return sourceCrop.getHeight() != displayFrame.getHeight() || + sourceCrop.getWidth() != displayFrame.getWidth(); +} + void OutputLayer::dump(std::string& out) const { using android::base::StringAppendF; diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index e3be0d7a9c..743da8207a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -30,6 +30,7 @@ #include "MockHWC2.h" #include "MockHWComposer.h" +#include "MockPowerAdvisor.h" namespace android::compositionengine { namespace { @@ -59,6 +60,7 @@ struct DisplayTest : public testing::Test { } StrictMock mHwComposer; + StrictMock mPowerAdvisor; StrictMock mCompositionEngine; sp mNativeWindow = new StrictMock(); StrictMock mHWC2Layer1; @@ -68,7 +70,10 @@ struct DisplayTest : public testing::Test { mock::OutputLayer* mLayer2 = new StrictMock(); mock::OutputLayer* mLayer3 = new StrictMock(); impl::Display mDisplay{mCompositionEngine, - DisplayCreationArgsBuilder().setDisplayId(DEFAULT_DISPLAY_ID).build()}; + DisplayCreationArgsBuilder() + .setDisplayId(DEFAULT_DISPLAY_ID) + .setPowerAdvisor(&mPowerAdvisor) + .build()}; }; /* @@ -343,6 +348,24 @@ TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) { EXPECT_TRUE(state.usesDeviceComposition); } +/* + * Display::getSkipColorTransform() + */ + +TEST_F(DisplayTest, getSkipColorTransformDoesNothingIfNonHwcDisplay) { + auto nonHwcDisplay{ + impl::createDisplay(mCompositionEngine, DisplayCreationArgsBuilder().build())}; + EXPECT_FALSE(nonHwcDisplay->getSkipColorTransform()); +} + +TEST_F(DisplayTest, getSkipColorTransformChecksHwcCapability) { + EXPECT_CALL(mHwComposer, + hasDisplayCapability(std::make_optional(DEFAULT_DISPLAY_ID), + HWC2::DisplayCapability::SkipClientColorTransform)) + .WillOnce(Return(true)); + EXPECT_TRUE(mDisplay.getSkipColorTransform()); +} + /* * Display::anyLayersRequireClientComposition() */ @@ -502,5 +525,17 @@ TEST_F(DisplayTest, presentAndGetFrameFencesReturnsPresentAndLayerFences) { EXPECT_EQ(layer2Fence, result.layerFences[&mHWC2Layer2]); } +/* + * Display::setExpensiveRenderingExpected() + */ + +TEST_F(DisplayTest, setExpensiveRenderingExpectedForwardsToPowerAdvisor) { + EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, true)).Times(1); + mDisplay.setExpensiveRenderingExpected(true); + + EXPECT_CALL(mPowerAdvisor, setExpensiveRenderingExpected(DEFAULT_DISPLAY_ID, false)).Times(1); + mDisplay.setExpensiveRenderingExpected(false); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp new file mode 100644 index 0000000000..85b94031c3 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2019 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 { + +// This will go away once PowerAdvisor is moved into the "backend" library +PowerAdvisor::~PowerAdvisor() = default; + +namespace mock { + +// The Google Mock documentation recommends explicit non-header instantiations +// for better compile time performance. +PowerAdvisor::PowerAdvisor() = default; +PowerAdvisor::~PowerAdvisor() = default; + +} // namespace mock +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h new file mode 100644 index 0000000000..c5a73f22f9 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h @@ -0,0 +1,37 @@ +/* + * Copyright 2019 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 + +#include "DisplayHardware/PowerAdvisor.h" + +namespace android { +namespace Hwc2 { +namespace mock { + +class PowerAdvisor : public android::Hwc2::PowerAdvisor { +public: + PowerAdvisor(); + ~PowerAdvisor() override; + + MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected)); +}; + +} // namespace mock +} // namespace Hwc2 +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index a5428ad993..c83cae65fb 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -875,5 +875,23 @@ TEST_F(OutputLayerTest, applyDeviceLayerRequestHandlesUnknownRequest) { EXPECT_FALSE(mOutputLayer.getState().clearClientTarget); } +/* + * OutputLayer::needsFiltering() + */ + +TEST_F(OutputLayerTest, needsFilteringReturnsFalseIfDisplaySizeSameAsSourceSize) { + mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200); + mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.f, 100.f}; + + EXPECT_FALSE(mOutputLayer.needsFiltering()); +} + +TEST_F(OutputLayerTest, needsFilteringReturnsTrueIfDisplaySizeDifferentFromSourceSize) { + mOutputLayer.editState().displayFrame = Rect(100, 100, 200, 200); + mOutputLayer.editState().sourceCrop = FloatRect{0.f, 0.f, 100.1f, 100.1f}; + + EXPECT_TRUE(mOutputLayer.needsFiltering()); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index d1365627cf..b6d79d41f2 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -60,7 +60,7 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs&& args) mDisplayInstallOrientation(args.displayInstallOrientation), mCompositionDisplay{mFlinger->getCompositionEngine().createDisplay( compositionengine::DisplayCreationArgs{args.isSecure, args.isVirtual, - args.displayId})}, + args.displayId, args.powerAdvisor})}, mIsVirtual(args.isVirtual), mOrientation(), mActiveConfig(0), diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 8bc19d4447..4321e3dd13 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -40,6 +40,7 @@ #include #include "DisplayHardware/DisplayIdentification.h" +#include "DisplayHardware/PowerAdvisor.h" #include "RenderArea.h" namespace android { @@ -241,6 +242,7 @@ struct DisplayDeviceCreationArgs { std::unordered_map> hwcColorModes; int initialPowerMode{HWC_POWER_MODE_NORMAL}; bool isPrimary{false}; + Hwc2::PowerAdvisor* powerAdvisor{nullptr}; }; class DisplayRenderArea : public RenderArea { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e7fbfe936d..a2ee763c4a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -440,6 +440,7 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio } void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compositionState) const { + const auto& drawingState{getDrawingState()}; compositionState.forceClientComposition = false; // TODO(lpique): b/121291683 Remove this one we are sure we don't need the @@ -451,9 +452,14 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.colorTransform = getColorTransform(); compositionState.colorTransformIsIdentity = !hasColorTransform(); compositionState.surfaceDamage = surfaceDamageRegion; + compositionState.hasProtectedContent = isProtected(); + + const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f; + compositionState.isOpaque = + isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf; // Force client composition for special cases known only to the front-end. - if (isHdrY410() || getRoundedCornerState().radius > 0.0f) { + if (isHdrY410() || usesRoundedCorners) { compositionState.forceClientComposition = true; } } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d2d9ea5d26..af4fa98b0d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1943,7 +1943,7 @@ void SurfaceFlinger::doDebugFlashRegions(const sp& displayDevice, if (!dirtyRegion.isEmpty()) { base::unique_fd readyFence; // redraw the whole screen - doComposeSurfaces(displayDevice, dirtyRegion, &readyFence); + display->composeSurfaces(dirtyRegion, &readyFence); display->getRenderSurface()->queueBuffer(std::move(readyFence)); } @@ -2488,6 +2488,7 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( creationArgs.displaySurface = dispSurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; + creationArgs.powerAdvisor = displayId ? &mPowerAdvisor : nullptr; const bool isInternalDisplay = displayId && displayId == getInternalDisplayIdLocked(); creationArgs.isPrimary = isInternalDisplay; @@ -3228,201 +3229,12 @@ void SurfaceFlinger::doDisplayComposition(const sp& displayDevice ALOGV("doDisplayComposition"); base::unique_fd readyFence; - if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return; + if (!display->composeSurfaces(Region::INVALID_REGION, &readyFence)) return; // swap buffers (presentation) display->getRenderSurface()->queueBuffer(std::move(readyFence)); } -bool SurfaceFlinger::doComposeSurfaces(const sp& displayDevice, - const Region& debugRegion, base::unique_fd* readyFence) { - ATRACE_CALL(); - ALOGV("doComposeSurfaces"); - - auto display = displayDevice->getCompositionDisplay(); - const auto& displayState = display->getState(); - const auto displayId = display->getId(); - auto& renderEngine = getRenderEngine(); - const bool supportProtectedContent = renderEngine.supportsProtectedContent(); - - const Region bounds(displayState.bounds); - const DisplayRenderArea renderArea(displayDevice); - const TracedOrdinal hasClientComposition = {"hasClientComposition", - displayState.usesClientComposition}; - bool applyColorMatrix = false; - - renderengine::DisplaySettings clientCompositionDisplay; - std::vector clientCompositionLayers; - sp buf; - base::unique_fd fd; - - if (hasClientComposition) { - ALOGV("hasClientComposition"); - - if (displayDevice->isPrimary() && supportProtectedContent) { - bool needsProtected = false; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - // If the layer is a protected layer, mark protected context is needed. - if (layer->isProtected()) { - needsProtected = true; - break; - } - } - if (needsProtected != renderEngine.isProtected()) { - renderEngine.useProtectedContext(needsProtected); - } - if (needsProtected != display->getRenderSurface()->isProtected() && - needsProtected == renderEngine.isProtected()) { - display->getRenderSurface()->setProtected(needsProtected); - } - } - - buf = display->getRenderSurface()->dequeueBuffer(&fd); - - if (buf == nullptr) { - ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " - "client composition for this frame", - displayDevice->getDisplayName().c_str()); - return false; - } - - clientCompositionDisplay.physicalDisplay = displayState.scissor; - clientCompositionDisplay.clip = displayState.scissor; - const ui::Transform& displayTransform = displayState.transform; - clientCompositionDisplay.globalTransform = displayTransform.asMatrix4(); - clientCompositionDisplay.orientation = displayState.orientation; - - const auto* profile = display->getDisplayColorProfile(); - Dataspace outputDataspace = Dataspace::UNKNOWN; - if (profile->hasWideColorGamut()) { - outputDataspace = displayState.dataspace; - } - clientCompositionDisplay.outputDataspace = outputDataspace; - clientCompositionDisplay.maxLuminance = - profile->getHdrCapabilities().getDesiredMaxLuminance(); - - const bool hasDeviceComposition = displayState.usesDeviceComposition; - const bool skipClientColorTransform = - getHwComposer() - .hasDisplayCapability(displayId, - HWC2::DisplayCapability::SkipClientColorTransform); - - // Compute the global color transform matrix. - applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform; - if (applyColorMatrix) { - clientCompositionDisplay.colorTransform = displayState.colorTransformMat; - } - } - - /* - * and then, render the layers targeted at the framebuffer - */ - - ALOGV("Rendering client layers"); - const bool useIdentityTransform = false; - bool firstLayer = true; - Region clearRegion = Region::INVALID_REGION; - for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) { - const Region viewportRegion(displayState.viewport); - const Region clip(viewportRegion.intersect(layer->visibleRegion)); - ALOGV("Layer: %s", layer->getName().string()); - ALOGV(" Composition type: %s", toString(layer->getCompositionType(displayDevice)).c_str()); - if (!clip.isEmpty()) { - switch (layer->getCompositionType(displayDevice)) { - case Hwc2::IComposerClient::Composition::CURSOR: - case Hwc2::IComposerClient::Composition::DEVICE: - case Hwc2::IComposerClient::Composition::SIDEBAND: - case Hwc2::IComposerClient::Composition::SOLID_COLOR: { - LOG_ALWAYS_FATAL_IF(!displayId); - const Layer::State& state(layer->getDrawingState()); - if (layer->getClearClientTarget(displayDevice) && !firstLayer && - layer->isOpaque(state) && (layer->getAlpha() == 1.0f) && - layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) { - // never clear the very first layer since we're - // guaranteed the FB is already cleared - Region dummyRegion; - compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ - clip, - useIdentityTransform, - layer->needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering(), - renderArea.isSecure(), - supportProtectedContent, - dummyRegion, - }; - auto result = layer->prepareClientComposition(targetSettings); - - if (result) { - auto& layerSettings = *result; - layerSettings.source.buffer.buffer = nullptr; - layerSettings.source.solidColor = half3(0.0, 0.0, 0.0); - layerSettings.alpha = half(0.0); - layerSettings.disableBlending = true; - clientCompositionLayers.push_back(layerSettings); - } - } - break; - } - case Hwc2::IComposerClient::Composition::CLIENT: { - compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ - clip, - useIdentityTransform, - layer->needsFiltering(renderArea.getDisplayDevice()) || - renderArea.needsFiltering(), - renderArea.isSecure(), - supportProtectedContent, - clearRegion, - }; - auto result = layer->prepareClientComposition(targetSettings); - if (result) { - clientCompositionLayers.push_back(*result); - } - break; - } - default: - break; - } - } else { - ALOGV(" Skipping for empty clip"); - } - firstLayer = false; - } - - // Perform some cleanup steps if we used client composition. - if (hasClientComposition) { - clientCompositionDisplay.clearRegion = clearRegion; - - // We boost GPU frequency here because there will be color spaces conversion - // and it's expensive. We boost the GPU frequency so that GPU composition can - // finish in time. We must reset GPU frequency afterwards, because high frequency - // consumes extra battery. - const bool expensiveRenderingExpected = - clientCompositionDisplay.outputDataspace == Dataspace::DISPLAY_P3; - if (expensiveRenderingExpected && displayId) { - mPowerAdvisor.setExpensiveRenderingExpected(*displayId, true); - } - if (!debugRegion.isEmpty()) { - Region::const_iterator it = debugRegion.begin(); - Region::const_iterator end = debugRegion.end(); - while (it != end) { - const Rect& rect = *it++; - renderengine::LayerSettings layerSettings; - layerSettings.source.buffer.buffer = nullptr; - layerSettings.source.solidColor = half3(1.0, 0.0, 1.0); - layerSettings.geometry.boundaries = rect.toFloatRect(); - layerSettings.alpha = half(1.0); - clientCompositionLayers.push_back(layerSettings); - } - } - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayers, - buf->getNativeBuffer(), /*useFramebufferCache=*/true, std::move(fd), - readyFence); - } else if (displayId) { - mPowerAdvisor.setExpensiveRenderingExpected(*displayId, false); - } - return true; -} - status_t SurfaceFlinger::addClientLayer(const sp& client, const sp& handle, const sp& gbc, const sp& lbc, const sp& parentHandle, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 64e87b14ed..ef096f85a5 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -768,12 +768,6 @@ private: void logLayerStats(); void doDisplayComposition(const sp& display, const Region& dirtyRegion); - // This fails if using GL and the surface has been destroyed. readyFence - // will be populated if using GL and native fence sync is supported, to - // signal when drawing has completed. - bool doComposeSurfaces(const sp& display, const Region& debugRegionm, - base::unique_fd* readyFence); - void postFrame(); /* ------------------------------------------------------------------------ -- cgit v1.2.3-59-g8ed1b From 49a108cda1eda5ce10b7532bf56482d80ae90afa Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 12 Aug 2019 11:23:06 -0700 Subject: Latch and relase buffers for offscreen layers on main thread. The current code was calling fakeVsync, which was latching and releasing buffers on a binder thread when a new frame arrived. This was causing a race with the latchBuffer on the main thread. This change calls latchAndReleaseBuffer on the main thread for offscreen layers to ensure we don't block dequeueBuffer but also don't race the other latchBuffer call. Fixes: 139118508 Test: Race was only reproducible in monkey tests Change-Id: Ie7d87aa775c215de3fb2322b73849402596cc3fc --- services/surfaceflinger/BufferLayer.cpp | 9 +++++++++ services/surfaceflinger/BufferLayer.h | 7 +++++++ services/surfaceflinger/BufferQueueLayer.cpp | 16 +--------------- services/surfaceflinger/BufferQueueLayer.h | 2 -- services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 18 +++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 1 - 7 files changed, 28 insertions(+), 27 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 13c748f24c..e9af9e292b 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -668,6 +668,15 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return FloatRect(0, 0, bufWidth, bufHeight); } +void BufferLayer::latchAndReleaseBuffer() { + mRefreshPending = false; + if (hasReadyFrame()) { + bool ignored = false; + latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); + } + releasePendingBuffer(systemTime()); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 7a0f82b5c0..fb8d7d027f 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -103,6 +103,13 @@ public: // Returns the current scaling mode, unless mOverrideScalingMode // is set, in which case, it returns mOverrideScalingMode uint32_t getEffectiveScalingMode() const override; + + // Calls latchBuffer if the buffer has a frame queued and then releases the buffer. + // This is used if the buffer is just latched and releases to free up the buffer + // and will not be shown on screen. + // Should only be called on the main thread. + void latchAndReleaseBuffer() override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 12be00f116..5f494ff3d5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -412,14 +412,6 @@ void BufferQueueLayer::latchPerFrameState( // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- -void BufferQueueLayer::fakeVsync() { - mRefreshPending = false; - bool ignored = false; - latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); - usleep(16000); - releasePendingBuffer(systemTime()); -} - void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); // Add this buffer from our internal queue tracker @@ -456,13 +448,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), item.mGraphicBuffer->getHeight(), item.mFrameNumber); - // If this layer is orphaned, then we run a fake vsync pulse so that - // dequeueBuffer doesn't block indefinitely. - if (isRemovedFromCurrentState()) { - fakeVsync(); - } else { - mFlinger->signalLayerUpdate(); - } + mFlinger->signalLayerUpdate(); mConsumer->onBufferAvailable(item); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 231a531f58..392b706416 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -138,8 +138,6 @@ private: // thread-safe std::atomic mQueuedFrames{0}; std::atomic mSidebandStreamChanged{false}; - - void fakeVsync(); }; } // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 87a5896c6a..2a1564a440 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -544,6 +544,8 @@ public: virtual bool isBufferLatched() const { return false; } + virtual void latchAndReleaseBuffer() {} + /* * Remove relative z for the layer if its relative parent is not part of the * provided layer tree. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 04e7bf5398..3375649aa2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2887,14 +2887,6 @@ void SurfaceFlinger::updateCursorAsync() } } -void SurfaceFlinger::latchAndReleaseBuffer(const sp& layer) { - if (layer->hasReadyFrame()) { - bool ignored = false; - layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); - } - layer->releasePendingBuffer(systemTime()); -} - void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { @@ -2905,7 +2897,7 @@ void SurfaceFlinger::commitTransaction() // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { - latchAndReleaseBuffer(l); + l->latchAndReleaseBuffer(); } // If the layer has been removed and has no parent, then it will not be reachable @@ -3163,6 +3155,14 @@ bool SurfaceFlinger::handlePageFlip() } }); + // The client can continue submitting buffers for offscreen layers, but they will not + // be shown on screen. Therefore, we need to latch and release buffers of offscreen + // layers to ensure dequeueBuffer doesn't block indefinitely. + for (Layer* offscreenLayer : mOffscreenLayers) { + offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, + [&](Layer* l) { l->latchAndReleaseBuffer(); }); + } + if (!mLayersWithQueuedFrames.empty()) { // mStateLock is needed for latchBuffer as LayerRejecter::reject() // writes to Layer current state. See also b/119481871 diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e199ad55f8..27a0f6bbaf 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -576,7 +576,6 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart); - void latchAndReleaseBuffer(const sp& layer); void commitTransaction() REQUIRES(mStateLock); void commitOffscreenLayers(); bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, -- cgit v1.2.3-59-g8ed1b From 2e1608ff49148a8d99c2e33897fa0e5c3ce532c2 Mon Sep 17 00:00:00 2001 From: Mikael Pessa Date: Fri, 19 Jul 2019 11:25:35 -0700 Subject: Add per-buffer perfetto trace points for SurfaceFlinger frame events In order to track how buffers move through the system, we add per-buffer perfetto trace points for SurfaceFlinger. The majority of these were already tracked through TimeStats, so the new tracing was built on top of TimeStats. Test: atest libsurfaceflinger_unittest Run trace with: { adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace <& displayId, if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); + mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + presentFence, TimeStats::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); + mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + actualPresentTime, + TimeStats::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 5f494ff3d5..6cad3c7d07 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -45,6 +45,14 @@ BufferQueueLayer::~BufferQueueLayer() { void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { mConsumer->setReleaseFence(releaseFence); + + // Prevent tracing the same release multiple times. + if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { + mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + TimeStats::FrameEvent::RELEASE_FENCE); + mPreviousReleasedFrameNumber = mPreviousFrameNumber; + } } void BufferQueueLayer::setTransformHint(uint32_t orientation) const { @@ -355,9 +363,15 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mQueuedFrames--; } + uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); + mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber, + mQueueItems[0].mFenceTime, + TimeStats::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); + mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + TimeStats::FrameEvent::LATCH); mQueueItems.removeAt(0); } @@ -373,6 +387,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t status_t BufferQueueLayer::updateActiveBuffer() { // update the active buffer + mPreviousBufferId = getCurrentBufferId(); mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; layerCompositionState.buffer = mActiveBuffer; @@ -413,6 +428,11 @@ void BufferQueueLayer::latchPerFrameState( // ----------------------------------------------------------------------- void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); + mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), TimeStats::FrameEvent::POST); + ATRACE_CALL(); // Add this buffer from our internal queue tracker { // Autolock scope diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 3bc625e462..bf3f917196 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -128,6 +128,9 @@ private: uint64_t mPreviousFrameNumber{0}; bool mUpdateTexImageFailed{false}; + uint64_t mPreviousBufferId = 0; + uint64_t mPreviousReleasedFrameNumber = 0; + // Local copy of the queued contents of the incoming BufferQueue mutable Mutex mQueueItemLock; Condition mQueueItemCondition; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e0804ff50e..4a8261d99f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -87,6 +87,14 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { break; } } + + // Prevent tracing the same release multiple times. + if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { + mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + TimeStats::FrameEvent::RELEASE_FENCE); + mPreviousReleasedFrameNumber = mPreviousFrameNumber; + } } void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { @@ -226,7 +234,11 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); + mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); + mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + TimeStats::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -561,8 +573,13 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } + const uint64_t bufferID = getCurrentBufferId(); mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); + mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + TimeStats::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); + mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + TimeStats::FrameEvent::LATCH); mCurrentStateModified = false; @@ -576,6 +593,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } + mPreviousBufferId = getCurrentBufferId(); mActiveBuffer = s.buffer; mActiveBufferFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; @@ -586,6 +604,7 @@ status_t BufferStateLayer::updateActiveBuffer() { status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { // TODO(marissaw): support frame history events + mPreviousFrameNumber = mCurrentFrameNumber; mCurrentFrameNumber = mFrameNumber; return NO_ERROR; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cc670087ac..c060ca8e76 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -156,6 +156,9 @@ private: mutable uint32_t mFrameNumber{0}; sp mPreviousReleaseFence; + uint64_t mPreviousBufferId = 0; + uint64_t mPreviousFrameNumber = 0; + uint64_t mPreviousReleasedFrameNumber = 0; mutable bool mCurrentStateModified = false; bool mReleasePreviousBuffer = false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9107189d52..aa3970eb3a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -376,6 +376,14 @@ public: int32_t getSequence() const { return sequence; } + // For tracing. + // TODO: Replace with raw buffer id from buffer metadata when that becomes available. + // GraphicBuffer::getId() does not provide a reliable global identifier. Since the traces + // creates its tracks by buffer id and has no way of associating a buffer back to the process + // that created it, the current implementation is only sufficient for cases where a buffer is + // only used within a single layer. + uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; } + // ----------------------------------------------------------------------- // Virtuals diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e8049239ba..6543089101 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -513,6 +513,8 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); + mTimeStats->initializeTracing(); + // wait patiently for the window manager death const String16 name("window"); mWindowManager = defaultServiceManager()->getService(name); diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp new file mode 100644 index 0000000000..9e1d5033b2 --- /dev/null +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -0,0 +1,15 @@ +cc_library_static { + name: "libtimestats", + defaults: ["surfaceflinger_defaults"], + srcs: [ + "TimeStats.cpp" + ], + export_include_dirs: ["."], + static_libs: [ + "libperfetto_client_experimental", + ], + shared_libs: [ + "libtimestats_proto", + "libui", + ], +} diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 3e3ab18e8f..b66e4cfe4f 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -30,10 +30,141 @@ #include #include +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource); + namespace android { namespace impl { +void TimeStats::initializeTracing() { + perfetto::TracingInitArgs args; + args.backends = perfetto::kSystemBackend; + perfetto::Tracing::Initialize(args); + registerTracingDataSource(); +} + +void TimeStats::registerTracingDataSource() { + perfetto::DataSourceDescriptor dsd; + dsd.set_name(kTimeStatsDataSource); + TimeStatsDataSource::Register(dsd); +} + +void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) { + TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) { + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + std::lock_guard lock(mTraceMutex); + mTraceTracker[layerID].layerName = layerName; + } + }); +} + +void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration) { + TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + duration](TimeStatsDataSource::TraceContext ctx) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + // Complete current trace. + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + }); +} + +void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime) { + TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + startTime](TimeStatsDataSource::TraceContext ctx) { + const nsecs_t signalTime = fence->getSignalTime(); + if (signalTime != Fence::SIGNAL_TIME_INVALID) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + } else { + mTraceTracker[layerID].pendingFences[bufferID].push_back( + {.frameNumber = frameNumber, + .type = type, + .fence = fence, + .startTime = startTime}); + } + } + }); +} + +void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID) { + if (mTraceTracker[layerID].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + for (size_t i = 0; i < pendingFences.size(); ++i) { + auto& pendingFence = pendingFences[i]; + + nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; + if (pendingFence.fence && pendingFence.fence->isValid()) { + signalTime = pendingFence.fence->getSignalTime(); + if (signalTime == Fence::SIGNAL_TIME_PENDING) { + continue; + } + } + + if (signalTime != Fence::SIGNAL_TIME_INVALID && + systemTime() - signalTime < kFenceSignallingDeadline) { + traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + pendingFence.startTime, signalTime); + } + + pendingFences.erase(pendingFences.begin() + i); + --i; + } + } +} + +void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(timestamp); + auto* event = packet->set_graphics_frame_event()->set_buffer_event(); + event->set_buffer_id(static_cast(bufferID)); + event->set_frame_number(frameNumber); + event->set_type(type); + + if (mTraceTracker.find(layerID) != mTraceTracker.end() && + !mTraceTracker[layerID].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerID].layerName; + event->set_layer_name(layerName.c_str(), layerName.size()); + } + + if (duration > 0) { + event->set_duration_ns(duration); + } +} + +void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, + FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime) { + nsecs_t timestamp = endTime; + nsecs_t duration = 0; + if (startTime > 0 && startTime < endTime) { + timestamp = startTime; + duration = endTime - startTime; + } + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); +} + void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { ATRACE_CALL(); @@ -76,6 +207,8 @@ std::string TimeStats::miniDump() { mTimeStatsTracker.size()); android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n", mTimeStats.stats.size()); + android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", + mTraceTracker.size()); return result; } @@ -407,14 +540,17 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, } void TimeStats::onDestroy(int32_t layerID) { - if (!mEnabled.load()) return; - ATRACE_CALL(); ALOGV("[%d]-onDestroy", layerID); + { + std::lock_guard lock(mMutex); + mTimeStatsTracker.erase(layerID); + } - std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - mTimeStatsTracker.erase(layerID); + { + std::lock_guard traceLock(mTraceMutex); + mTraceTracker.erase(layerID); + } } void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index eed711158a..470137a431 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -16,13 +16,12 @@ #pragma once +#include +#include +#include #include #include - -#include - #include - #include #include @@ -37,8 +36,32 @@ namespace android { class TimeStats { public: + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; + virtual ~TimeStats() = default; + // Sets up the perfetto tracing backend and data source. + virtual void initializeTracing() = 0; + // Registers the data source with the perfetto backend. Called as part of initializeTracing() + // and should not be called manually outside of tests. Public to allow for substituting a + // perfetto::kInProcessBackend in tests. + virtual void registerTracingDataSource() = 0; + // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or + // traceFence() for each layer. + virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0; + // Creates a trace point at the timestamp provided. + virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0) = 0; + // Creates a trace point after the provided fence has been signalled. If a startTime is provided + // the trace will have be timestamped from startTime until fence signalling time. If no + // startTime is provided, a durationless trace point will be created timestamped at fence + // signalling time. If the fence hasn't signalled yet, the trace point will be created the next + // time after signalling a trace call for this buffer occurs. + virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0; + virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; virtual std::string miniDump() = 0; @@ -66,6 +89,13 @@ public: // Source of truth is RefrehRateStats. virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; virtual void setPresentFenceGlobal(const std::shared_ptr& presentFence) = 0; + + static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats"; + + // The maximum amount of time a fence has to signal before it is discarded. + // Used to avoid fence's from previous traces generating new trace points in later ones. + // Public for testing. + static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds }; namespace impl { @@ -87,6 +117,13 @@ class TimeStats : public android::TimeStats { std::shared_ptr presentFence; }; + struct PendingFence { + uint64_t frameNumber; + FrameEvent::BufferEventType type; + std::shared_ptr fence; + nsecs_t startTime; + }; + struct LayerRecord { std::string layerName; // This is the index in timeRecords, at which the timestamps for that @@ -98,6 +135,12 @@ class TimeStats : public android::TimeStats { std::deque timeRecords; }; + struct TraceRecord { + std::string layerName; + using BufferID = uint64_t; + std::unordered_map> pendingFences; + }; + struct PowerTime { int32_t powerMode = HWC_POWER_MODE_OFF; nsecs_t prevTime = 0; @@ -109,8 +152,23 @@ class TimeStats : public android::TimeStats { }; public: + class TimeStatsDataSource : public perfetto::DataSource { + virtual void OnSetup(const SetupArgs&) override{}; + virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); }; + virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); }; + }; + TimeStats() = default; + void initializeTracing() override; + void registerTracingDataSource() override; + void traceNewLayer(int32_t layerID, const std::string& layerName) override; + void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration = 0) override; + void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, FrameEvent::BufferEventType type, + nsecs_t startTime = 0) override; + void parseArgs(bool asProto, const Vector& args, std::string& result) override; bool isEnabled() override; std::string miniDump() override; @@ -142,6 +200,20 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: + // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates + // trace points for them. + void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID); + // Creates a trace point by translating a start time and an end time to a timestamp and + // duration. If startTime is later than end time it sets end time as the timestamp and the + // duration to 0. Used by traceFence(). + void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime); + void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0); + bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); @@ -160,6 +232,9 @@ private: PowerTime mPowerTime; GlobalRecord mGlobalRecord; + std::mutex mTraceMutex; + std::unordered_map mTraceTracker; + static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_LAYER_STATS = 200; }; diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 644cd7e698..57851bc850 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -34,7 +34,9 @@ cc_test { ], static_libs: [ "libgmock", + "libperfetto_client_experimental", "librenderengine", + "libtimestats", "libtrace_proto", ], header_libs: [ diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 4917bc2a51..0eedf9b7b1 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -36,7 +36,7 @@ cc_test { ":libsurfaceflinger_sources", "libsurfaceflinger_unittest_main.cpp", "CachingTest.cpp", - "CompositionTest.cpp", + "CompositionTest.cpp", "DispSyncSourceTest.cpp", "DisplayIdentificationTest.cpp", "DisplayTransactionTest.cpp", @@ -69,7 +69,13 @@ cc_test { "libgmock", "libcompositionengine", "libcompositionengine_mocks", + "libperfetto_client_experimental", "librenderengine_mocks", + "libtimestats", + "perfetto_trace_protos", + ], + shared_libs: [ + "libsurfaceflinger", ], header_libs: [ "libsurfaceflinger_headers", diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index f35758debf..f01e603f20 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -17,18 +17,17 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include #include #include - #include +#include #include #include #include #include -#include "TimeStats/TimeStats.h" - #include "libsurfaceflinger_unittest_main.h" using namespace android::surfaceflinger; @@ -110,6 +109,15 @@ public: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + // Need to initialize tracing in process for testing, and only once per test suite. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } } ~TimeStatsTest() { @@ -118,6 +126,13 @@ public: ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } + void SetUp() override { + mTimeStats = std::make_unique(); + mTimeStats->registerTracingDataSource(); + } + + void TearDown() override { mTimeStats.reset(); } + std::string inputCommand(InputCommand cmd, bool useProto); void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts); @@ -132,8 +147,22 @@ public: } } + // Each tracing session can be used for a single block of Start -> Stop. + static std::unique_ptr getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(TimeStats::kTimeStatsDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; + } + std::mt19937 mRandomEngine = std::mt19937(std::random_device()()); - std::unique_ptr mTimeStats = std::make_unique(); + std::unique_ptr mTimeStats; + FenceToFenceTimeMap fenceFactory; }; std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { @@ -210,6 +239,330 @@ int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) { return distr(mRandomEngine); } +TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) { + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + mTimeStats->traceNewLayer(layerID, layerName); + + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + mTimeStats->traceNewLayer(layerID, layerName); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + tracingSession->StopBlocking(); +} + +TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) { + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const int32_t secondLayerID = 6; + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceNewLayer(secondLayerID, layerName); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n"); + tracingSession->StopBlocking(); + + mTimeStats->onDestroy(layerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + mTimeStats->onDestroy(layerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + mTimeStats->onDestroy(secondLayerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); +} + +TEST_F(TimeStatsTest, canTraceAfterAddingLayer) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 1; + const uint32_t bufferID = 2; + const uint64_t frameNumber = 3; + const nsecs_t timestamp = 4; + const nsecs_t duration = 5; + const auto type = TimeStats::FrameEvent::POST; + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 1); + + const auto& packet = trace.packet().Get(0); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + ASSERT_TRUE(buffer_event.has_duration_ns()); + EXPECT_EQ(buffer_event.duration_ns(), duration); + } +} + +TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + // Trace. + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + const nsecs_t timestamp = systemTime(); + fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. + + const auto& packet = trace.packet().Get(1); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + EXPECT_FALSE(buffer_event.has_duration_ns()); + } +} + +TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 + 100000; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 + 100000; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), signalTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), signalTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); +} + +TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline; + + auto tracingSession = getTracingSessionForTest(); + auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); + // Create extra trace packet to trigger and finalize any previous fence packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); +} + +TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + const nsecs_t duration = 1234; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 - duration; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 - duration; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), startTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event1.duration_ns(), duration); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), startTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event2.duration_ns(), duration); +} + TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); ASSERT_TRUE(mTimeStats->isEnabled()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index b1634a8da7..542c70a8fb 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -28,6 +28,14 @@ public: TimeStats(); ~TimeStats() override; + MOCK_METHOD0(initializeTracing, void()); + MOCK_METHOD0(registerTracingDataSource, void()); + MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); + MOCK_METHOD6(traceTimestamp, + void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD6(traceFence, + void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, + FrameEvent::BufferEventType, nsecs_t)); MOCK_METHOD3(parseArgs, void(bool, const Vector&, std::string&)); MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD0(miniDump, std::string()); -- cgit v1.2.3-59-g8ed1b From 90092f4335b7360b149a57ee759df778e099ff87 Mon Sep 17 00:00:00 2001 From: Mikael Pessa Date: Mon, 26 Aug 2019 17:22:04 -0700 Subject: Refactor: Pull tracing out of TimeStats. The tracing in TimeStats ended up having no actual overlap with current TimeStats functionality. This CL pulls all tracing related code out into its own class. Test: atest libsurfaceflinger_unittest and manually inspected traces. Run trace with: { adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace <deleteTextureAsync(mTextureName); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void BufferLayer::useSurfaceDamage() { @@ -314,17 +317,17 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, - presentFence, TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, - actualPresentTime, - TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + actualPresentTime, + FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6cad3c7d07..4da39e4d6f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -29,6 +29,7 @@ #include "LayerRejecter.h" #include "SurfaceInterceptor.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -48,9 +49,9 @@ void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -337,6 +338,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mQueueItems.clear(); mQueuedFrames = 0; mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } // Once we have hit this state, the shadow queue may no longer @@ -366,12 +368,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber, - mQueueItems[0].mFenceTime, - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mQueueItems[0].mFenceTime, + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); } @@ -429,9 +431,9 @@ void BufferQueueLayer::latchPerFrameState( void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { const int32_t layerID = getSequence(); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, - systemTime(), TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), FrameTracer::FrameEvent::POST); ATRACE_CALL(); // Add this buffer from our internal queue tracker diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4a8261d99f..e7d1b63b03 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -32,6 +32,7 @@ #include "BufferStateLayer.h" #include "ColorLayer.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -90,9 +91,9 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -236,9 +237,9 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi const int32_t layerID = getSequence(); mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, - TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -569,17 +570,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse status_t err = bindTextureImage(); if (err != NO_ERROR) { mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp new file mode 100644 index 0000000000..7cbb8d8b7c --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -0,0 +1,173 @@ +/* + * Copyright 2019 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 "FrameTracer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "FrameTracer.h" + +#include + +#include + +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource); + +namespace android { + +void FrameTracer::initialize() { + perfetto::TracingInitArgs args; + args.backends = perfetto::kSystemBackend; + perfetto::Tracing::Initialize(args); + registerDataSource(); +} + +void FrameTracer::registerDataSource() { + perfetto::DataSourceDescriptor dsd; + dsd.set_name(kFrameTracerDataSource); + FrameTracerDataSource::Register(dsd); +} + +void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + std::lock_guard lock(mTraceMutex); + mTraceTracker[layerID].layerName = layerName; + } + }); +} + +void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + duration](FrameTracerDataSource::TraceContext ctx) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + // Complete current trace. + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + }); +} + +void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + startTime](FrameTracerDataSource::TraceContext ctx) { + const nsecs_t signalTime = fence->getSignalTime(); + if (signalTime != Fence::SIGNAL_TIME_INVALID) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + } else { + mTraceTracker[layerID].pendingFences[bufferID].push_back( + {.frameNumber = frameNumber, + .type = type, + .fence = fence, + .startTime = startTime}); + } + } + }); +} + +void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, + int32_t layerID, uint64_t bufferID) { + if (mTraceTracker[layerID].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + for (size_t i = 0; i < pendingFences.size(); ++i) { + auto& pendingFence = pendingFences[i]; + + nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; + if (pendingFence.fence && pendingFence.fence->isValid()) { + signalTime = pendingFence.fence->getSignalTime(); + if (signalTime == Fence::SIGNAL_TIME_PENDING) { + continue; + } + } + + if (signalTime != Fence::SIGNAL_TIME_INVALID && + systemTime() - signalTime < kFenceSignallingDeadline) { + traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + pendingFence.startTime, signalTime); + } + + pendingFences.erase(pendingFences.begin() + i); + --i; + } + } +} + +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(timestamp); + auto* event = packet->set_graphics_frame_event()->set_buffer_event(); + event->set_buffer_id(static_cast(bufferID)); + event->set_frame_number(frameNumber); + event->set_type(type); + + if (mTraceTracker.find(layerID) != mTraceTracker.end() && + !mTraceTracker[layerID].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerID].layerName; + event->set_layer_name(layerName.c_str(), layerName.size()); + } + + if (duration > 0) { + event->set_duration_ns(duration); + } +} + +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, + FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime) { + nsecs_t timestamp = endTime; + nsecs_t duration = 0; + if (startTime > 0 && startTime < endTime) { + timestamp = startTime; + duration = endTime - startTime; + } + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); +} + +void FrameTracer::onDestroy(int32_t layerID) { + std::lock_guard traceLock(mTraceMutex); + mTraceTracker.erase(layerID); +} + +std::string FrameTracer::miniDump() { + std::string result = "FrameTracer miniDump:\n"; + std::lock_guard lock(mTraceMutex); + android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", + mTraceTracker.size()); + return result; +} + +} // namespace android diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h new file mode 100644 index 0000000000..d34ad81fee --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -0,0 +1,105 @@ +/* + * Copyright 2019 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 +#include +#include + +#include +#include + +namespace android { + +class FrameTracer { +public: + class FrameTracerDataSource : public perfetto::DataSource { + virtual void OnSetup(const SetupArgs&) override{}; + virtual void OnStart(const StartArgs&) override{}; + virtual void OnStop(const StopArgs&) override{}; + }; + + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; + + ~FrameTracer() = default; + + // Sets up the perfetto tracing backend and data source. + void initialize(); + // Registers the data source with the perfetto backend. Called as part of initialize() + // and should not be called manually outside of tests. Public to allow for substituting a + // perfetto::kInProcessBackend in tests. + void registerDataSource(); + // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or + // traceFence() for each layer. + void traceNewLayer(int32_t layerID, const std::string& layerName); + // Creates a trace point at the timestamp provided. + void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration = 0); + // Creates a trace point after the provided fence has been signalled. If a startTime is provided + // the trace will have be timestamped from startTime until fence signalling time. If no + // startTime is provided, a durationless trace point will be created timestamped at fence + // signalling time. If the fence hasn't signalled yet, the trace point will be created the next + // time after signalling a trace call for this buffer occurs. + void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, FrameEvent::BufferEventType type, + nsecs_t startTime = 0); + + // Takes care of cleanup when a layer is destroyed. + void onDestroy(int32_t layerID); + + std::string miniDump(); + + static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame"; + + // The maximum amount of time a fence has to signal before it is discarded. + // Used to avoid fences from previous traces generating new trace points in later ones. + // Public for testing. + static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds + +private: + struct PendingFence { + uint64_t frameNumber; + FrameEvent::BufferEventType type; + std::shared_ptr fence; + nsecs_t startTime; + }; + + struct TraceRecord { + std::string layerName; + using BufferID = uint64_t; + std::unordered_map> pendingFences; + }; + + // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates + // trace points for them. + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID); + // Creates a trace point by translating a start time and an end time to a timestamp and + // duration. If startTime is later than end time it sets end time as the timestamp and the + // duration to 0. Used by traceFence(). + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, + nsecs_t startTime, nsecs_t endTime); + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0); + + std::mutex mTraceMutex; + std::unordered_map mTraceTracker; +}; + +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..106d505faa 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -57,6 +57,7 @@ #include "Colorizer.h" #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" +#include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" @@ -1343,7 +1344,9 @@ void Layer::dumpFrameEvents(std::string& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6543089101..e8902b3c62 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -98,6 +98,7 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "Effects/Daltonizer.h" +#include "FrameTracer/FrameTracer.h" #include "RegionSamplingThread.h" #include "Scheduler/DispSync.h" #include "Scheduler/DispSyncSource.h" @@ -257,6 +258,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), mInterceptor(mFactory.createSurfaceInterceptor(this)), mTimeStats(mFactory.createTimeStats()), + mFrameTracer(std::make_unique()), mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mPhaseOffsets(mFactory.createPhaseOffsets()) {} @@ -513,7 +515,7 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); - mTimeStats->initializeTracing(); + mFrameTracer->initialize(); // wait patiently for the window manager death const String16 name("window"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8408ef5174..c7cc07e490 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -94,6 +94,7 @@ class MessageBase; class RefreshRateOverlay; class RegionSamplingThread; class TimeStats; +class FrameTracer; namespace compositionengine { class DisplaySurface; @@ -996,6 +997,7 @@ private: bool mTracingEnabled = false; bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false; const std::shared_ptr mTimeStats; + const std::unique_ptr mFrameTracer; bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount = 0; std::atomic mHwcFrameMissedCount = 0; diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp index 9e1d5033b2..2080a3847e 100644 --- a/services/surfaceflinger/TimeStats/Android.bp +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -2,12 +2,9 @@ cc_library_static { name: "libtimestats", defaults: ["surfaceflinger_defaults"], srcs: [ - "TimeStats.cpp" + "TimeStats.cpp", ], export_include_dirs: ["."], - static_libs: [ - "libperfetto_client_experimental", - ], shared_libs: [ "libtimestats_proto", "libui", diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index b66e4cfe4f..b01fa81594 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -30,141 +30,10 @@ #include #include -PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource); - namespace android { namespace impl { -void TimeStats::initializeTracing() { - perfetto::TracingInitArgs args; - args.backends = perfetto::kSystemBackend; - perfetto::Tracing::Initialize(args); - registerTracingDataSource(); -} - -void TimeStats::registerTracingDataSource() { - perfetto::DataSourceDescriptor dsd; - dsd.set_name(kTimeStatsDataSource); - TimeStatsDataSource::Register(dsd); -} - -void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) { - TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; - } - }); -} - -void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, - duration](TimeStatsDataSource::TraceContext ctx) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); - }); -} - -void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, - startTime](TimeStatsDataSource::TraceContext ctx) { - const nsecs_t signalTime = fence->getSignalTime(); - if (signalTime != Fence::SIGNAL_TIME_INVALID) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); - } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( - {.frameNumber = frameNumber, - .type = type, - .fence = fence, - .startTime = startTime}); - } - } - }); -} - -void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; - for (size_t i = 0; i < pendingFences.size(); ++i) { - auto& pendingFence = pendingFences[i]; - - nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; - if (pendingFence.fence && pendingFence.fence->isValid()) { - signalTime = pendingFence.fence->getSignalTime(); - if (signalTime == Fence::SIGNAL_TIME_PENDING) { - continue; - } - } - - if (signalTime != Fence::SIGNAL_TIME_INVALID && - systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, - pendingFence.startTime, signalTime); - } - - pendingFences.erase(pendingFences.begin() + i); - --i; - } - } -} - -void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(timestamp); - auto* event = packet->set_graphics_frame_event()->set_buffer_event(); - event->set_buffer_id(static_cast(bufferID)); - event->set_frame_number(frameNumber); - event->set_type(type); - - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; - event->set_layer_name(layerName.c_str(), layerName.size()); - } - - if (duration > 0) { - event->set_duration_ns(duration); - } -} - -void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, - FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime) { - nsecs_t timestamp = endTime; - nsecs_t duration = 0; - if (startTime > 0 && startTime < endTime) { - timestamp = startTime; - duration = endTime - startTime; - } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); -} - void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { ATRACE_CALL(); @@ -207,8 +76,6 @@ std::string TimeStats::miniDump() { mTimeStatsTracker.size()); android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n", mTimeStats.stats.size()); - android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", - mTraceTracker.size()); return result; } @@ -542,15 +409,8 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, void TimeStats::onDestroy(int32_t layerID) { ATRACE_CALL(); ALOGV("[%d]-onDestroy", layerID); - { - std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); - } - - { - std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); - } + std::lock_guard lock(mMutex); + mTimeStatsTracker.erase(layerID); } void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 470137a431..9ebc1adc90 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -17,8 +17,6 @@ #pragma once #include -#include -#include #include #include #include @@ -36,32 +34,8 @@ namespace android { class TimeStats { public: - using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; - virtual ~TimeStats() = default; - // Sets up the perfetto tracing backend and data source. - virtual void initializeTracing() = 0; - // Registers the data source with the perfetto backend. Called as part of initializeTracing() - // and should not be called manually outside of tests. Public to allow for substituting a - // perfetto::kInProcessBackend in tests. - virtual void registerTracingDataSource() = 0; - // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or - // traceFence() for each layer. - virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0; - // Creates a trace point at the timestamp provided. - virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0) = 0; - // Creates a trace point after the provided fence has been signalled. If a startTime is provided - // the trace will have be timestamped from startTime until fence signalling time. If no - // startTime is provided, a durationless trace point will be created timestamped at fence - // signalling time. If the fence hasn't signalled yet, the trace point will be created the next - // time after signalling a trace call for this buffer occurs. - virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0; - virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; virtual std::string miniDump() = 0; @@ -89,13 +63,6 @@ public: // Source of truth is RefrehRateStats. virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; virtual void setPresentFenceGlobal(const std::shared_ptr& presentFence) = 0; - - static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats"; - - // The maximum amount of time a fence has to signal before it is discarded. - // Used to avoid fence's from previous traces generating new trace points in later ones. - // Public for testing. - static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds }; namespace impl { @@ -117,13 +84,6 @@ class TimeStats : public android::TimeStats { std::shared_ptr presentFence; }; - struct PendingFence { - uint64_t frameNumber; - FrameEvent::BufferEventType type; - std::shared_ptr fence; - nsecs_t startTime; - }; - struct LayerRecord { std::string layerName; // This is the index in timeRecords, at which the timestamps for that @@ -135,12 +95,6 @@ class TimeStats : public android::TimeStats { std::deque timeRecords; }; - struct TraceRecord { - std::string layerName; - using BufferID = uint64_t; - std::unordered_map> pendingFences; - }; - struct PowerTime { int32_t powerMode = HWC_POWER_MODE_OFF; nsecs_t prevTime = 0; @@ -152,23 +106,8 @@ class TimeStats : public android::TimeStats { }; public: - class TimeStatsDataSource : public perfetto::DataSource { - virtual void OnSetup(const SetupArgs&) override{}; - virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); }; - virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); }; - }; - TimeStats() = default; - void initializeTracing() override; - void registerTracingDataSource() override; - void traceNewLayer(int32_t layerID, const std::string& layerName) override; - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration = 0) override; - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, FrameEvent::BufferEventType type, - nsecs_t startTime = 0) override; - void parseArgs(bool asProto, const Vector& args, std::string& result) override; bool isEnabled() override; std::string miniDump() override; @@ -200,20 +139,6 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates - // trace points for them. - void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID); - // Creates a trace point by translating a start time and an end time to a timestamp and - // duration. If startTime is later than end time it sets end time as the timestamp and the - // duration to 0. Used by traceFence(). - void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime); - void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0); - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); @@ -232,9 +157,6 @@ private: PowerTime mPowerTime; GlobalRecord mGlobalRecord; - std::mutex mTraceMutex; - std::unordered_map mTraceTracker; - static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_LAYER_STATS = 200; }; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 0eedf9b7b1..8d98af6298 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -51,6 +51,7 @@ cc_test { "RefreshRateStatsTest.cpp", "RegionSamplingTest.cpp", "TimeStatsTest.cpp", + "FrameTracerTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplay.cpp", "mock/DisplayHardware/MockPowerAdvisor.cpp", @@ -63,6 +64,7 @@ cc_test { "mock/MockNativeWindowSurface.cpp", "mock/MockSurfaceInterceptor.cpp", "mock/MockTimeStats.cpp", + "mock/MockFrameTracer.cpp", "mock/system/window/MockNativeWindow.cpp", ], static_libs: [ diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp new file mode 100644 index 0000000000..b5af591e25 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2019 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 "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include +#include + +#include "libsurfaceflinger_unittest_main.h" + +using namespace google::protobuf; + +namespace android { +namespace { + +class FrameTracerTest : public testing::Test { +public: + FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + // Need to initialize tracing in process for testing, and only once per test suite. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } + } + + ~FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + void SetUp() override { + mFrameTracer = std::make_unique(); + mFrameTracer->registerDataSource(); + } + + void TearDown() override { mFrameTracer.reset(); } + + // Each tracing session can be used for a single block of Start -> Stop. + static std::unique_ptr getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(FrameTracer::kFrameTracerDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; + } + + std::unique_ptr mFrameTracer; + FenceToFenceTimeMap fenceFactory; +}; + +TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + mFrameTracer->traceNewLayer(layerID, layerName); + + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + mFrameTracer->traceNewLayer(layerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + tracingSession->StopBlocking(); +} + +TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const int32_t secondLayerID = 6; + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(secondLayerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); + tracingSession->StopBlocking(); + + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(secondLayerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); +} + +TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 1; + const uint32_t bufferID = 2; + const uint64_t frameNumber = 3; + const nsecs_t timestamp = 4; + const nsecs_t duration = 5; + const auto type = FrameTracer::FrameEvent::POST; + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 1); + + const auto& packet = trace.packet().Get(0); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + ASSERT_TRUE(buffer_event.has_duration_ns()); + EXPECT_EQ(buffer_event.duration_ns(), duration); + } +} + +TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + // Trace. + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + const nsecs_t timestamp = systemTime(); + fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. + + const auto& packet = trace.packet().Get(1); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + EXPECT_FALSE(buffer_event.has_duration_ns()); + } +} + +TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 + 100000; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 + 100000; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), signalTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), signalTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); +} + +TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline; + + auto tracingSession = getTracingSessionForTest(); + auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); + // Create extra trace packet to trigger and finalize any previous fence packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); +} + +TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t duration = 1234; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 - duration; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 - duration; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), startTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event1.duration_ns(), duration); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), startTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event2.duration_ns(), duration); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index f01e603f20..ffacbfef16 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -20,8 +20,8 @@ #include #include #include + #include -#include #include #include @@ -109,15 +109,6 @@ public: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - // Need to initialize tracing in process for testing, and only once per test suite. - static bool wasInitialized = false; - if (!wasInitialized) { - perfetto::TracingInitArgs args; - args.backends = perfetto::kInProcessBackend; - perfetto::Tracing::Initialize(args); - wasInitialized = true; - } } ~TimeStatsTest() { @@ -126,13 +117,6 @@ public: ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } - void SetUp() override { - mTimeStats = std::make_unique(); - mTimeStats->registerTracingDataSource(); - } - - void TearDown() override { mTimeStats.reset(); } - std::string inputCommand(InputCommand cmd, bool useProto); void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts); @@ -147,22 +131,8 @@ public: } } - // Each tracing session can be used for a single block of Start -> Stop. - static std::unique_ptr getTracingSessionForTest() { - perfetto::TraceConfig cfg; - cfg.set_duration_ms(500); - cfg.add_buffers()->set_size_kb(1024); - auto* ds_cfg = cfg.add_data_sources()->mutable_config(); - ds_cfg->set_name(TimeStats::kTimeStatsDataSource); - - auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); - tracingSession->Setup(cfg); - return tracingSession; - } - std::mt19937 mRandomEngine = std::mt19937(std::random_device()()); - std::unique_ptr mTimeStats; - FenceToFenceTimeMap fenceFactory; + std::unique_ptr mTimeStats = std::make_unique(); }; std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { @@ -239,330 +209,6 @@ int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) { return distr(mRandomEngine); } -TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mTimeStats->traceNewLayer(layerID, layerName); - - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - mTimeStats->traceNewLayer(layerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - tracingSession->StopBlocking(); -} - -TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceNewLayer(secondLayerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n"); - tracingSession->StopBlocking(); - - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(secondLayerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); -} - -TEST_F(TimeStatsTest, canTraceAfterAddingLayer) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; - const uint32_t bufferID = 2; - const uint64_t frameNumber = 3; - const nsecs_t timestamp = 4; - const nsecs_t duration = 5; - const auto type = TimeStats::FrameEvent::POST; - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 1); - - const auto& packet = trace.packet().Get(0); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - ASSERT_TRUE(buffer_event.has_duration_ns()); - EXPECT_EQ(buffer_event.duration_ns(), duration); - } -} - -TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - // Trace. - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - const nsecs_t timestamp = systemTime(); - fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. - - const auto& packet = trace.packet().Get(1); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - EXPECT_FALSE(buffer_event.has_duration_ns()); - } -} - -TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 + 100000; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 + 100000; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), signalTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), signalTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); -} - -TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline; - - auto tracingSession = getTracingSessionForTest(); - auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); - // Create extra trace packet to trigger and finalize any previous fence packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); -} - -TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t duration = 1234; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 - duration; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 - duration; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), startTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event1.duration_ns(), duration); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), startTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event2.duration_ns(), duration); -} - TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); ASSERT_TRUE(mTimeStats->isEnabled()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp new file mode 100644 index 0000000000..358dfdb856 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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 "mock/MockFrameTracer.h" + +namespace android { +namespace mock { + +// Explicit default instantiation is recommended. +FrameTracer::FrameTracer() = default; +FrameTracer::~FrameTracer() = default; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h new file mode 100644 index 0000000000..f768b8114d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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 + +#include "FrameTracer/FrameTracer.h" + +namespace android { +namespace mock { + +class FrameTracer : public android::FrameTracer { +public: + FrameTracer(); + ~FrameTracer(); + + MOCK_METHOD0(initialize, void()); + MOCK_METHOD0(registerDataSource, void()); + MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); + MOCK_METHOD6(traceTimestamp, + void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD6(traceFence, + void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, + FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD0(miniDump, std::string()); +}; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index 542c70a8fb..b1634a8da7 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -28,14 +28,6 @@ public: TimeStats(); ~TimeStats() override; - MOCK_METHOD0(initializeTracing, void()); - MOCK_METHOD0(registerTracingDataSource, void()); - MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); - MOCK_METHOD6(traceTimestamp, - void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); - MOCK_METHOD6(traceFence, - void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, - FrameEvent::BufferEventType, nsecs_t)); MOCK_METHOD3(parseArgs, void(bool, const Vector&, std::string&)); MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD0(miniDump, std::string()); -- cgit v1.2.3-59-g8ed1b From a2468669661cd9bcd1258ec908716c4b85ef007e Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 7 Mar 2019 21:31:06 -0800 Subject: SF: Move layer visibility state to CompositionEngine The layer visibility/coverage state was the last bit of display-dependent data that had not yet been moved to OutputLayerCompositionState. This moves it, and fixes up all references to the data to get it in a display-dependent way. Test: atest libsurfaceflinger_unittest libcompositionengine_test Bug: 121291683 Change-Id: Id9f314f05b743212dba3a113df2baeb38fd19eb8 --- services/surfaceflinger/BufferLayer.cpp | 3 +- .../compositionengine/LayerFECompositionState.h | 4 -- .../compositionengine/impl/LayerCompositionState.h | 3 +- .../impl/OutputLayerCompositionState.h | 13 ++++++- .../CompositionEngine/src/Output.cpp | 2 +- .../CompositionEngine/src/OutputLayer.cpp | 11 ++---- .../src/OutputLayerCompositionState.cpp | 9 +++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 9 +++-- .../CompositionEngine/tests/OutputTest.cpp | 10 ++--- services/surfaceflinger/Layer.cpp | 44 +++++++++------------- services/surfaceflinger/Layer.h | 30 +-------------- services/surfaceflinger/SurfaceFlinger.cpp | 35 +++++++++-------- .../tests/unittests/CompositionTest.cpp | 22 ++++++++++- 13 files changed, 98 insertions(+), 97 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a8bdb799e7..a7970db473 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -158,7 +158,8 @@ std::optional BufferLayer::prepareClientComposition finished = true; return; } - under.orSelf(layer->visibleRegion); + + under.orSelf(layer->getScreenBounds()); }); // if not everything below us is covered, we plug the holes! Region holes(targetSettings.clip.subtract(under)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 6a0caf0746..b066cd1bda 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -56,10 +56,6 @@ struct LayerFECompositionState { Region geomActiveTransparentRegion; FloatRect geomLayerBounds; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - Region geomVisibleRegion; - /* * Presentation */ diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h index ab01c209d1..726c850780 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h @@ -21,6 +21,7 @@ #include #include +#include namespace android { @@ -28,7 +29,7 @@ namespace compositionengine::impl { struct LayerCompositionState { /* - * State intended to be set by LayerFE::getCompositionState + * State set by LayerFE::getCompositionState */ LayerFECompositionState frontEnd; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index de0f08ace8..13474492af 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -40,9 +40,18 @@ class HWComposer; namespace compositionengine::impl { struct OutputLayerCompositionState { - // The region of this layer which is visible on this output + // The portion of the layer that is not obscured by opaque layers on top Region visibleRegion; + // The portion of the layer that is not obscured and is also opaque + Region visibleNonTransparentRegion; + + // The portion of the layer that is obscured by opaque layers on top + Region coveredRegion; + + // The visibleRegion transformed to output space + Region outputSpaceVisibleRegion; + // If true, client composition will be used on this output bool forceClientComposition{false}; @@ -62,7 +71,7 @@ struct OutputLayerCompositionState { ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; // The Z order index of this layer on this output - uint32_t z; + uint32_t z{0}; /* * HWC state diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 903ca9891c..9f4f259f7c 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -601,7 +601,7 @@ std::vector Output::generateClientCompositionReques const auto& layerFEState = layer->getLayer().getState().frontEnd; auto& layerFE = layer->getLayerFE(); - const Region clip(viewportRegion.intersect(layerFEState.geomVisibleRegion)); + const Region clip(viewportRegion.intersect(layerState.visibleRegion)); ALOGV("Layer: %s", layerFE.getDebugName()); if (clip.isEmpty()) { ALOGV(" Skipping for empty clip"); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 73bb03be02..21f0ce8b15 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -315,11 +315,6 @@ void OutputLayer::updateCompositionState(bool includeGeometry) { ? outputState.targetDataspace : layerFEState.dataspace; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - mState.visibleRegion = outputState.transform.transform( - layerFEState.geomVisibleRegion.intersect(outputState.viewport)); - // These are evaluated every frame as they can potentially change at any // time. if (layerFEState.forceClientComposition || !profile.isDataspaceSupported(mState.dataspace)) { @@ -421,13 +416,13 @@ void OutputLayer::writeOutputIndependentGeometryStateToHWC( void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) { const auto& outputDependentState = getState(); - // TODO(lpique): b/121291683 visibleRegion is output-dependent geometry + // TODO(lpique): b/121291683 outputSpaceVisibleRegion is output-dependent geometry // state and should not change every frame. - if (auto error = hwcLayer->setVisibleRegion(outputDependentState.visibleRegion); + if (auto error = hwcLayer->setVisibleRegion(outputDependentState.outputSpaceVisibleRegion); error != HWC2::Error::None) { ALOGE("[%s] Failed to set visible region: %s (%d)", mLayerFE->getDebugName(), to_string(error).c_str(), static_cast(error)); - outputDependentState.visibleRegion.dump(LOG_TAG); + outputDependentState.outputSpaceVisibleRegion.dump(LOG_TAG); } if (auto error = hwcLayer->setDataspace(outputDependentState.dataspace); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index e320bee4e1..ad668b6b89 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -41,6 +41,15 @@ void OutputLayerCompositionState::dump(std::string& out) const { out.append(" "); dumpVal(out, "visibleRegion", visibleRegion); + out.append(" "); + dumpVal(out, "visibleNonTransparentRegion", visibleNonTransparentRegion); + + out.append(" "); + dumpVal(out, "coveredRegion", coveredRegion); + + out.append(" "); + dumpVal(out, "output visibleRegion", outputSpaceVisibleRegion); + out.append(" "); dumpVal(out, "forceClientComposition", forceClientComposition); dumpVal(out, "clearClientTarget", clearClientTarget); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 75e960c575..2276dc3691 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -574,7 +574,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const half4 kColor; static const Rect kDisplayFrame; - static const Region kVisibleRegion; + static const Region kOutputSpaceVisibleRegion; static const mat4 kColorTransform; static const Region kSurfaceDamage; static const HdrMetadata kHdrMetadata; @@ -590,7 +590,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.sourceCrop = kSourceCrop; outputLayerState.z = kZOrder; outputLayerState.bufferTransform = static_cast(kBufferTransform); - outputLayerState.visibleRegion = kVisibleRegion; + outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion; outputLayerState.dataspace = kDataspace; mLayerState.frontEnd.blendMode = kBlendMode; @@ -629,7 +629,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { } void expectPerFrameCommonCalls(SimulateUnsupported unsupported = SimulateUnsupported::None) { - EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kVisibleRegion))) + EXPECT_CALL(*mHwcLayer, setVisibleRegion(RegionEq(kOutputSpaceVisibleRegion))) .WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setDataspace(kDataspace)).WillOnce(Return(kError)); EXPECT_CALL(*mHwcLayer, setColorTransform(kColorTransform)) @@ -673,7 +673,8 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, 84.f / 255.f}; const Rect OutputLayerWriteStateToHWCTest::kDisplayFrame{1001, 1002, 1003, 10044}; -const Region OutputLayerWriteStateToHWCTest::kVisibleRegion{Rect{1005, 1006, 1007, 1008}}; +const Region OutputLayerWriteStateToHWCTest::kOutputSpaceVisibleRegion{ + Rect{1005, 1006, 1007, 1008}}; const mat4 OutputLayerWriteStateToHWCTest::kColorTransform{ 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 1d5f2f0d54..b0e8e3699c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -661,9 +661,9 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) impl::OutputLayerCompositionState leftOutputLayerState; leftOutputLayerState.clearClientTarget = false; + leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}}; leftLayerState.frontEnd.isOpaque = true; const half3 leftLayerColor{1.f, 0.f, 0.f}; @@ -672,9 +672,9 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = false; + rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}}; rightLayerState.frontEnd.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; @@ -735,9 +735,9 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit impl::OutputLayerCompositionState outputLayerState; outputLayerState.clearClientTarget = false; + outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}}; impl::LayerCompositionState layerState; - layerState.frontEnd.geomVisibleRegion = Region{Rect{3000, 0, 4000, 1000}}; layerState.frontEnd.isOpaque = true; EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); @@ -790,16 +790,16 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { impl::OutputLayerCompositionState leftOutputLayerState; leftOutputLayerState.clearClientTarget = true; + leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.geomVisibleRegion = Region{Rect{0, 0, 1000, 1000}}; leftLayerState.frontEnd.isOpaque = true; impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = true; + rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.geomVisibleRegion = Region{Rect{1000, 0, 2000, 1000}}; rightLayerState.frontEnd.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 557d0bba27..b669421103 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -443,10 +443,6 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo const auto& drawingState{getDrawingState()}; compositionState.forceClientComposition = false; - // TODO(lpique): b/121291683 Remove this one we are sure we don't need the - // value recomputed / set every frame. - compositionState.geomVisibleRegion = visibleRegion; - compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); compositionState.dataspace = mCurrentDataSpace; compositionState.colorTransform = getColorTransform(); @@ -567,27 +563,6 @@ bool Layer::isSecure() const { return (s.flags & layer_state_t::eLayerSecure); } -void Layer::setVisibleRegion(const Region& visibleRegion) { - // always called from main thread - this->visibleRegion = visibleRegion; -} - -void Layer::setCoveredRegion(const Region& coveredRegion) { - // always called from main thread - this->coveredRegion = coveredRegion; -} - -void Layer::setVisibleNonTransparentRegion(const Region& setVisibleNonTransparentRegion) { - // always called from main thread - this->visibleNonTransparentRegion = setVisibleNonTransparentRegion; -} - -void Layer::clearVisibilityRegions() { - visibleRegion.clear(); - visibleNonTransparentRegion.clear(); - coveredRegion.clear(); -} - // ---------------------------------------------------------------------------- // transaction // ---------------------------------------------------------------------------- @@ -1202,7 +1177,8 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; - info.mVisibleRegion = visibleRegion; + + info.mVisibleRegion = debugGetVisibleRegionOnDefaultDisplay(); info.mSurfaceDamageRegion = surfaceDamageRegion; info.mLayerStack = getLayerStack(); info.mX = ds.active_legacy.transform.tx(); @@ -1826,7 +1802,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(), [&]() { return layerInfo->mutable_position(); }); LayerProtoHelper::writeToProto(mBounds, [&]() { return layerInfo->mutable_bounds(); }); - LayerProtoHelper::writeToProto(visibleRegion, + LayerProtoHelper::writeToProto(debugGetVisibleRegionOnDefaultDisplay(), [&]() { return layerInfo->mutable_visible_region(); }); LayerProtoHelper::writeToProto(surfaceDamageRegion, [&]() { return layerInfo->mutable_damage_region(); }); @@ -2003,6 +1979,20 @@ compositionengine::OutputLayer* Layer::findOutputLayerForDisplay( return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionLayer().get()); } +Region Layer::debugGetVisibleRegionOnDefaultDisplay() const { + sp displayDevice = mFlinger->getDefaultDisplayDeviceLocked(); + if (displayDevice == nullptr) { + return {}; + } + + auto outputLayer = findOutputLayerForDisplay(displayDevice); + if (outputLayer == nullptr) { + return {}; + } + + return outputLayer->getState().visibleRegion; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 23809e85be..02a7d36b4d 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -98,10 +98,6 @@ class Layer : public compositionengine::LayerFE { public: mutable bool contentDirty{false}; - // regions below are in window-manager space - Region visibleRegion; - Region coveredRegion; - Region visibleNonTransparentRegion; Region surfaceDamageRegion; // Layer serial number. This gives layers an explicit ordering, so we @@ -518,30 +514,6 @@ public: */ uint32_t doTransaction(uint32_t transactionFlags); - /* - * setVisibleRegion - called to set the new visible region. This gives - * a chance to update the new visible region or record the fact it changed. - */ - void setVisibleRegion(const Region& visibleRegion); - - /* - * setCoveredRegion - called when the covered region changes. The covered - * region corresponds to any area of the surface that is covered - * (transparently or not) by another surface. - */ - void setCoveredRegion(const Region& coveredRegion); - - /* - * setVisibleNonTransparentRegion - called when the visible and - * non-transparent region changes. - */ - void setVisibleNonTransparentRegion(const Region& visibleNonTransparentRegion); - - /* - * Clear the visible, covered, and non-transparent regions. - */ - void clearVisibilityRegions(); - /* * latchBuffer - called each time the screen is redrawn and returns whether * the visible regions need to be recomputed (this is a fairly heavy @@ -684,6 +656,8 @@ public: compositionengine::OutputLayer* findOutputLayerForDisplay( const sp& display) const; + Region debugGetVisibleRegionOnDefaultDisplay() const; + protected: // constant sp mFlinger; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 49a6800409..11e970232d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2793,7 +2793,6 @@ void SurfaceFlinger::computeVisibleRegions( */ Region transparentRegion; - // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(s); @@ -2826,7 +2825,6 @@ void SurfaceFlinger::computeVisibleRegions( } if (visibleRegion.isEmpty()) { - layer->clearVisibilityRegions(); return; } @@ -2839,12 +2837,21 @@ void SurfaceFlinger::computeVisibleRegions( // subtract the opaque region covered by the layers above us visibleRegion.subtractSelf(aboveOpaqueLayers); + // Get coverage information for the layer as previously displayed + auto prevOutputLayer = display->getOutputLayerForLayer(compositionLayer.get()); + // TODO(b/121291683): Define this as a constant in Region.h + const Region kEmptyRegion; + const Region& oldVisibleRegion = + prevOutputLayer ? prevOutputLayer->getState().visibleRegion : kEmptyRegion; + const Region& oldCoveredRegion = + prevOutputLayer ? prevOutputLayer->getState().coveredRegion : kEmptyRegion; + // compute this layer's dirty region if (layer->contentDirty) { // we need to invalidate the whole region dirty = visibleRegion; // as well, as the old visible region - dirty.orSelf(layer->visibleRegion); + dirty.orSelf(oldVisibleRegion); layer->contentDirty = false; } else { /* compute the exposed region: @@ -2860,8 +2867,6 @@ void SurfaceFlinger::computeVisibleRegions( * exposed because of a resize. */ const Region newExposed = visibleRegion - coveredRegion; - const Region oldVisibleRegion = layer->visibleRegion; - const Region oldCoveredRegion = layer->coveredRegion; const Region oldExposed = oldVisibleRegion - oldCoveredRegion; dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed); } @@ -2873,16 +2878,13 @@ void SurfaceFlinger::computeVisibleRegions( // Update aboveOpaqueLayers for next (lower) layer aboveOpaqueLayers.orSelf(opaqueRegion); - // Store the visible region in screen space - layer->setVisibleRegion(visibleRegion); - layer->setCoveredRegion(coveredRegion); - layer->setVisibleNonTransparentRegion( - visibleRegion.subtract(transparentRegion)); + // Compute the visible non-transparent region + Region visibleNonTransparentRegion = visibleRegion.subtract(transparentRegion); - // Setup an output layer for this output if the layer is - // visible on this output + // Setup an output layer for this output if the layer is visible on this + // output const auto& displayState = display->getState(); - Region drawRegion(displayState.transform.transform(layer->visibleNonTransparentRegion)); + Region drawRegion(displayState.transform.transform(visibleNonTransparentRegion)); drawRegion.andSelf(displayState.bounds); if (drawRegion.isEmpty()) { return; @@ -2895,8 +2897,11 @@ void SurfaceFlinger::computeVisibleRegions( outLayersSortedByZ.emplace_back( display->getOrCreateOutputLayer(displayId, compositionLayer, layerFE)); auto& outputLayerState = outLayersSortedByZ.back()->editState(); - outputLayerState.visibleRegion = displayState.transform.transform( - layer->visibleRegion.intersect(displayState.viewport)); + outputLayerState.visibleRegion = std::move(visibleRegion); + outputLayerState.visibleNonTransparentRegion = std::move(visibleNonTransparentRegion); + outputLayerState.coveredRegion = std::move(coveredRegion); + outputLayerState.outputSpaceVisibleRegion = displayState.transform.transform( + outputLayerState.visibleRegion.intersect(displayState.viewport)); }); outOpaqueRegion = aboveOpaqueLayers; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 425768e244..9e4d57e7dc 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -614,6 +614,12 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so gtet the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() << "layerSettings was not expected to be empty in " + "setupREBufferCompositionCommonCallExpectations " + "verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); @@ -657,6 +663,12 @@ struct BaseLayerProperties { displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() + << "layerSettings was not expected to be empty in " + "setupREColorCompositionCallExpectations verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], @@ -727,6 +739,12 @@ struct SecureLayerProperties : public BaseLayerProperties displaySettings.clip); // screen capture adds an additional color layer as an alpha // prefill, so get the back layer. + if (layerSettings.empty()) { + ADD_FAILURE() << "layerSettings was not expected to be empty in " + "setupInsecureREBufferCompositionCommonCallExpectations " + "verification lambda"; + return NO_ERROR; + } renderengine::LayerSettings layer = layerSettings.back(); EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); @@ -786,7 +804,6 @@ struct BaseLayerVariant { layerDrawingState.color = half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2], LayerProperties::COLOR[3]); layer->computeBounds(FloatRect(0, 0, 100, 100), ui::Transform()); - layer->setVisibleRegion(Region(Rect(0, 0, 100, 100))); return layer; } @@ -801,6 +818,9 @@ struct BaseLayerVariant { layer->getCompositionLayer(), layer)); + outputLayers.back()->editState().visibleRegion = Region(Rect(0, 0, 100, 100)); + outputLayers.back()->editState().outputSpaceVisibleRegion = Region(Rect(0, 0, 100, 100)); + test->mDisplay->getCompositionDisplay()->setOutputLayersOrderedByZ(std::move(outputLayers)); Mock::VerifyAndClear(test->mComposer); -- cgit v1.2.3-59-g8ed1b From 4244e0356083fba0a367b9cb5422cd24d567518a Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 11:27:49 -0700 Subject: Created bufferInfo to track buffer data in a single place (1/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: Iba1be05c4b038f0b678150deed8e673bf1e7710b --- services/surfaceflinger/BufferLayer.cpp | 124 ++++++++++++++++---------- services/surfaceflinger/BufferLayer.h | 46 ++++++---- services/surfaceflinger/BufferQueueLayer.cpp | 65 ++++---------- services/surfaceflinger/BufferQueueLayer.h | 15 +--- services/surfaceflinger/BufferStateLayer.cpp | 126 ++++++++++----------------- services/surfaceflinger/BufferStateLayer.h | 20 ++--- services/surfaceflinger/ColorLayer.cpp | 9 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/Layer.cpp | 42 +++------ services/surfaceflinger/Layer.h | 12 +-- 10 files changed, 204 insertions(+), 257 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 90a02b3ad9..bca15e6903 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -81,7 +81,7 @@ void BufferLayer::useSurfaceDamage() { if (mFlinger->mForceFullDamage) { surfaceDamageRegion = Region::INVALID_REGION; } else { - surfaceDamageRegion = getDrawingSurfaceDamage(); + surfaceDamageRegion = mBufferInfo.mSurfaceDamage; } } @@ -187,7 +187,7 @@ std::optional BufferLayer::prepareClientComposition // Query the texture matrix given our current filtering mode. float textureMatrix[16]; setFilteringEnabled(useFiltering); - getDrawingTransformMatrix(textureMatrix); + memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix)); if (getTransformToDisplayInverse()) { /* @@ -254,8 +254,8 @@ std::optional BufferLayer::prepareClientComposition bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - getDrawingApi() == NATIVE_WINDOW_API_MEDIA && + return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && + mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } @@ -268,7 +268,7 @@ void BufferLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { // Normal buffer layers - compositionState.hdrMetadata = getDrawingHdrMetadata(); + compositionState.hdrMetadata = mBufferInfo.mHdrMetadata; compositionState.compositionType = mPotentialCursor ? Hwc2::IComposerClient::Composition::CURSOR : Hwc2::IComposerClient::Composition::DEVICE; @@ -300,13 +300,13 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } // Update mFrameTracker. - nsecs_t desiredPresentTime = getDesiredPresentTime(); + nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); const int32_t layerID = getSequence(); mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); - std::shared_ptr frameReadyFence = getCurrentFenceTime(); + std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -394,6 +394,9 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } + BufferInfo oldBufferInfo = mBufferInfo; + gatherBufferInfo(); + mRefreshPending = true; mFrameLatencyNeeded = true; if (oldBuffer == nullptr) { @@ -402,43 +405,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - ui::Dataspace dataSpace = getDrawingDataSpace(); - // translate legacy dataspaces to modern dataspaces - switch (dataSpace) { - case ui::Dataspace::SRGB: - dataSpace = ui::Dataspace::V0_SRGB; - break; - case ui::Dataspace::SRGB_LINEAR: - dataSpace = ui::Dataspace::V0_SRGB_LINEAR; - break; - case ui::Dataspace::JFIF: - dataSpace = ui::Dataspace::V0_JFIF; - break; - case ui::Dataspace::BT601_625: - dataSpace = ui::Dataspace::V0_BT601_625; - break; - case ui::Dataspace::BT601_525: - dataSpace = ui::Dataspace::V0_BT601_525; - break; - case ui::Dataspace::BT709: - dataSpace = ui::Dataspace::V0_BT709; - break; - default: - break; - } - mCurrentDataSpace = dataSpace; - - Rect crop(getDrawingCrop()); - const uint32_t transform(getDrawingTransform()); - const uint32_t scalingMode(getDrawingScalingMode()); - const bool transformToDisplayInverse(getTransformToDisplayInverse()); - if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || - (scalingMode != mCurrentScalingMode) || - (transformToDisplayInverse != mTransformToDisplayInverse)) { - mCurrentCrop = crop; - mCurrentTransform = transform; - mCurrentScalingMode = scalingMode; - mTransformToDisplayInverse = transformToDisplayInverse; + if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) || + (mBufferInfo.mTransform != oldBufferInfo.mTransform) || + (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) || + (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) { recomputeVisibleRegions = true; } @@ -510,7 +480,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { return mOverrideScalingMode; } - return mCurrentScalingMode; + return mBufferInfo.mScaleMode; } bool BufferLayer::isProtected() const { @@ -626,7 +596,7 @@ Rect BufferLayer::getBufferSize(const State& s) const { uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -662,7 +632,7 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -685,6 +655,66 @@ void BufferLayer::latchAndReleaseBuffer() { releasePendingBuffer(systemTime()); } +PixelFormat BufferLayer::getPixelFormat() const { + return mBufferInfo.mPixelFormat; +} + +bool BufferLayer::getTransformToDisplayInverse() const { + return mBufferInfo.mTransformToDisplayInverse; +} + +Rect BufferLayer::getBufferCrop() const { + // this is the crop rectangle that applies to the buffer + // itself (as opposed to the window) + if (!mBufferInfo.mCrop.isEmpty()) { + // if the buffer crop is defined, we use that + return mBufferInfo.mCrop; + } else if (mActiveBuffer != nullptr) { + // otherwise we use the whole buffer + return mActiveBuffer->getBounds(); + } else { + // if we don't have a buffer yet, we use an empty/invalid crop + return Rect(); + } +} + +uint32_t BufferLayer::getBufferTransform() const { + return mBufferInfo.mTransform; +} + +ui::Dataspace BufferLayer::getDataSpace() const { + return mBufferInfo.mDataspace; +} + +ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { + ui::Dataspace updatedDataspace = dataspace; + // translate legacy dataspaces to modern dataspaces + switch (dataspace) { + case ui::Dataspace::SRGB: + updatedDataspace = ui::Dataspace::V0_SRGB; + break; + case ui::Dataspace::SRGB_LINEAR: + updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR; + break; + case ui::Dataspace::JFIF: + updatedDataspace = ui::Dataspace::V0_JFIF; + break; + case ui::Dataspace::BT601_625: + updatedDataspace = ui::Dataspace::V0_BT601_625; + break; + case ui::Dataspace::BT601_525: + updatedDataspace = ui::Dataspace::V0_BT601_525; + break; + case ui::Dataspace::BT709: + updatedDataspace = ui::Dataspace::V0_BT709; + break; + default: + break; + } + + return updatedDataspace; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index ee44cbe836..e8838e812c 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -106,6 +106,14 @@ public: // Should only be called on the main thread. void latchAndReleaseBuffer() override; + bool getTransformToDisplayInverse() const override; + + Rect getBufferCrop() const override; + + uint32_t getBufferTransform() const override; + + ui::Dataspace getDataSpace() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -115,18 +123,7 @@ private: virtual bool fenceHasSignaled() const = 0; virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; - virtual nsecs_t getDesiredPresentTime() = 0; - virtual std::shared_ptr getCurrentFenceTime() const = 0; - - virtual void getDrawingTransformMatrix(float *matrix) = 0; - virtual uint32_t getDrawingTransform() const = 0; - virtual ui::Dataspace getDrawingDataSpace() const = 0; - virtual Rect getDrawingCrop() const = 0; - virtual uint32_t getDrawingScalingMode() const = 0; - virtual Region getDrawingSurfaceDamage() const = 0; - virtual const HdrMetadata& getDrawingHdrMetadata() const = 0; - virtual int getDrawingApi() const = 0; - virtual PixelFormat getPixelFormat() const = 0; + PixelFormat getPixelFormat() const; virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; @@ -148,6 +145,25 @@ private: virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; protected: + struct BufferInfo { + nsecs_t mDesiredPresentTime; + std::shared_ptr mFenceTime; + sp mFence; + float mTransformMatrix[16]; + uint32_t mTransform{0}; + ui::Dataspace mDataspace; + Rect mCrop; + uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; + Region mSurfaceDamage; + HdrMetadata mHdrMetadata; + int mApi; + PixelFormat mPixelFormat; + bool mTransformToDisplayInverse{false}; + }; + + BufferInfo mBufferInfo; + virtual void gatherBufferInfo() = 0; + /* * compositionengine::LayerFE overrides */ @@ -171,16 +187,14 @@ protected: bool mRefreshPending{false}; + ui::Dataspace translateDataspace(ui::Dataspace dataspace); + private: // Returns true if this layer requires filtering bool needsFiltering(const sp& displayDevice) const override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; - - bool mTransformToDisplayInverse{false}; - // main thread. bool mBufferLatched{false}; // TODO: Use mActiveBuffer? diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 4da39e4d6f..e9e8e6e9dc 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -70,10 +70,6 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo return history; } -bool BufferQueueLayer::getTransformToDisplayInverse() const { - return mConsumer->getTransformToDisplayInverse(); -} - void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { if (!mConsumer->releasePendingBuffer()) { return; @@ -155,55 +151,12 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].mTimestamp <= expectedPresentTime; } -nsecs_t BufferQueueLayer::getDesiredPresentTime() { - return mConsumer->getTimestamp(); -} - -std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { - return mConsumer->getCurrentFenceTime(); -} - -void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { - return mConsumer->getTransformMatrix(matrix); -} - // NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's // These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state // so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's // current buffer so the consumer functions start with "getCurrent". // // This results in the rather confusing functions below. -uint32_t BufferQueueLayer::getDrawingTransform() const { - return mConsumer->getCurrentTransform(); -} - -ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const { - return mConsumer->getCurrentDataSpace(); -} - -Rect BufferQueueLayer::getDrawingCrop() const { - return mConsumer->getCurrentCrop(); -} - -uint32_t BufferQueueLayer::getDrawingScalingMode() const { - return mConsumer->getCurrentScalingMode(); -} - -Region BufferQueueLayer::getDrawingSurfaceDamage() const { - return mConsumer->getSurfaceDamage(); -} - -const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const { - return mConsumer->getCurrentHdrMetadata(); -} - -int BufferQueueLayer::getDrawingApi() const { - return mConsumer->getCurrentApi(); -} - -PixelFormat BufferQueueLayer::getPixelFormat() const { - return mFormat; -} uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); @@ -422,7 +375,7 @@ void BufferQueueLayer::latchPerFrameState( compositionState.buffer = mActiveBuffer; compositionState.bufferSlot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; - compositionState.acquireFence = mConsumer->getCurrentFence(); + compositionState.acquireFence = mBufferInfo.mFence; } // ----------------------------------------------------------------------- @@ -573,4 +526,20 @@ uint32_t BufferQueueLayer::getProducerStickyTransform() const { return static_cast(producerStickyTransform); } +void BufferQueueLayer::gatherBufferInfo() { + mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp(); + mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime(); + mBufferInfo.mFence = mConsumer->getCurrentFence(); + mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = mConsumer->getCurrentTransform(); + mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace()); + mBufferInfo.mCrop = mConsumer->getCurrentCrop(); + mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode(); + mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage(); + mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata(); + mBufferInfo.mApi = mConsumer->getCurrentApi(); + mBufferInfo.mPixelFormat = mFormat; + mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index bf3f917196..6cbafb31ce 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -46,7 +46,6 @@ public: std::vector getOccupancyHistory(bool forceFlush) override; - bool getTransformToDisplayInverse() const override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; @@ -66,18 +65,6 @@ public: bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -103,6 +90,8 @@ private: // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- protected: + void gatherBufferInfo() override; + void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onSidebandStreamChanged() override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e7d1b63b03..07a83b9d35 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -125,10 +125,6 @@ bool BufferStateLayer::willPresentCurrentTransaction() const { (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)); } -bool BufferStateLayer::getTransformToDisplayInverse() const { - return mCurrentState.transformToDisplayInverse; -} - void BufferStateLayer::pushPendingState() { if (!mCurrentState.modified) { return; @@ -400,75 +396,6 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mCurrentState.desiredPresentTime <= expectedPresentTime; } -nsecs_t BufferStateLayer::getDesiredPresentTime() { - return getDrawingState().desiredPresentTime; -} - -std::shared_ptr BufferStateLayer::getCurrentFenceTime() const { - return std::make_shared(getDrawingState().acquireFence); -} - -void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { - std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); -} - -uint32_t BufferStateLayer::getDrawingTransform() const { - return getDrawingState().transform; -} - -ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { - return getDrawingState().dataspace; -} - -// Crop that applies to the buffer -Rect BufferStateLayer::getDrawingCrop() const { - const State& s(getDrawingState()); - - if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBounds(); - } else if (s.buffer) { - Rect crop = s.crop; - crop.left = std::max(crop.left, 0); - crop.top = std::max(crop.top, 0); - uint32_t bufferWidth = s.buffer->getWidth(); - uint32_t bufferHeight = s.buffer->getHeight(); - if (bufferHeight <= std::numeric_limits::max() && - bufferWidth <= std::numeric_limits::max()) { - crop.right = std::min(crop.right, static_cast(bufferWidth)); - crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); - } - if (!crop.isValid()) { - // Crop rect is out of bounds, return whole buffer - return s.buffer->getBounds(); - } - return crop; - } - return s.crop; -} - -uint32_t BufferStateLayer::getDrawingScalingMode() const { - return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; -} - -Region BufferStateLayer::getDrawingSurfaceDamage() const { - return getDrawingState().surfaceDamageRegion; -} - -const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { - return getDrawingState().hdrMetadata; -} - -int BufferStateLayer::getDrawingApi() const { - return getDrawingState().api; -} - -PixelFormat BufferStateLayer::getPixelFormat() const { - if (!mActiveBuffer) { - return PIXEL_FORMAT_NONE; - } - return mActiveBuffer->format; -} - uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mFrameNumber; } @@ -506,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, - mCurrentTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -576,8 +503,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, @@ -622,7 +549,7 @@ void BufferStateLayer::latchPerFrameState( compositionState.buffer = s.buffer; compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); - compositionState.acquireFence = s.acquireFence; + compositionState.acquireFence = mBufferInfo.mFence; mFrameNumber++; } @@ -707,4 +634,47 @@ void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& mFreeHwcCacheSlots.push(hwcCacheSlot); mCachedBuffers.erase(clientCacheId); } + +void BufferStateLayer::gatherBufferInfo() { + const State& s(getDrawingState()); + + mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; + mBufferInfo.mFenceTime = std::make_shared(s.acquireFence); + mBufferInfo.mFence = s.acquireFence; + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), + mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = s.transform; + mBufferInfo.mDataspace = translateDataspace(s.dataspace); + mBufferInfo.mCrop = computeCrop(s); + mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; + mBufferInfo.mHdrMetadata = s.hdrMetadata; + mBufferInfo.mApi = s.api; + mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; +} + +Rect BufferStateLayer::computeCrop(const State& s) { + if (s.crop.isEmpty() && s.buffer) { + return s.buffer->getBounds(); + } else if (s.buffer) { + Rect crop = s.crop; + crop.left = std::max(crop.left, 0); + crop.top = std::max(crop.top, 0); + uint32_t bufferWidth = s.buffer->getWidth(); + uint32_t bufferHeight = s.buffer->getHeight(); + if (bufferHeight <= std::numeric_limits::max() && + bufferWidth <= std::numeric_limits::max()) { + crop.right = std::min(crop.right, static_cast(bufferWidth)); + crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); + } + if (!crop.isValid()) { + // Crop rect is out of bounds, return whole buffer + return s.buffer->getBounds(); + } + return crop; + } + return s.crop; +} + } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index c060ca8e76..086fd0a6ba 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -48,8 +48,6 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; - bool getTransformToDisplayInverse() const override; - uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { return flags; } @@ -106,19 +104,10 @@ public: bool fenceHasSignaled() const override; bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; +protected: + void gatherBufferInfo() override; + private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -140,6 +129,9 @@ private: void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + // Crop that applies to the buffer + Rect computeCrop(const State& s); + private: friend class SlotGenerationTest; void onFirstRef() override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 2ad7591b86..49b18102c7 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -99,11 +99,6 @@ void ColorLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; } -void ColorLayer::commitTransaction(const State& stateToCommit) { - Layer::commitTransaction(stateToCommit); - mCurrentDataSpace = mDrawingState.dataspace; -} - std::shared_ptr ColorLayer::getCompositionLayer() const { return mCompositionLayer; } @@ -112,6 +107,10 @@ bool ColorLayer::isOpaque(const Layer::State& s) const { return (s.flags & layer_state_t::eLayerOpaque) != 0; } +ui::Dataspace ColorLayer::getDataSpace() const { + return mDrawingState.dataspace; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 57c54c7e2c..16921df356 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -37,7 +37,7 @@ public: bool setDataspace(ui::Dataspace dataspace) override; - void commitTransaction(const State& stateToCommit) override; + ui::Dataspace getDataSpace() const override; bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c916f74291..f1a5175424 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -78,7 +78,6 @@ Layer::Layer(const LayerCreationArgs& args) mName(args.name), mClientRef(args.client), mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { - mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; @@ -259,23 +258,6 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -Rect Layer::getContentCrop() const { - // this is the crop rectangle that applies to the buffer - // itself (as opposed to the window) - Rect crop; - if (!mCurrentCrop.isEmpty()) { - // if the buffer crop is defined, we use that - crop = mCurrentCrop; - } else if (mActiveBuffer != nullptr) { - // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); - } else { - // if we don't have a buffer yet, we use an empty/invalid crop - crop.makeInvalid(); - } - return crop; -} - static Rect reduce(const Rect& win, const Region& exclude) { if (CC_LIKELY(exclude.isEmpty())) { return win; @@ -335,7 +317,7 @@ ui::Transform Layer::getBufferScaleTransform() const { int bufferWidth = mActiveBuffer->getWidth(); int bufferHeight = mActiveBuffer->getHeight(); - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); } @@ -442,9 +424,9 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio compositionState.geomLayerTransform = getTransform(); compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); compositionState.geomBufferSize = getBufferSize(drawingState); - compositionState.geomContentCrop = getContentCrop(); + compositionState.geomContentCrop = getBufferCrop(); compositionState.geomCrop = getCrop(drawingState); - compositionState.geomBufferTransform = mCurrentTransform; + compositionState.geomBufferTransform = getBufferTransform(); compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState); compositionState.geomLayerBounds = mBounds; @@ -466,7 +448,7 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.geomVisibleRegion = visibleRegion; compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); - compositionState.dataspace = mCurrentDataSpace; + compositionState.dataspace = getDataSpace(); compositionState.colorTransform = getColorTransform(); compositionState.colorTransformIsIdentity = !hasColorTransform(); compositionState.surfaceDamage = surfaceDamageRegion; @@ -543,7 +525,7 @@ std::optional Layer::prepareClientComposition( layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; layerSettings.alpha = alpha; - layerSettings.sourceDataspace = mCurrentDataSpace; + layerSettings.sourceDataspace = getDataSpace(); return layerSettings; } @@ -726,7 +708,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -1232,7 +1214,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(mCurrentDataSpace); + info.mDataSpace = static_cast(getDataSpace()); info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; @@ -1551,8 +1533,9 @@ bool Layer::hasColorTransform() const { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | - ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); + return !(getDataSpace() & + (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | + ui::Dataspace::RANGE_MASK)); } void Layer::setParent(const sp& layer) { @@ -1834,13 +1817,12 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); - LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), + LayerProtoHelper::writeToProto(ui::Transform(getBufferTransform()), layerInfo->mutable_buffer_transform()); } layerInfo->set_invalidate(contentDirty); layerInfo->set_is_protected(isProtected()); - layerInfo->set_dataspace( - dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_dataspace(dataspaceDetails(static_cast(getDataSpace()))); layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_curr_frame(mCurrentFrameNumber); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 23c1acd759..ea5b8447ad 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -330,7 +330,7 @@ public: virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); - ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } + virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; } // Before color management is introduced, contents on Android have to be // desaturated in order to match what they appears like visually. @@ -587,7 +587,12 @@ public: * returns the rectangle that crops the content of the layer and scales it * to the layer's size. */ - Rect getContentCrop() const; + virtual Rect getBufferCrop() const { return Rect(); } + + /* + * Returns the transform applied to the buffer. + */ + virtual uint32_t getBufferTransform() const { return 0; } /* * Returns if a frame is ready @@ -846,9 +851,6 @@ protected: // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; - ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; - Rect mCurrentCrop; - uint32_t mCurrentTransform{0}; // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; -- cgit v1.2.3-59-g8ed1b From d62d30645c41d703a241443de761ab9eaa0c99af Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 14:48:02 -0700 Subject: Moved info about activeBuffer into bufferInfo (2/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: I48c34141151370d9905c312239883f8374b884b9 --- services/surfaceflinger/BufferLayer.cpp | 53 +++++++++++++++------------- services/surfaceflinger/BufferLayer.h | 8 +++-- services/surfaceflinger/BufferQueueLayer.cpp | 14 ++++---- services/surfaceflinger/BufferQueueLayer.h | 1 - services/surfaceflinger/BufferStateLayer.cpp | 19 +++++----- services/surfaceflinger/Layer.cpp | 16 ++++----- services/surfaceflinger/Layer.h | 7 ++-- 7 files changed, 62 insertions(+), 56 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index bca15e6903..6a3d60f50c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -92,7 +92,7 @@ void BufferLayer::useEmptyDamage() { bool BufferLayer::isOpaque(const Layer::State& s) const { // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the // layer's opaque flag. - if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) { return false; } @@ -103,7 +103,7 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { bool BufferLayer::isVisible() const { bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (mActiveBuffer != nullptr || mSidebandStream != nullptr); + (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); return visible; @@ -144,7 +144,7 @@ std::optional BufferLayer::prepareClientComposition return result; } - if (CC_UNLIKELY(mActiveBuffer == 0)) { + if (CC_UNLIKELY(mBufferInfo.mBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -175,9 +175,9 @@ std::optional BufferLayer::prepareClientComposition const State& s(getDrawingState()); auto& layer = *result; if (!blackOutLayer) { - layer.source.buffer.buffer = mActiveBuffer; + layer.source.buffer.buffer = mBufferInfo.mBuffer; layer.source.buffer.isOpaque = isOpaque(s); - layer.source.buffer.fence = mActiveBufferFence; + layer.source.buffer.fence = mBufferInfo.mFence; layer.source.buffer.textureName = mTextureName; layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); @@ -256,7 +256,7 @@ bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && - mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); + mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } void BufferLayer::latchPerFrameState( @@ -276,7 +276,7 @@ void BufferLayer::latchPerFrameState( } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferLatched) { + if (mBufferInfo.mBuffer != nullptr) { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); } @@ -370,7 +370,8 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp oldBuffer = mActiveBuffer; + + BufferInfo oldBufferInfo = mBufferInfo; if (!allTransactionsSignaled(expectedPresentTime)) { mFlinger->setTransactionFlags(eTraversalNeeded); @@ -387,19 +388,16 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } - mBufferLatched = true; - err = updateFrameNumber(latchTime); if (err != NO_ERROR) { return false; } - BufferInfo oldBufferInfo = mBufferInfo; gatherBufferInfo(); mRefreshPending = true; mFrameLatencyNeeded = true; - if (oldBuffer == nullptr) { + if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; @@ -412,10 +410,11 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - if (oldBuffer != nullptr) { - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); - if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) { + if (oldBufferInfo.mBuffer != nullptr) { + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + if (bufWidth != uint32_t(oldBufferInfo.mBuffer->width) || + bufHeight != uint32_t(oldBufferInfo.mBuffer->height)) { recomputeVisibleRegions = true; } } @@ -484,7 +483,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - const sp& buffer(mActiveBuffer); + const sp& buffer(mBufferInfo.mBuffer); return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } @@ -588,12 +587,12 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect(getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return Rect::INVALID_RECT; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -624,12 +623,12 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return parentBounds; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -669,9 +668,9 @@ Rect BufferLayer::getBufferCrop() const { if (!mBufferInfo.mCrop.isEmpty()) { // if the buffer crop is defined, we use that return mBufferInfo.mCrop; - } else if (mActiveBuffer != nullptr) { + } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mActiveBuffer->getBounds(); + return mBufferInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -715,6 +714,10 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { return updatedDataspace; } +sp BufferLayer::getBuffer() const { + return mBufferInfo.mBuffer; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index e8838e812c..a685ea2305 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -114,6 +114,8 @@ public: ui::Dataspace getDataSpace() const override; + sp getBuffer() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -159,6 +161,9 @@ protected: int mApi; PixelFormat mPixelFormat; bool mTransformToDisplayInverse{false}; + + sp mBuffer; + int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; }; BufferInfo mBufferInfo; @@ -195,9 +200,6 @@ private: uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - // main thread. - bool mBufferLatched{false}; // TODO: Use mActiveBuffer? - // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame // and its parent layer is not bounded Rect getBufferSize(const State& s) const override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e9e8e6e9dc..a4f7bc23a4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -343,11 +343,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t status_t BufferQueueLayer::updateActiveBuffer() { // update the active buffer mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); + mBufferInfo.mBuffer = + mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { // this can only happen if the very first buffer was rejected. return BAD_VALUE; } @@ -372,9 +373,10 @@ void BufferQueueLayer::latchPerFrameState( return; } - compositionState.buffer = mActiveBuffer; - compositionState.bufferSlot = - (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; + compositionState.buffer = mBufferInfo.mBuffer; + compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) + ? 0 + : mBufferInfo.mBufferSlot; compositionState.acquireFence = mBufferInfo.mFence; } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 6cbafb31ce..43eb3eaab8 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -127,7 +127,6 @@ private: std::atomic mLastFrameNumberReceived{0}; bool mAutoRefresh{false}; - int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; // thread-safe std::atomic mQueuedFrames{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 07a83b9d35..afbe22854f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -53,12 +53,12 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) } BufferStateLayer::~BufferStateLayer() { - if (mActiveBuffer != nullptr) { - // Ensure that mActiveBuffer is uncached from RenderEngine here, as + if (mBufferInfo.mBuffer != nullptr) { + // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. auto& engine(mFlinger->getRenderEngine()); - engine.unbindExternalTextureBuffer(mActiveBuffer->getId()); + engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); } } @@ -433,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, - mBufferInfo.mTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer, + mBufferInfo.mCrop, mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -523,10 +523,10 @@ status_t BufferStateLayer::updateActiveBuffer() { } mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = s.buffer; - mActiveBufferFence = s.acquireFence; + mBufferInfo.mBuffer = s.buffer; + mBufferInfo.mFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; } @@ -650,7 +650,8 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; mBufferInfo.mApi = s.api; - mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mPixelFormat = + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f1a5175424..d0b9187d56 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -302,7 +302,7 @@ ui::Transform Layer::getBufferScaleTransform() const { // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g. // it isFixedSize) then there may be additional scaling not accounted // for in the layer transform. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return {}; } @@ -314,8 +314,8 @@ ui::Transform Layer::getBufferScaleTransform() const { return {}; } - int bufferWidth = mActiveBuffer->getWidth(); - int bufferHeight = mActiveBuffer->getHeight(); + int bufferWidth = getBuffer()->getWidth(); + int bufferHeight = getBuffer()->getHeight(); if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); @@ -332,7 +332,7 @@ ui::Transform Layer::getBufferScaleTransform() const { ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const { // We need to mirror this scaling to child surfaces or we will break the contract where WM can // treat child surfaces as pixels in the parent surface. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mEffectiveTransform; } return mEffectiveTransform * bufferScaleTransform; @@ -341,7 +341,7 @@ ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTrans FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const { // We need the pre scaled layer bounds when computing child bounds to make sure the child is // cropped to its parent layer after any buffer transform scaling is applied. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mBounds; } return bufferScaleTransform.inverse().transform(mBounds); @@ -740,7 +740,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const bool resizePending = ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && - (mActiveBuffer != nullptr); + (getBuffer() != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == nullptr) { flags |= eDontUpdateGeometryState; @@ -1220,7 +1220,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { - sp buffer = mActiveBuffer; + sp buffer = getBuffer(); if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1813,7 +1813,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) } } - auto buffer = mActiveBuffer; + auto buffer = getBuffer(); if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ea5b8447ad..d6cc27a801 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -382,7 +382,7 @@ public: // creates its tracks by buffer id and has no way of associating a buffer back to the process // that created it, the current implementation is only sufficient for cases where a buffer is // only used within a single layer. - uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; } + uint64_t getCurrentBufferId() const { return getBuffer() ? getBuffer()->getId() : 0; } // ----------------------------------------------------------------------- // Virtuals @@ -594,6 +594,8 @@ public: */ virtual uint32_t getBufferTransform() const { return 0; } + virtual sp getBuffer() const { return nullptr; } + /* * Returns if a frame is ready */ @@ -844,9 +846,6 @@ protected: // main thread sp mSidebandStream; - // Active buffer fields - sp mActiveBuffer; - sp mActiveBufferFence; // False if the buffer and its contents have been previously used for GPU // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; -- cgit v1.2.3-59-g8ed1b From f83ce183aa13db5e66b5fd5e6bd09de5169373c5 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 12 Sep 2019 14:43:08 -0700 Subject: Corrected drawingTransformMatrix The transformMatrix needed to be calculated in prepareClientComposition so storing it in BufferInfo was incorrect. Instead, allow the transformMatrix to get calculated when prepareClientComposition but avoid using the consumer for BufferQueueLayer. Also combined getDrawingTransformMatrix and setFilteringEnabled since setFilteringEnabled was only used to update the transformMatrix before getting it. BufferQueueLayers no longer go through the consumer to get the transformMatrix and just directly calculate the matrix using the GLUtils class. Fixes: 140759442 Test: atest android.view.cts.ASurfaceControlTest Change-Id: I09179de275bd905960fb366e45e36fb9874bc0b3 --- services/surfaceflinger/BufferLayer.cpp | 9 +++++++-- services/surfaceflinger/BufferLayer.h | 9 +++++---- services/surfaceflinger/BufferQueueLayer.cpp | 12 ------------ services/surfaceflinger/BufferQueueLayer.h | 4 ---- services/surfaceflinger/BufferStateLayer.cpp | 14 +++----------- services/surfaceflinger/BufferStateLayer.h | 6 ------ 6 files changed, 15 insertions(+), 39 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 486b042873..b060b047af 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -187,8 +188,7 @@ std::optional BufferLayer::prepareClientComposition // Query the texture matrix given our current filtering mode. float textureMatrix[16]; - setFilteringEnabled(useFiltering); - memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix)); + getDrawingTransformMatrix(useFiltering, textureMatrix); if (getTransformToDisplayInverse()) { /* @@ -719,6 +719,11 @@ sp BufferLayer::getBuffer() const { return mBufferInfo.mBuffer; } +void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { + GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, filteringEnabled); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index a685ea2305..f0a30e319a 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -127,6 +127,10 @@ private: PixelFormat getPixelFormat() const; + // Computes the transform matrix using the setFilteringEnabled to determine whether the + // transform matrix should be computed for use with bilinear filtering. + void getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]); + virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; virtual bool getAutoRefresh() const = 0; @@ -137,8 +141,6 @@ private: virtual bool hasFrameUpdate() const = 0; - virtual void setFilteringEnabled(bool enabled) = 0; - virtual status_t bindTextureImage() = 0; virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) = 0; @@ -151,9 +153,8 @@ protected: nsecs_t mDesiredPresentTime; std::shared_ptr mFenceTime; sp mFence; - float mTransformMatrix[16]; uint32_t mTransform{0}; - ui::Dataspace mDataspace; + ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN}; Rect mCrop; uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; Region mSurfaceDamage; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index a9e364a00d..5f7975085a 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -151,13 +151,6 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].mTimestamp <= expectedPresentTime; } -// NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's -// These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state -// so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's -// current buffer so the consumer functions start with "getCurrent". -// -// This results in the rather confusing functions below. - uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); uint64_t frameNumber = mQueueItems[0].mFrameNumber; @@ -220,10 +213,6 @@ bool BufferQueueLayer::hasFrameUpdate() const { return mQueuedFrames > 0; } -void BufferQueueLayer::setFilteringEnabled(bool enabled) { - return mConsumer->setFilteringEnabled(enabled); -} - status_t BufferQueueLayer::bindTextureImage() { return mConsumer->bindTextureImage(); } @@ -532,7 +521,6 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp(); mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime(); mBufferInfo.mFence = mConsumer->getCurrentFence(); - mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix); mBufferInfo.mTransform = mConsumer->getCurrentTransform(); mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace()); mBufferInfo.mCrop = mConsumer->getCurrentCrop(); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 43eb3eaab8..9374741ddb 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -46,7 +46,6 @@ public: std::vector getOccupancyHistory(bool forceFlush) override; - // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; @@ -65,7 +64,6 @@ public: bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; @@ -75,8 +73,6 @@ private: bool hasFrameUpdate() const override; - void setFilteringEnabled(bool enabled) override; - status_t bindTextureImage() override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index afbe22854f..509deaf996 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -432,11 +432,6 @@ bool BufferStateLayer::hasFrameUpdate() const { return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } -void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer, - mBufferInfo.mCrop, mBufferInfo.mTransform, enabled); -} - status_t BufferStateLayer::bindTextureImage() { const State& s(getDrawingState()); auto& engine(mFlinger->getRenderEngine()); @@ -545,10 +540,8 @@ void BufferStateLayer::latchPerFrameState( return; } - const State& s(getDrawingState()); - - compositionState.buffer = s.buffer; - compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); + compositionState.buffer = mBufferInfo.mBuffer; + compositionState.bufferSlot = mBufferInfo.mBufferSlot; compositionState.acquireFence = mBufferInfo.mFence; mFrameNumber++; @@ -641,8 +634,6 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; mBufferInfo.mFenceTime = std::make_shared(s.acquireFence); mBufferInfo.mFence = s.acquireFence; - std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), - mBufferInfo.mTransformMatrix); mBufferInfo.mTransform = s.transform; mBufferInfo.mDataspace = translateDataspace(s.dataspace); mBufferInfo.mCrop = computeCrop(s); @@ -653,6 +644,7 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; + mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); } Rect BufferStateLayer::computeCrop(const State& s) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 0b27d640ce..52063fcc58 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -19,7 +19,6 @@ #include "BufferLayer.h" #include "Layer.h" -#include #include #include #include @@ -108,7 +107,6 @@ protected: void gatherBufferInfo() override; private: - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; @@ -118,8 +116,6 @@ private: bool hasFrameUpdate() const override; - void setFilteringEnabled(bool enabled) override; - status_t bindTextureImage() override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) override; @@ -141,8 +137,6 @@ private: std::unique_ptr mTextureImage; - std::array mTransformMatrix{IDENTITY_MATRIX}; - std::atomic mSidebandStreamChanged{false}; mutable uint32_t mFrameNumber{0}; -- cgit v1.2.3-59-g8ed1b From 9755fb755c062b406ff5a9310ef6b23b9f1ce5a2 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 26 Mar 2019 14:44:40 -0700 Subject: CE: Layers only have FE layer state Remove the concept of having a compositionengine::Layer having internal state since it was only used to internally store a copy of the LayerFECompositionState. Instead switch the Layer interface so only the FE state can be obtained. Any internal state will from now on be private. Doing this also allows the LayerFECompostionState to be easily extended by extended versions of CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Test: go/wm-smoke Bug: 121291683 Change-Id: I689e8714aca46320c87e0cb5ef18fdde93eb7499 --- services/surfaceflinger/BufferLayer.cpp | 2 - services/surfaceflinger/BufferQueueLayer.cpp | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 12 +- services/surfaceflinger/ColorLayer.cpp | 4 - .../surfaceflinger/CompositionEngine/Android.bp | 2 +- .../include/compositionengine/Layer.h | 16 +-- .../compositionengine/LayerFECompositionState.h | 3 + .../include/compositionengine/impl/Layer.h | 9 +- .../compositionengine/impl/LayerCompositionState.h | 42 ------- .../include/compositionengine/mock/Layer.h | 6 +- .../CompositionEngine/src/CompositionEngine.cpp | 4 +- .../surfaceflinger/CompositionEngine/src/Layer.cpp | 12 +- .../src/LayerCompositionState.cpp | 91 -------------- .../src/LayerFECompositionState.cpp | 85 +++++++++++++ .../CompositionEngine/src/Output.cpp | 19 ++- .../CompositionEngine/src/OutputLayer.cpp | 16 +-- .../CompositionEngine/tests/OutputLayerTest.cpp | 132 ++++++++++----------- .../CompositionEngine/tests/OutputTest.cpp | 76 ++++++------ services/surfaceflinger/Layer.cpp | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - .../tests/unittests/TestableSurfaceFlinger.h | 4 +- 21 files changed, 243 insertions(+), 308 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h delete mode 100644 services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp create mode 100644 services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b060b047af..fba235d397 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -22,12 +22,10 @@ #include "BufferLayer.h" #include -#include #include #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index f2e861d1ce..fcabedf63e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -17,15 +17,13 @@ #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include +#include "BufferQueueLayer.h" + #include -#include -#include -#include +#include #include #include -#include "BufferQueueLayer.h" #include "LayerRejecter.h" #include "SurfaceInterceptor.h" @@ -197,7 +195,7 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { // mSidebandStreamChanged was changed to false mSidebandStream = mConsumer->getSidebandStream(); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.sidebandStream = mSidebandStream; if (layerCompositionState.sidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); @@ -335,7 +333,7 @@ status_t BufferQueueLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; if (mBufferInfo.mBuffer == nullptr) { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 509deaf996..ad05bc8671 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -19,18 +19,16 @@ #define LOG_TAG "BufferStateLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include "BufferStateLayer.h" + #include -#include #include -#include -#include -#include +#include #include #include #include -#include "BufferStateLayer.h" #include "ColorLayer.h" #include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" @@ -415,7 +413,7 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // mSidebandStreamChanged was true LOG_ALWAYS_FATAL_IF(!getCompositionLayer()); mSidebandStream = s.sidebandStream; - getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream; + getCompositionLayer()->editFEState().sidebandStream = mSidebandStream; if (mSidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); @@ -520,7 +518,7 @@ status_t BufferStateLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = s.buffer; mBufferInfo.mFence = s.acquireFence; - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 49b18102c7..99805d9da2 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -25,13 +25,9 @@ #include #include -#include #include #include #include -#include -#include -#include #include #include #include diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index e49b65ff07..fcb94fde95 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -47,7 +47,7 @@ cc_library { "src/DumpHelpers.cpp", "src/HwcBufferCache.cpp", "src/Layer.cpp", - "src/LayerCompositionState.cpp", + "src/LayerFECompositionState.cpp", "src/Output.cpp", "src/OutputCompositionState.cpp", "src/OutputLayer.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h index 451608b2ae..1259c524b2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h @@ -26,9 +26,7 @@ namespace android::compositionengine { class Display; class LayerFE; -namespace impl { -struct LayerCompositionState; -} // namespace impl +struct LayerFECompositionState; /** * A layer contains the output-independent composition state for a front-end @@ -42,17 +40,13 @@ public: // front-end layer no longer exists. virtual sp getLayerFE() const = 0; - using CompositionState = impl::LayerCompositionState; - - // Gets the raw composition state data for the layer + // Gets the raw front-end composition state data for the layer // TODO(lpique): Make this protected once it is only internally called. - virtual const CompositionState& getState() const = 0; + virtual const LayerFECompositionState& getFEState() const = 0; - // Allows mutable access to the raw composition state data for the layer. - // This is meant to be used by the various functions that are part of the - // composition process. + // Allows mutable access to the raw front-end composition state // TODO(lpique): Make this protected once it is only internally called. - virtual CompositionState& editState() = 0; + virtual LayerFECompositionState& editFEState() = 0; // Debugging virtual void dump(std::string& result) const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 530f49a600..2ba781d924 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -147,6 +147,9 @@ struct LayerFECompositionState { // The output-independent frame for the cursor Rect cursorFrame; + + // Debugging + void dump(std::string& out) const; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h index 3e56b21b18..d441c9c1b6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -41,8 +41,8 @@ public: sp getLayerFE() const override; - const LayerCompositionState& getState() const override; - LayerCompositionState& editState() override; + const LayerFECompositionState& getFEState() const override; + LayerFECompositionState& editFEState() override; void dump(std::string& result) const override; @@ -50,7 +50,8 @@ private: const compositionengine::CompositionEngine& mCompositionEngine; const wp mLayerFE; - LayerCompositionState mState; + // State obtained from calls to LayerFE::getCompositionState + LayerFECompositionState mFrontEndState; }; std::shared_ptr createLayer(const compositionengine::CompositionEngine&, diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h deleted file mode 100644 index 726c850780..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 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 -#include - -#include -#include -#include - -namespace android { - -namespace compositionengine::impl { - -struct LayerCompositionState { - /* - * State set by LayerFE::getCompositionState - */ - - LayerFECompositionState frontEnd; - - // Debugging - void dump(std::string& result) const; -}; - -} // namespace compositionengine::impl -} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h index cce3b97bbd..4f03cb46ae 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include namespace android::compositionengine::mock { @@ -30,8 +30,8 @@ public: MOCK_CONST_METHOD0(getLayerFE, sp()); - MOCK_CONST_METHOD0(getState, const CompositionState&()); - MOCK_METHOD0(editState, CompositionState&()); + MOCK_CONST_METHOD0(getFEState, const LayerFECompositionState&()); + MOCK_METHOD0(editFEState, LayerFECompositionState&()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 713266ff85..8391458e99 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -103,8 +103,8 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { for (auto& layer : output->getOutputLayersOrderedByZ()) { if (layer->isHardwareCursor()) { // Latch the cursor composition state from each front-end layer. - layer->getLayerFE().latchCursorCompositionState( - layer->getLayer().editState().frontEnd); + layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState()); + layer->writeCursorPositionToHWC(); } } diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp index 96e9731768..8a1cbe409b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp @@ -43,19 +43,21 @@ sp Layer::getLayerFE() const { return mLayerFE.promote(); } -const LayerCompositionState& Layer::getState() const { - return mState; +const compositionengine::LayerFECompositionState& Layer::getFEState() const { + return mFrontEndState; } -LayerCompositionState& Layer::editState() { - return mState; +compositionengine::LayerFECompositionState& Layer::editFEState() { + return mFrontEndState; } void Layer::dump(std::string& out) const { auto layerFE = getLayerFE(); android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this, layerFE ? layerFE->getDebugName() : ""); - mState.dump(out); + + out.append(" frontend:\n"); + mFrontEndState.dump(out); } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp deleted file mode 100644 index c5debf6e77..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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 -#include -#include - -namespace android::compositionengine::impl { - -namespace { - -using android::compositionengine::impl::dumpVal; - -void dumpVal(std::string& out, const char* name, half4 value) { - using android::base::StringAppendF; - StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), - static_cast(value.g), static_cast(value.b)); -} - -void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { - out.append(" "); - dumpVal(out, "isSecure", state.isSecure); - dumpVal(out, "geomUsesSourceCrop", state.geomUsesSourceCrop); - dumpVal(out, "geomBufferUsesDisplayInverseTransform", - state.geomBufferUsesDisplayInverseTransform); - dumpVal(out, "geomLayerTransform", state.geomLayerTransform); - - out.append("\n "); - dumpVal(out, "geomBufferSize", state.geomBufferSize); - dumpVal(out, "geomContentCrop", state.geomContentCrop); - dumpVal(out, "geomCrop", state.geomCrop); - dumpVal(out, "geomBufferTransform", state.geomBufferTransform); - - out.append("\n "); - dumpVal(out, "transparentRegionHint", state.transparentRegionHint); - - out.append(" "); - dumpVal(out, "geomLayerBounds", state.geomLayerBounds); - - out.append("\n "); - dumpVal(out, "blend", toString(state.blendMode), state.blendMode); - dumpVal(out, "alpha", state.alpha); - - out.append("\n "); - dumpVal(out, "type", state.type); - dumpVal(out, "appId", state.appId); - - dumpVal(out, "composition type", toString(state.compositionType), state.compositionType); - - out.append("\n buffer: "); - dumpVal(out, "bufferSlot", state.bufferSlot); - dumpVal(out, "buffer", state.buffer.get()); - - out.append("\n "); - dumpVal(out, "sideband stream", state.sidebandStream.get()); - - out.append("\n "); - dumpVal(out, "color", state.color); - - out.append("\n "); - dumpVal(out, "isOpaque", state.isOpaque); - dumpVal(out, "hasProtectedContent", state.hasProtectedContent); - dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); - dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); - dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); - dumpVal(out, "colorTransform", state.colorTransform); - - out.append("\n"); -} - -} // namespace - -void LayerCompositionState::dump(std::string& out) const { - out.append(" frontend:\n"); - dumpFrontEnd(out, frontEnd); -} - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp new file mode 100644 index 0000000000..1ca03dca5f --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2019 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 +#include +#include + +namespace android::compositionengine { + +namespace { + +using android::compositionengine::impl::dumpVal; + +void dumpVal(std::string& out, const char* name, half4 value) { + using android::base::StringAppendF; + StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), + static_cast(value.g), static_cast(value.b)); +} + +} // namespace + +void LayerFECompositionState::dump(std::string& out) const { + out.append(" "); + dumpVal(out, "isSecure", isSecure); + dumpVal(out, "geomUsesSourceCrop", geomUsesSourceCrop); + dumpVal(out, "geomBufferUsesDisplayInverseTransform", geomBufferUsesDisplayInverseTransform); + dumpVal(out, "geomLayerTransform", geomLayerTransform); + + out.append("\n "); + dumpVal(out, "geomBufferSize", geomBufferSize); + dumpVal(out, "geomContentCrop", geomContentCrop); + dumpVal(out, "geomCrop", geomCrop); + dumpVal(out, "geomBufferTransform", geomBufferTransform); + + out.append("\n "); + dumpVal(out, "transparentRegionHint", transparentRegionHint); + + out.append(" "); + dumpVal(out, "geomLayerBounds", geomLayerBounds); + + out.append("\n "); + dumpVal(out, "blend", toString(blendMode), blendMode); + dumpVal(out, "alpha", alpha); + + out.append("\n "); + dumpVal(out, "type", type); + dumpVal(out, "appId", appId); + + dumpVal(out, "composition type", toString(compositionType), compositionType); + + out.append("\n buffer: "); + dumpVal(out, "slot", bufferSlot); + dumpVal(out, "buffer", buffer.get()); + + out.append("\n "); + dumpVal(out, "sideband stream", sidebandStream.get()); + + out.append("\n "); + dumpVal(out, "color", color); + + out.append("\n "); + dumpVal(out, "isOpaque", isOpaque); + dumpVal(out, "hasProtectedContent", hasProtectedContent); + dumpVal(out, "isColorspaceAgnostic", isColorspaceAgnostic); + dumpVal(out, "dataspace", toString(dataspace), dataspace); + dumpVal(out, "hdr metadata types", hdrMetadata.validTypes); + dumpVal(out, "colorTransform", colorTransform); + + out.append("\n"); +} + +} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 83df628f25..02ebc1fc4f 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -249,7 +249,7 @@ bool Output::belongsInOutput(const compositionengine::Layer* layer) const { return false; } - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly); } @@ -400,12 +400,12 @@ std::unique_ptr Output::getOutputLayerIfVisible( // appear on multiple outputs. if (!coverage.latchedLayers.count(layerFE)) { coverage.latchedLayers.insert(layerFE); - layerFE->latchCompositionState(layer->editState().frontEnd, + layerFE->latchCompositionState(layer->editFEState(), compositionengine::LayerFE::StateSubset::BasicGeometry); } // Obtain a read-only reference to the front-end layer state - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); // Only consider the layers on the given layer stack if (!belongsInOutput(layer.get())) { @@ -572,7 +572,7 @@ void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const { for (auto& layer : mOutputLayersOrderedByZ) { - layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd, + layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(), args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent : LayerFE::StateSubset::Content); @@ -615,7 +615,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, *outHdrDataSpace = ui::Dataspace::UNKNOWN; for (const auto& layer : mOutputLayersOrderedByZ) { - switch (layer->getLayer().getState().frontEnd.dataspace) { + switch (layer->getLayer().getFEState().dataspace) { case ui::Dataspace::V0_SCRGB: case ui::Dataspace::V0_SCRGB_LINEAR: case ui::Dataspace::BT2020: @@ -631,8 +631,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, case ui::Dataspace::BT2020_ITU_PQ: bestDataSpace = ui::Dataspace::DISPLAY_P3; *outHdrDataSpace = ui::Dataspace::BT2020_PQ; - *outIsHdrClientComposition = - layer->getLayer().getState().frontEnd.forceClientComposition; + *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition; break; case ui::Dataspace::BT2020_HLG: case ui::Dataspace::BT2020_ITU_HLG: @@ -838,7 +837,7 @@ std::optional Output::composeSurfaces(const Region& debugRegion bool needsProtected = std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(), [](auto& layer) { - return layer->getLayer().getState().frontEnd.hasProtectedContent; + return layer->getLayer().getFEState().hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); @@ -892,7 +891,7 @@ std::vector Output::generateClientCompositionReques for (auto& layer : mOutputLayersOrderedByZ) { const auto& layerState = layer->getState(); - const auto& layerFEState = layer->getLayer().getState().frontEnd; + const auto& layerFEState = layer->getLayer().getFEState(); auto& layerFE = layer->getLayerFE(); const Region clip(viewportRegion.intersect(layerState.visibleRegion)); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 4eb256f94c..2e45953e5f 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -86,7 +86,7 @@ OutputLayerCompositionState& OutputLayer::editState() { } Rect OutputLayer::calculateInitialCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); // apply the projection's clipping to the window crop in // layerstack space, and convert-back to layer space. @@ -119,7 +119,7 @@ Rect OutputLayer::calculateInitialCrop() const { } FloatRect OutputLayer::calculateOutputSourceCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); if (!layerState.geomUsesSourceCrop) { @@ -196,7 +196,7 @@ FloatRect OutputLayer::calculateOutputSourceCrop() const { } Rect OutputLayer::calculateOutputDisplayFrame() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); // apply the layer's transform, followed by the display's global transform @@ -243,7 +243,7 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { } uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); /* @@ -283,7 +283,7 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { } // namespace impl void OutputLayer::updateCompositionState(bool includeGeometry) { - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); const auto& profile = *mOutput.getDisplayColorProfile(); @@ -327,7 +327,7 @@ void OutputLayer::writeStateToHWC(bool includeGeometry) { return; } - const auto& outputIndependentState = mLayer->getState().frontEnd; + const auto& outputIndependentState = mLayer->getFEState(); auto requestedCompositionType = outputIndependentState.compositionType; if (includeGeometry) { @@ -544,7 +544,7 @@ void OutputLayer::writeCursorPositionToHWC() const { return; } - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); Rect frame = layerFEState.cursorFrame; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index b73c47ba17..88cedfa7ea 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -59,7 +59,7 @@ struct OutputLayerTest : public testing::Test { EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE")); EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName)); - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); } @@ -70,7 +70,7 @@ struct OutputLayerTest : public testing::Test { new StrictMock()}; impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE}; - impl::LayerCompositionState mLayerState; + LayerFECompositionState mLayerFEState; impl::OutputCompositionState mOutputState; }; @@ -112,27 +112,26 @@ struct OutputLayerSourceCropTest : public OutputLayerTest { OutputLayerSourceCropTest() { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.geomUsesSourceCrop = true; - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferTransform = TR_IDENT; + mLayerFEState.geomUsesSourceCrop = true; + mLayerFEState.geomContentCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferTransform = TR_IDENT; mOutputState.viewport = Rect{0, 0, 1920, 1080}; } FloatRect calculateOutputSourceCrop() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputSourceCrop(); } }; TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) { - mLayerState.frontEnd.geomUsesSourceCrop = false; + mLayerFEState.geomUsesSourceCrop = false; const FloatRect expected{}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -144,15 +143,15 @@ TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; const FloatRect expected{0.f, 0.f, 1920.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const FloatRect expected{0.f, 0.f, 1080.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -190,8 +189,8 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i; @@ -199,7 +198,7 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed } TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) { - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540}; + mLayerFEState.geomContentCrop = Rect{0, 0, 960, 540}; const FloatRect expected{0.f, 0.f, 960.f, 540.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -221,20 +220,19 @@ struct OutputLayerDisplayFrameTest : public OutputLayerTest { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; - mLayerState.frontEnd.geomCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; mOutputState.viewport = Rect{0, 0, 1920, 1080}; mOutputState.transform = ui::Transform{TR_IDENT}; } Rect calculateOutputDisplayFrame() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputDisplayFrame(); } @@ -246,32 +244,32 @@ TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) { - mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; + mLayerFEState.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; const Rect expected{0, 0, 0, 0}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; const Rect expected{100, 200, 300, 500}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const Rect expected{1420, 100, 1720, 300}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) { - mLayerState.frontEnd.geomCrop = Rect{}; + mLayerFEState.geomCrop = Rect{}; const Rect expected{0, 0, 1920, 1080}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; const Rect expected{0, 0, 960, 540}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } @@ -293,7 +291,7 @@ TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) { */ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; struct Entry { uint32_t layer; @@ -340,8 +338,8 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform.set(entry.layer, 1920, 1080); - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080); + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -351,7 +349,7 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true; + mLayerFEState.geomBufferUsesDisplayInverseTransform = true; struct Entry { uint32_t layer; @@ -398,8 +396,8 @@ TEST_F(OutputLayerTest, for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer}; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform = ui::Transform{entry.layer}; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -425,7 +423,7 @@ struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLaye struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest { public: OutputLayerUpdateCompositionStateTest() { - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -458,7 +456,7 @@ public: }; TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; setupGeometryChildCallValues(); @@ -472,7 +470,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = false; setupGeometryChildCallValues(); @@ -486,7 +484,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfUnsupportedBufferTransform) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; mBufferTransform = ui::Transform::ROT_INVALID; @@ -501,12 +499,12 @@ TEST_F(OutputLayerUpdateCompositionStateTest, } TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) { - mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3; + mLayerFEState.dataspace = ui::Dataspace::DISPLAY_P3; mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB; // If the layer is not colorspace agnostic, the output layer dataspace // should use the layers requested colorspace. - mLayerState.frontEnd.isColorspaceAgnostic = false; + mLayerFEState.isColorspaceAgnostic = false; mOutputLayer.updateCompositionState(false); @@ -514,7 +512,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // If the layer is colorspace agnostic, the output layer dataspace // should use the colorspace chosen for the whole output. - mLayerState.frontEnd.isColorspaceAgnostic = true; + mLayerFEState.isColorspaceAgnostic = true; mOutputLayer.updateCompositionState(false); @@ -528,7 +526,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotReque } TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) { - mLayerState.frontEnd.forceClientComposition = true; + mLayerFEState.forceClientComposition = true; mOutputLayer.updateCompositionState(false); @@ -583,18 +581,18 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion; outputLayerState.dataspace = kDataspace; - mLayerState.frontEnd.blendMode = kBlendMode; - mLayerState.frontEnd.alpha = kAlpha; - mLayerState.frontEnd.type = kType; - mLayerState.frontEnd.appId = kAppId; - mLayerState.frontEnd.colorTransform = kColorTransform; - mLayerState.frontEnd.color = kColor; - mLayerState.frontEnd.surfaceDamage = kSurfaceDamage; - mLayerState.frontEnd.hdrMetadata = kHdrMetadata; - mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); - mLayerState.frontEnd.buffer = kBuffer; - mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; - mLayerState.frontEnd.acquireFence = kFence; + mLayerFEState.blendMode = kBlendMode; + mLayerFEState.alpha = kAlpha; + mLayerFEState.type = kType; + mLayerFEState.appId = kAppId; + mLayerFEState.colorTransform = kColorTransform; + mLayerFEState.color = kColor; + mLayerFEState.surfaceDamage = kSurfaceDamage; + mLayerFEState.hdrMetadata = kHdrMetadata; + mLayerFEState.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); + mLayerFEState.buffer = kBuffer; + mLayerFEState.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + mLayerFEState.acquireFence = kFence; EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -698,7 +696,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -708,7 +706,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; expectPerFrameCommonCalls(); expectSetSidebandHandleCall(); @@ -718,7 +716,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::CURSOR; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -728,7 +726,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -741,7 +739,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { (*mOutputLayer.editState().hwc).hwcCompositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -751,7 +749,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { } TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform); expectSetColorCall(); @@ -763,7 +761,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransf TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) { mOutputLayer.editState().forceClientComposition = true; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -787,7 +785,7 @@ struct OutputLayerWriteCursorPositionToHWCTest : public OutputLayerTest { auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); - mLayerState.frontEnd.cursorFrame = kDefaultCursorFrame; + mLayerFEState.cursorFrame = kDefaultCursorFrame; mOutputState.viewport = kDefaultDisplayViewport; mOutputState.transform = ui::Transform{kDefaultTransform}; @@ -812,7 +810,7 @@ TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCWritesSt } TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCIntersectedWithViewport) { - mLayerState.frontEnd.cursorFrame = Rect{3000, 3000, 3016, 3016}; + mLayerFEState.cursorFrame = Rect{3000, 3000, 3016, 3016}; EXPECT_CALL(*mHwcLayer, setCursorPosition(1920, 1080)).WillOnce(Return(kDefaultError)); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index a0b8017264..70c343bba6 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include #include @@ -378,9 +378,9 @@ TEST_F(OutputTest, belongsInOutputFiltersAsExpected) { TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { StrictMock layer; - impl::LayerCompositionState layerState; + LayerFECompositionState layerFEState; - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); const uint32_t layerStack1 = 123u; const uint32_t layerStack2 = 456u; @@ -392,29 +392,29 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // A layer with no layerStack does not belong to it, internal-only or not. - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // Any layer with layerStack1 belongs to it, internal-only or not. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // If the output accepts layerStack1 but not internal-only layers... @@ -424,20 +424,20 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // Only non-internal layers with layerStack1 belong to it. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); } @@ -732,8 +732,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) leftOutputLayerState.clearClientTarget = false; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; const half3 leftLayerColor{1.f, 0.f, 0.f}; renderengine::LayerSettings leftLayerRESettings; @@ -743,8 +743,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) rightOutputLayerState.clearClientTarget = false; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -755,7 +755,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); @@ -763,7 +763,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; @@ -806,15 +806,15 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit outputLayerState.clearClientTarget = false; outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}}; - impl::LayerCompositionState layerState; - layerState.frontEnd.isOpaque = true; + LayerFECompositionState layerFEState; + layerFEState.isOpaque = true; EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(*outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer)); EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); EXPECT_CALL(*outputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*outputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0); Output::OutputLayers outputLayers; @@ -861,15 +861,15 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { leftOutputLayerState.clearClientTarget = true; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = true; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -881,14 +881,14 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer)); EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bed33a71d0..7b708bccae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cc12608e87..15550799bf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -41,12 +41,9 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d0d391b679..b77f82a7f8 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -18,9 +18,9 @@ #include #include +#include #include #include -#include #include #include "BufferQueueLayer.h" @@ -235,7 +235,7 @@ public: void setLayerSidebandStream(sp layer, sp sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; - layer->getCompositionLayer()->editState().frontEnd.sidebandStream = sidebandStream; + layer->getCompositionLayer()->editFEState().sidebandStream = sidebandStream; } void setLayerCompositionType(sp layer, HWC2::Composition type) { -- cgit v1.2.3-59-g8ed1b From b4c6e5850f16d045abcb4e3308b7556749a61be0 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 16 Aug 2019 14:35:07 -0700 Subject: [Mirror Layers] Added clone function to layers (1/4) Added a cloning function to each layer in preparation for mirroring Test: Nothing to test yet since no calls Bug: 131622422 Change-Id: Iba0692b75c4d99841de48f40ed55b3dbccf2b9b9 --- services/surfaceflinger/BufferLayer.cpp | 19 +++++++++++++-- services/surfaceflinger/BufferLayer.h | 1 + services/surfaceflinger/BufferQueueLayer.cpp | 20 ++++++++++------ services/surfaceflinger/BufferQueueLayer.h | 2 ++ services/surfaceflinger/BufferStateLayer.cpp | 27 ++++++++++++++-------- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 8 +++++++ services/surfaceflinger/ColorLayer.h | 2 ++ services/surfaceflinger/ContainerLayer.cpp | 7 ++++++ services/surfaceflinger/ContainerLayer.h | 3 +++ services/surfaceflinger/Layer.cpp | 9 ++++++++ services/surfaceflinger/Layer.h | 15 ++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++++++++---- .../tests/unittests/CompositionTest.cpp | 13 +++++++---- 14 files changed, 121 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fba235d397..d189846dd5 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -58,7 +58,7 @@ namespace android { BufferLayer::BufferLayer(const LayerCreationArgs& args) : Layer(args), - mTextureName(args.flinger->getNewTexture()), + mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { ALOGV("Creating Layer %s", args.name.string()); @@ -70,7 +70,13 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) } BufferLayer::~BufferLayer() { - mFlinger->deleteTextureAsync(mTextureName); + if (!isClone()) { + // The original layer and the clone layer share the same texture. Therefore, only one of + // the layers, in this case the original layer, needs to handle the deletion. The original + // layer and the clone should be removed at the same time so there shouldn't be any issue + // with the clone layer trying to use the deleted texture. + mFlinger->deleteTextureAsync(mTextureName); + } const int32_t layerID = getSequence(); mFlinger->mTimeStats->onDestroy(layerID); mFlinger->mFrameTracer->onDestroy(layerID); @@ -722,6 +728,15 @@ void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatr mBufferInfo.mTransform, filteringEnabled); } +void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { + Layer::setInitialValuesForClone(clonedFrom); + + sp bufferClonedFrom = static_cast(clonedFrom.get()); + mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; + mPotentialCursor = bufferClonedFrom->mPotentialCursor; + mProtectedByApp = bufferClonedFrom->mProtectedByApp; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index f0a30e319a..b2c06183a6 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -194,6 +194,7 @@ protected: bool mRefreshPending{false}; ui::Dataspace translateDataspace(ui::Dataspace dataspace); + void setInitialValuesForClone(const sp& clonedFrom); private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index fcabedf63e..eb13f658d9 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -461,12 +461,7 @@ void BufferQueueLayer::onFirstRef() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, 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 = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); @@ -476,7 +471,7 @@ void BufferQueueLayer::onFirstRef() { mProducer->setMaxDequeuedBufferCount(2); } - if (const auto display = mFlinger->getDefaultDisplayDevice()) { + if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { updateTransformHint(display); } } @@ -531,4 +526,15 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); } +sp BufferQueueLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferQueueLayer(args); + layer->setInitialValuesForClone(this); + + return layer; +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 9374741ddb..36dff156e1 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -31,6 +31,7 @@ namespace android { */ class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { public: + // Only call while mStateLock is held explicit BufferQueueLayer(const LayerCreationArgs&); ~BufferQueueLayer() override; @@ -81,6 +82,7 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ad05bc8671..30fdbe14e8 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -48,10 +48,17 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mCurrentState.dataspace = ui::Dataspace::V0_SRGB; + if (const auto display = args.displayDevice) { + updateTransformHint(display); + } } BufferStateLayer::~BufferStateLayer() { - if (mBufferInfo.mBuffer != nullptr) { + // The original layer and the clone layer share the same texture and buffer. Therefore, only + // one of the layers, in this case the original layer, needs to handle the deletion. The + // original layer and the clone should be removed at the same time so there shouldn't be any + // issue with the clone layer trying to use the texture. + if (mBufferInfo.mBuffer != nullptr && !isClone()) { // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. @@ -545,14 +552,6 @@ void BufferStateLayer::latchPerFrameState( mFrameNumber++; } -void BufferStateLayer::onFirstRef() { - BufferLayer::onFirstRef(); - - if (const auto display = mFlinger->getDefaultDisplayDevice()) { - updateTransformHint(display); - } -} - void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { std::lock_guard lock(mMutex); if (!clientCacheId.isValid()) { @@ -668,4 +667,14 @@ Rect BufferStateLayer::computeCrop(const State& s) { return s.crop; } +sp BufferStateLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferStateLayer(args); + layer->mHwcSlotGenerator = mHwcSlotGenerator; + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 52063fcc58..e951ccf97a 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -124,13 +124,13 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // Crop that applies to the buffer Rect computeCrop(const State& s); private: friend class SlotGenerationTest; - void onFirstRef() override; bool willPresentCurrentTransaction() const; static const std::array IDENTITY_MATRIX; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 99805d9da2..5b620543ac 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -107,6 +107,14 @@ ui::Dataspace ColorLayer::getDataSpace() const { return mDrawingState.dataspace; } +sp ColorLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ColorLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 16921df356..634a80003a 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -50,6 +50,8 @@ protected: compositionengine::LayerFE::ClientCompositionTargetSettings&) override; std::shared_ptr mCompositionLayer; + + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 4a1130365a..cb50d9ff6d 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -30,4 +30,11 @@ bool ContainerLayer::isVisible() const { return false; } +sp ContainerLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ContainerLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index c3624f6d7d..b48d471bde 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -32,6 +32,9 @@ public: bool isVisible() const override; bool isCreatedFromMainThread() const override { return true; } + +protected: + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba948cfdbc..52a09b35d1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2015,6 +2015,15 @@ Region Layer::debugGetVisibleRegionOnDefaultDisplay() const { return outputLayer->getState().visibleRegion; } +void Layer::setInitialValuesForClone(const sp& clonedFrom) { + // copy drawing state from cloned layer + mDrawingState = clonedFrom->mDrawingState; + mClonedFrom = clonedFrom; + + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8771ccd08e..96970ace89 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -91,6 +91,8 @@ struct LayerCreationArgs { LayerMetadata metadata; pid_t callingPid; uid_t callingUid; + sp displayDevice; + uint32_t textureName; }; class Layer : public compositionengine::LayerFE { @@ -465,6 +467,13 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp&) const { return false; } +protected: + virtual sp createClone() = 0; + sp getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + + bool isClone() { return getClonedFrom() != nullptr; } + virtual void setInitialValuesForClone(const sp& clonedFrom); + public: /* * compositionengine::LayerFE overrides @@ -912,6 +921,12 @@ private: // to help debugging. pid_t mCallingPid; uid_t mCallingUid; + + // The current layer is a clone of mClonedFrom. This means that this layer will update it's + // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers, + // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children, + // and relatives, this layer will update as well. + wp mClonedFrom; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 41afb5da55..e3cf84aa1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3532,8 +3532,18 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const break; } - sp layer = getFactory().createBufferQueueLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + sp layer; + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.textureName = getNewTexture(); + { + // Grab the SF state lock during this since it's the only safe way to access + // RenderEngine when creating a BufferLayerConsumer + // TODO: Check if this lock is still needed here + Mutex::Autolock lock(mStateLock); + layer = getFactory().createBufferQueueLayer(args); + } + status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); @@ -3549,8 +3559,11 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - sp layer = getFactory().createBufferStateLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.displayDevice = getDefaultDisplayDevice(); + args.textureName = getNewTexture(); + sp layer = getFactory().createBufferStateLayer(args); *handle = layer->getHandle(); *outLayer = layer; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 20dfed65e2..f29e2ddd33 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -883,11 +883,14 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { - return new BufferQueueLayer( - LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, - LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata())); + sp client; + String8 name("test-layer"); + LayerCreationArgs args = + LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); + args.textureName = test->mFlinger.mutableTexturePool().back(); + return new BufferQueueLayer(args); }); LayerProperties::setupLayerState(test, layer); -- cgit v1.2.3-59-g8ed1b From 74b03178292a8fd1e514b8b53d425e8d9c739319 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 19 Aug 2019 11:09:03 -0700 Subject: [Mirror Layers] Added functions to update mirrored layers info (2/4) Added updateMirrorInfo and updateBufferInfoFromClone to ensure the state and buffer of the clones are updated properly. updateMirrorInfo is called when commitTransaction is called to update the drawing state, children, and relatives. updateBufferInfoFromClone is called in handlePageFlip after the real layer calls latchBuffer to ensure the cloned layer gets the updated buffer and buffer info. Test: No mirror request yet so everything runs normally Bug: 131622422 Change-Id: Ic2b1f66cab98175dbdccf90f2f8310c7f19d8cff --- services/surfaceflinger/BufferLayer.cpp | 35 ++++++++- services/surfaceflinger/BufferLayer.h | 4 ++ services/surfaceflinger/BufferQueueLayer.h | 2 - services/surfaceflinger/BufferStateLayer.h | 1 - services/surfaceflinger/Layer.cpp | 112 +++++++++++++++++++++++++++++ services/surfaceflinger/Layer.h | 22 +++++- services/surfaceflinger/SurfaceFlinger.cpp | 3 + 7 files changed, 170 insertions(+), 9 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d189846dd5..b500ad3eee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -295,7 +295,7 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, const CompositorTiming& compositorTiming) { // mFrameLatencyNeeded is true when a new frame was latched for the // composition. - if (!mFrameLatencyNeeded) return false; + if (!mBufferInfo.mFrameLatencyNeeded) return false; // Update mFrameEventHistory. { @@ -337,7 +337,7 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } mFrameTracker.advanceFrame(); - mFrameLatencyNeeded = false; + mBufferInfo.mFrameLatencyNeeded = false; return true; } @@ -401,7 +401,7 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, gatherBufferInfo(); mRefreshPending = true; - mFrameLatencyNeeded = true; + mBufferInfo.mFrameLatencyNeeded = true; if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. @@ -735,6 +735,35 @@ void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; mPotentialCursor = bufferClonedFrom->mPotentialCursor; mProtectedByApp = bufferClonedFrom->mProtectedByApp; + + updateCloneBufferInfo(); +} + +void BufferLayer::updateCloneBufferInfo() { + if (!isClone() || !isClonedFromAlive()) { + return; + } + + sp clonedFrom = static_cast(getClonedFrom().get()); + mBufferInfo = clonedFrom->mBufferInfo; + mSidebandStream = clonedFrom->mSidebandStream; + surfaceDamageRegion = clonedFrom->surfaceDamageRegion; + mCurrentFrameNumber = clonedFrom->mCurrentFrameNumber.load(); + mPreviousFrameNumber = clonedFrom->mPreviousFrameNumber; + + // After buffer info is updated, the drawingState from the real layer needs to be copied into + // the cloned. This is because some properties of drawingState can change when latchBuffer is + // called. However, copying the drawingState would also overwrite the cloned layer's relatives. + // Therefore, temporarily store the relatives so they can be set in the cloned drawingState + // again. + wp tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf; + SortedVector> tmpZOrderRelatives = mDrawingState.zOrderRelatives; + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf; + mDrawingState.zOrderRelatives = tmpZOrderRelatives; } } // namespace android diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b2c06183a6..656ba12a19 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -165,6 +165,8 @@ protected: sp mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; + + bool mFrameLatencyNeeded{false}; }; BufferInfo mBufferInfo; @@ -195,6 +197,8 @@ protected: ui::Dataspace translateDataspace(ui::Dataspace dataspace); void setInitialValuesForClone(const sp& clonedFrom); + void updateCloneBufferInfo() override; + uint64_t mPreviousFrameNumber = 0; private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 36dff156e1..f3e8a19a7d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -111,8 +111,6 @@ private: PixelFormat mFormat{PIXEL_FORMAT_NONE}; - // Only accessed on the main thread. - uint64_t mPreviousFrameNumber{0}; bool mUpdateTexImageFailed{false}; uint64_t mPreviousBufferId = 0; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index e951ccf97a..3dfe76cf9f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -143,7 +143,6 @@ private: sp mPreviousReleaseFence; uint64_t mPreviousBufferId = 0; - uint64_t mPreviousFrameNumber = 0; uint64_t mPreviousReleasedFrameNumber = 0; mutable bool mCurrentStateModified = false; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 079bc66303..f017ca07cf 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2025,6 +2025,118 @@ void Layer::setInitialValuesForClone(const sp& clonedFrom) { // InputWindows per client token yet. mDrawingState.inputInfo.token = nullptr; } + +void Layer::updateMirrorInfo() { + if (mClonedChild == nullptr || !mClonedChild->isClonedFromAlive()) { + // If mClonedChild is null, there is nothing to mirror. If isClonedFromAlive returns false, + // it means that there is a clone, but the layer it was cloned from has been destroyed. In + // that case, we want to delete the reference to the clone since we want it to get + // destroyed. The root, this layer, will still be around since the client can continue + // to hold a reference, but no cloned layers will be displayed. + mClonedChild = nullptr; + return; + } + + std::map, sp> clonedLayersMap; + // If the real layer exists and is in current state, add the clone as a child of the root. + // There's no need to remove from drawingState when the layer is offscreen since currentState is + // copied to drawingState for the root layer. So the clonedChild is always removed from + // drawingState and then needs to be added back each traversal. + if (!mClonedChild->getClonedFrom()->isRemovedFromCurrentState()) { + addChildToDrawing(mClonedChild); + } + + mClonedChild->updateClonedDrawingState(clonedLayersMap); + mClonedChild->updateClonedChildren(this, clonedLayersMap); + mClonedChild->updateClonedRelatives(clonedLayersMap); +} + +void Layer::updateClonedDrawingState(std::map, sp>& clonedLayersMap) { + // If the layer the clone was cloned from is alive, copy the content of the drawingState + // to the clone. If the real layer is no longer alive, continue traversing the children + // since we may be able to pull out other children that are still alive. + if (isClonedFromAlive()) { + sp clonedFrom = getClonedFrom(); + mDrawingState = clonedFrom->mDrawingState; + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; + clonedLayersMap.emplace(clonedFrom, this); + } + + // The clone layer may have children in drawingState since they may have been created and + // added from a previous request to updateMirorInfo. This is to ensure we don't recreate clones + // that already exist, since we can just re-use them. + // The drawingChildren will not get overwritten by the currentChildren since the clones are + // not updated in the regular traversal. They are skipped since the root will lose the + // reference to them when it copies its currentChildren to drawing. + for (sp& child : mDrawingChildren) { + child->updateClonedDrawingState(clonedLayersMap); + } +} + +void Layer::updateClonedChildren(const sp& mirrorRoot, + std::map, sp>& clonedLayersMap) { + mDrawingChildren.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp clonedFrom = getClonedFrom(); + for (sp& child : clonedFrom->mDrawingChildren) { + if (child == mirrorRoot) { + // This is to avoid cyclical mirroring. + continue; + } + sp clonedChild = clonedLayersMap[child]; + if (clonedChild == nullptr) { + clonedChild = child->createClone(); + clonedLayersMap[child] = clonedChild; + } + addChildToDrawing(clonedChild); + clonedChild->updateClonedChildren(mirrorRoot, clonedLayersMap); + } +} + +void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap) { + mDrawingState.zOrderRelativeOf = nullptr; + mDrawingState.zOrderRelatives.clear(); + + if (!isClonedFromAlive()) { + return; + } + + sp clonedFrom = getClonedFrom(); + for (wp& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { + sp relative = relativeWeak.promote(); + auto clonedRelative = clonedLayersMap[relative]; + if (clonedRelative != nullptr) { + mDrawingState.zOrderRelatives.add(clonedRelative); + } + } + + // Check if the relativeLayer for the real layer is part of the cloned hierarchy. + // It's possible that the layer it's relative to is outside the requested cloned hierarchy. + // In that case, we treat the layer as if the relativeOf has been removed. This way, it will + // still traverse the children, but the layer with the missing relativeOf will not be shown + // on screen. + sp relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + sp clonedRelativeOf = clonedLayersMap[relativeOf]; + if (clonedRelativeOf != nullptr) { + mDrawingState.zOrderRelativeOf = clonedRelativeOf; + } + + for (sp& child : mDrawingChildren) { + child->updateClonedRelatives(clonedLayersMap); + } +} + +void Layer::addChildToDrawing(const sp& layer) { + mDrawingChildren.add(layer); + layer->mDrawingParent = this; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 610df25637..3023cf5df3 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -468,13 +468,30 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp&) const { return false; } -protected: + // This layer is not a clone, but it's the parent to the cloned hierarchy. The + // variable mClonedChild represents the top layer that will be cloned so this + // layer will be the parent of mClonedChild. + // The layers in the cloned hierarchy will match the lifetime of the real layers. That is + // if the real layer is destroyed, then the clone layer will also be destroyed. + sp mClonedChild; + virtual sp createClone() = 0; + void updateMirrorInfo(); + virtual void updateCloneBufferInfo(){}; + +protected: sp getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + bool isClone() { return mClonedFrom != nullptr; } + bool isClonedFromAlive() { return getClonedFrom() != nullptr; } - bool isClone() { return getClonedFrom() != nullptr; } virtual void setInitialValuesForClone(const sp& clonedFrom); + void updateClonedDrawingState(std::map, sp>& clonedLayersMap); + void updateClonedChildren(const sp& mirrorRoot, + std::map, sp>& clonedLayersMap); + void updateClonedRelatives(std::map, sp> clonedLayersMap); + void addChildToDrawing(const sp& layer); + public: /* * compositionengine::LayerFE overrides @@ -838,7 +855,6 @@ protected: // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; - bool mFrameLatencyNeeded{false}; // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 86997477b3..86e73c2481 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2600,6 +2600,7 @@ void SurfaceFlinger::commitTransactionLocked() { }); commitOffscreenLayers(); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateMirrorInfo(); }); } void SurfaceFlinger::withTracingLock(std::function lockedOperation) { @@ -2718,6 +2719,8 @@ bool SurfaceFlinger::handlePageFlip() mBootStage = BootStage::BOOTANIMATION; } + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->updateCloneBufferInfo(); }); + // Only continue with the refresh if there is actually new work to do return !mLayersWithQueuedFrames.empty() && newDataLatched; } -- cgit v1.2.3-59-g8ed1b From 87a07e42dd60a748cbf82be7e82b07b0326ea469 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Thu, 10 Oct 2019 20:38:02 -0700 Subject: SF: Use std::string for layer names Bug: 130554049 Test: Build Change-Id: Id083a85fcb838da4138c39a55b12cf10ff0cdddb --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.cpp | 16 ++-- services/surfaceflinger/BufferStateLayer.cpp | 8 +- services/surfaceflinger/ColorLayer.cpp | 8 +- services/surfaceflinger/ContainerLayer.cpp | 5 +- services/surfaceflinger/EventLog/EventLog.cpp | 27 +++--- services/surfaceflinger/EventLog/EventLog.h | 38 +++------ services/surfaceflinger/FrameTracker.cpp | 5 +- services/surfaceflinger/FrameTracker.h | 21 ++--- services/surfaceflinger/Layer.cpp | 45 +++++----- services/surfaceflinger/Layer.h | 11 ++- services/surfaceflinger/LayerRejecter.cpp | 7 +- services/surfaceflinger/LayerRejecter.h | 37 ++++---- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 98 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 14 ++-- services/surfaceflinger/SurfaceInterceptor.cpp | 6 +- services/surfaceflinger/SurfaceInterceptor.h | 1 - .../tests/unittests/CompositionTest.cpp | 10 +-- 19 files changed, 159 insertions(+), 202 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b500ad3eee..603a9f7f70 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -61,7 +61,7 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { - ALOGV("Creating Layer %s", args.name.string()); + ALOGV("Creating Layer %s", getDebugName()); mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d80a70e4c6..cd0d87cb82 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -62,7 +62,7 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo std::vector history; status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result); return {}; } return history; @@ -110,7 +110,7 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " "relative to expectedPresent %" PRId64, - mName.string(), addedTime, expectedPresentTime); + getDebugName(), addedTime, expectedPresentTime); const bool isDue = addedTime < expectedPresentTime; return isDue || !isPlausible; @@ -225,7 +225,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t bool queuedBuffer = false; const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, + getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { @@ -398,7 +398,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -426,7 +426,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -464,7 +464,7 @@ void BufferQueueLayer::onFirstRef() { mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); - mConsumer->setName(mName); + mConsumer->setName(String8(mName.data(), mName.size())); // BufferQueueCore::mMaxDequeuedBufferCount is default to 1 if (!mFlinger->isLayerTripleBufferingDisabled()) { @@ -527,9 +527,7 @@ void BufferQueueLayer::gatherBufferInfo() { } sp BufferQueueLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 75fc0e9c06..6fe89c41b5 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -136,7 +136,7 @@ void BufferStateLayer::pushPendingState() { return; } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { @@ -479,7 +479,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", - mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); return BAD_VALUE; } @@ -669,9 +669,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } sp BufferStateLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 172d44556a..8bfa569eeb 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -108,13 +108,11 @@ ui::Dataspace ColorLayer::getDataSpace() const { } sp ColorLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } -// --------------------------------------------------------------------------- - -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index e58e6f425e..ab664be5e2 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -31,10 +31,11 @@ bool ContainerLayer::isVisible() const { } sp ContainerLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } + } // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index 365a0bd868..a532fc130f 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -17,13 +17,10 @@ #include #include #include -#include #include "EventLog.h" -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) @@ -31,11 +28,11 @@ ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) EventLog::EventLog() { } -void EventLog::doLogFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { +void EventLog::doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR); buffer.startList(1 + numDurations); - buffer.writeString8(window); + buffer.writeString(name); for (size_t i = 0; i < numDurations; i++) { buffer.writeInt32(durations[i]); } @@ -43,10 +40,9 @@ void EventLog::doLogFrameDurations(const String8& window, buffer.log(); } -void EventLog::logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { - EventLog::getInstance().doLogFrameDurations(window, durations, - numDurations); +void EventLog::logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { + EventLog::getInstance().doLogFrameDurations(name, durations, numDurations); } // --------------------------------------------------------------------------- @@ -113,9 +109,9 @@ void EventLog::TagBuffer::writeInt64(int64_t value) { mPos += needed; } -void EventLog::TagBuffer::writeString8(const String8& value) { +void EventLog::TagBuffer::writeString(const std::string_view& value) { if (mOverflow) return; - const int32_t stringLen = value.length(); + const size_t stringLen = value.length(); const size_t needed = 1 + sizeof(int32_t) + stringLen; if (mPos + needed > STORAGE_MAX_SIZE) { mOverflow = true; @@ -123,11 +119,8 @@ void EventLog::TagBuffer::writeString8(const String8& value) { } mStorage[mPos + 0] = EVENT_TYPE_STRING; memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t)); - memcpy(&mStorage[mPos + 5], value.string(), stringLen); + memcpy(&mStorage[mPos + 5], value.data(), stringLen); mPos += needed; } -// --------------------------------------------------------------------------- -}// namespace android - -// --------------------------------------------------------------------------- +} // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h index efc5d70cd3..ee3587ef8a 100644 --- a/services/surfaceflinger/EventLog/EventLog.h +++ b/services/surfaceflinger/EventLog/EventLog.h @@ -14,24 +14,21 @@ * limitations under the License. */ -#include +#pragma once + #include #include -#ifndef ANDROID_SF_EVENTLOG_H -#define ANDROID_SF_EVENTLOG_H +#include +#include -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- - -class String8; class EventLog : public Singleton { public: - static void logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations); + static void logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); protected: EventLog(); @@ -54,18 +51,13 @@ private: public: explicit TagBuffer(int32_t tag); - // starts list of items void startList(int8_t count); - // terminates the list void endList(); - // write a 32-bit integer - void writeInt32(int32_t value); - // write a 64-bit integer - void writeInt64(int64_t value); - // write a C string - void writeString8(const String8& value); - // outputs the the buffer to the log + void writeInt32(int32_t); + void writeInt64(int64_t); + void writeString(const std::string_view&); + void log(); }; @@ -74,12 +66,8 @@ private: EventLog& operator =(const EventLog&); enum { LOGTAG_SF_FRAME_DUR = 60100 }; - void doLogFrameDurations(const String8& window, const int32_t* durations, - size_t numDurations); + void doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); }; -// --------------------------------------------------------------------------- -}// namespace android -// --------------------------------------------------------------------------- - -#endif /* ANDROID_SF_EVENTLOG_H */ +} // namespace android diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index f4cc49b851..a6e511e76e 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -21,7 +21,6 @@ #include #include -#include #include @@ -139,7 +138,7 @@ void FrameTracker::getStats(FrameStats* outStats) const { } } -void FrameTracker::logAndResetStats(const String8& name) { +void FrameTracker::logAndResetStats(const std::string_view& name) { Mutex::Autolock lock(mMutex); logStatsLocked(name); resetFrameCountersLocked(); @@ -217,7 +216,7 @@ void FrameTracker::resetFrameCountersLocked() { } } -void FrameTracker::logStatsLocked(const String8& name) const { +void FrameTracker::logStatsLocked(const std::string_view& name) const { for (int i = 0; i < NUM_FRAME_BUCKETS; i++) { if (mNumFrames[i] > 0) { EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS); diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index 555dcc1d1f..35382be1c0 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -14,20 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_FRAMETRACKER_H -#define ANDROID_FRAMETRACKER_H +#pragma once #include - -#include - #include -#include #include +#include -namespace android { +#include +#include -class String8; +namespace android { // FrameTracker tracks information about the most recently rendered frames. It // uses a circular buffer of frame records, and is *NOT* thread-safe - @@ -87,7 +84,7 @@ public: // logAndResetStats dumps the current statistics to the binary event log // and then resets the accumulated statistics to their initial values. - void logAndResetStats(const String8& name); + void logAndResetStats(const std::string_view& name); // dumpStats dump appends the current frame display time history to the result string. void dumpStats(std::string& result) const; @@ -123,7 +120,7 @@ private: void resetFrameCountersLocked(); // logStatsLocked dumps the current statistics to the binary event log. - void logStatsLocked(const String8& name) const; + void logStatsLocked(const std::string_view& name) const; // isFrameValidLocked returns true if the data for the given frame index is // valid and has all arrived (i.e. there are no oustanding fences). @@ -160,6 +157,4 @@ private: mutable Mutex mMutex; }; -} - -#endif // ANDROID_FRAMETRACKER_H +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6a45625c89..0c700a779f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -83,8 +83,6 @@ Layer::Layer(const LayerCreationArgs& args) if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - mTransactionName = String8("TX - ") + mName; - mCurrentState.active_legacy.w = args.w; mCurrentState.active_legacy.h = args.h; mCurrentState.flags = layerFlags; @@ -137,11 +135,11 @@ Layer::~Layer() { } LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags, + std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) : flinger(flinger), client(client), - name(name), + name(std::move(name)), w(w), h(h), flags(flags), @@ -235,10 +233,6 @@ void Layer::addToCurrentState() { // set-up // --------------------------------------------------------------------------- -const String8& Layer::getName() const { - return mName; -} - bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } @@ -523,7 +517,7 @@ void Layer::latchCompositionState(compositionengine::LayerFECompositionState& co } const char* Layer::getDebugName() const { - return mName.string(); + return mName.c_str(); } // --------------------------------------------------------------------------- @@ -614,7 +608,7 @@ void Layer::pushPendingState() { if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { - ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); + ALOGE("[%s] Unable to promote barrier Layer.", getDebugName()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). @@ -638,7 +632,7 @@ void Layer::pushPendingState() { mFlinger->setTransactionFlags(eTraversalNeeded); } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } void Layer::popPendingState(State* stateToCommit) { @@ -646,7 +640,7 @@ void Layer::popPendingState(State* stateToCommit) { *stateToCommit = mPendingStates[0]; mPendingStates.removeAt(0); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool Layer::applyPendingStates(State* stateToCommit) { @@ -657,7 +651,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting // into too much trouble. - ALOGE("[%s] No local sync point found", mName.string()); + ALOGE("[%s] No local sync point found", getDebugName()); popPendingState(stateToCommit); stateUpdateAvailable = true; continue; @@ -665,7 +659,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber_legacy) { - ALOGE("[%s] Unexpected sync point frame number found", mName.string()); + ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -717,7 +711,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), + this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -999,9 +993,10 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da if (!mCurrentState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor; - const String8& name = mName + "BackgroundColorLayer"; + std::string name = mName + "BackgroundColorLayer"; mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, + LayerMetadata())); // add to child list addChild(mCurrentState.bgColorLayer); @@ -1196,11 +1191,13 @@ void Layer::updateTransformHint(const sp& display) const { // TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { + using namespace std::string_literals; + LayerDebugInfo info; const State& ds = getDrawingState(); info.mName = getName(); sp parent = getParent(); - info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); + info.mParentName = parent ? parent->getName() : "none"s; info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; @@ -1267,12 +1264,12 @@ void Layer::miniDump(std::string& result, const sp& displayDevice std::string name; if (mName.length() > 77) { std::string shortened; - shortened.append(mName.string(), 36); + shortened.append(mName, 0, 36); shortened.append("[...]"); - shortened.append(mName.string() + (mName.length() - 36), 36); - name = shortened; + shortened.append(mName, mName.length() - 36); + name = std::move(shortened); } else { - name = std::string(mName.string(), mName.size()); + name = mName; } StringAppendF(&result, " %s\n", name.c_str()); @@ -1319,14 +1316,14 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this); + StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); } void Layer::dumpCallingUidPid(std::string& result) const { - StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(), + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(), mCallingPid, mCallingUid); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3023cf5df3..ad81920dc9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -79,12 +78,12 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- struct LayerCreationArgs { - LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, const String8& name, + LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata); SurfaceFlinger* flinger; const sp& client; - const String8& name; + std::string name; uint32_t w; uint32_t h; uint32_t flags; @@ -804,7 +803,7 @@ public: // Creates a new handle each time, so we only expect // this to be called once. sp getHandle(); - const String8& getName() const; + const std::string& getName() const { return mName; } virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; @@ -820,8 +819,8 @@ protected: bool usingRelativeZ(LayerVector::StateSet stateSet) const; bool mPremultipliedAlpha{true}; - String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces + const std::string mName; + const std::string mTransactionName{"TX - " + mName}; bool mPrimaryDisplayOnly = false; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 8a221837ac..1a60f1ed08 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -24,7 +24,7 @@ namespace android { LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, - bool& recomputeVisibleRegions, bool stickySet, const char* name, + bool& recomputeVisibleRegions, bool stickySet, const std::string& name, int32_t overrideScalingMode, bool transformToDisplayInverse) : mFront(front), mCurrent(current), @@ -90,7 +90,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) "(%4d,%4d) " "}\n" " requested_legacy={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), @@ -102,7 +102,8 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // reject this buffer ALOGE("[%s] rejecting buffer: " "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); + mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w, + mFront.active_legacy.h); return true; } } diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 1bd0c26dc6..fb5c750571 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -14,30 +14,29 @@ * limitations under the License. */ -#ifndef ANDROID_LAYER_REJECTER_H -#define ANDROID_LAYER_REJECTER_H +#pragma once #include "Layer.h" #include "BufferLayerConsumer.h" namespace android { - class LayerRejecter : public BufferLayerConsumer::BufferRejecter { - public: - LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions, - bool stickySet, const char *name, int32_t overrideScalingMode, - bool transformToDisplayInverse); - virtual bool reject(const sp &buf, const BufferItem &item); +class LayerRejecter : public BufferLayerConsumer::BufferRejecter { +public: + LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions, + bool stickySet, const std::string& name, int32_t overrideScalingMode, + bool transformToDisplayInverse); - private: - Layer::State &mFront; - Layer::State &mCurrent; - bool &mRecomputeVisibleRegions; - bool mStickyTransformSet; - const char *mName; - int32_t mOverrideScalingMode; - bool mTransformToDisplayInverse; - }; -} // namespace android + virtual bool reject(const sp&, const BufferItem&); -#endif // ANDROID_LAYER_REJECTER_H +private: + Layer::State& mFront; + Layer::State& mCurrent; + bool& mRecomputeVisibleRegions; + const bool mStickyTransformSet; + const std::string& mName; + const int32_t mOverrideScalingMode; + const bool mTransformToDisplayInverse; +}; + +} // namespace android diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 1c1367c916..30027decfb 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -436,7 +436,7 @@ void RegionSamplingThread::captureSample() { } if (!intersectsAnyArea) return; - ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left, + ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left, bounds.top, bounds.right, bounds.bottom); visitor(layer); }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54e20659a7..0e33f10ab6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -122,6 +122,8 @@ namespace android { +using namespace std::string_literals; + using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using namespace android::sysprop; @@ -1911,8 +1913,7 @@ void SurfaceFlinger::postComposition() layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime, presentFenceTime, compositorTiming); if (frameLatched) { - recordBufferingStats(layer->getName().string(), - layer->getOccupancyHistory(false)); + recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); } }); @@ -2574,7 +2575,7 @@ void SurfaceFlinger::commitTransactionLocked() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from for (const auto& l : mLayersPendingRemoval) { - recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); + recordBufferingStats(l->getName(), l->getOccupancyHistory(true)); // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { @@ -3244,11 +3245,12 @@ uint32_t SurfaceFlinger::setClientStateLocked( // everything else inherits layer stack from its parent. if (layer->hasParent()) { ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", - layer->getName().string()); + layer->getDebugName()); } else if (idx < 0) { ALOGE("Attempt to set layer stack on layer without parent (%s) that " - "that also does not appear in the top level layer list. Something" - " has gone wrong.", layer->getName().string()); + "that also does not appear in the top level layer list. Something" + " has gone wrong.", + layer->getDebugName()); } else if (layer->setLayerStack(s.layerStack)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); @@ -3406,7 +3408,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp sp mirrorLayer; sp mirrorFrom; - String8 uniqueName = getUniqueLayerName(String8("MirrorRoot")); + std::string uniqueName = getUniqueLayerName("MirrorRoot"); { Mutex::Autolock _l(mStateLock); @@ -3415,8 +3417,8 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp return NAME_NOT_FOUND; } - status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(), - outHandle, &mirrorLayer); + status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0, + LayerMetadata(), outHandle, &mirrorLayer); if (result != NO_ERROR) { return result; } @@ -3447,7 +3449,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie sp layer; - String8 uniqueName = getUniqueLayerName(name); + std::string uniqueName = getUniqueLayerName(name.string()); bool primaryDisplayOnly = false; @@ -3463,13 +3465,13 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: - result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata), - format, handle, gbp, &layer); + result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: // check if buffer size is set for color layer. @@ -3479,8 +3481,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return BAD_VALUE; } - result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle, - &layer); + result = createColorLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceContainer: // check if buffer size is set for container layer. @@ -3489,8 +3491,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie int(w), int(h)); return BAD_VALUE; } - result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createContainerLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; default: result = BAD_VALUE; @@ -3517,35 +3519,32 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return result; } -String8 SurfaceFlinger::getUniqueLayerName(const String8& name) -{ - bool matchFound = true; - uint32_t dupeCounter = 0; +std::string SurfaceFlinger::getUniqueLayerName(const char* name) { + unsigned dupeCounter = 0; // 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()); + std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter); // 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 + bool matchFound = true; while (matchFound) { matchFound = false; mCurrentState.traverseInZOrder([&](Layer* layer) { if (layer->getName() == uniqueName) { matchFound = true; - uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str()); + uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter); } }); } - ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), - uniqueName.c_str()); - + ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str()); return uniqueName; } -status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* handle, @@ -3563,8 +3562,7 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const } sp layer; - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.textureName = getNewTexture(); { // Grab the SF state lock during this since it's the only safe way to access @@ -3585,12 +3583,11 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const return err; } -status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.displayDevice = getDefaultDisplayDevice(); args.textureName = getNewTexture(); sp layer = getFactory().createBufferStateLayer(args); @@ -3600,26 +3597,25 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const return NO_ERROR; } -status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, +status_t SurfaceFlinger::createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createColorLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } -status_t SurfaceFlinger::createContainerLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createContainerLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } - void SurfaceFlinger::markLayerPendingRemovalLocked(const sp& layer) { mLayersPendingRemoval.add(layer); mLayersRemoved = true; @@ -3828,8 +3824,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, strerror(-err), err); } - using namespace std::string_literals; - static const std::unordered_map dumpers = { {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, @@ -3885,7 +3879,7 @@ status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { void SurfaceFlinger::listLayersLocked(std::string& result) const { mCurrentState.traverseInZOrder( - [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); }); + [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); }); } void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const { @@ -3894,7 +3888,7 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) if (args.size() > 1) { const auto name = String8(args[1]); mCurrentState.traverseInZOrder([&](Layer* layer) { - if (name == layer->getName()) { + if (layer->getName() == name.string()) { layer->dumpFrameStats(result); } }); @@ -3904,8 +3898,11 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) } void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) { + const bool clearAll = args.size() < 2; + const auto name = clearAll ? String8() : String8(args[1]); + mCurrentState.traverseInZOrder([&](Layer* layer) { - if (args.size() < 2 || String8(args[1]) == layer->getName()) { + if (clearAll || layer->getName() == name.string()) { layer->clearFrameStats(); } }); @@ -3924,7 +3921,7 @@ void SurfaceFlinger::logFrameStats() { layer->logFrameStats(); }); - mAnimFrameTracker.logAndResetStats(String8("")); + mAnimFrameTracker.logAndResetStats(""); } void SurfaceFlinger::appendSfConfigString(std::string& result) const { @@ -3982,8 +3979,8 @@ void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const { bucketTimeSec, percent); } -void SurfaceFlinger::recordBufferingStats(const char* layerName, - std::vector&& history) { +void SurfaceFlinger::recordBufferingStats(const std::string& layerName, + std::vector&& history) { Mutex::Autolock lock(getBE().mBufferingStatsMutex); auto& stats = getBE().mBufferingStats[layerName]; for (const auto& segment : history) { @@ -5031,13 +5028,14 @@ status_t SurfaceFlinger::captureLayers( drawLayers(); } else { Rect bounds = getBounds(); + uint32_t w = static_cast(bounds.getWidth()); + uint32_t h = static_cast(bounds.getHeight()); // In the "childrenOnly" case we reparent the children to a screenshot // layer which has no properties set and which does not draw. sp screenshotParentLayer = - mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"), - bounds.getWidth(), bounds.getHeight(), 0, - LayerMetadata())); + mFlinger->getFactory().createContainerLayer({mFlinger, nullptr, + "Screenshot Parent"s, w, h, 0, + LayerMetadata()}); ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop); drawLayers(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9f3a914366..b719245caa 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -607,27 +607,27 @@ private: sp* handle, sp* gbp, const sp& parentHandle, const sp& parentLayer = nullptr); - status_t createBufferQueueLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* outHandle, sp* outGbp, sp* outLayer); - status_t createBufferStateLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, + status_t createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createContainerLayer(const sp& client, const String8& name, uint32_t w, + status_t createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, sp* outHandle); - String8 getUniqueLayerName(const String8& name); + std::string getUniqueLayerName(const char* name); // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all @@ -866,8 +866,8 @@ private: // Not const because each Layer needs to query Fences and cache timestamps. void dumpFrameEventsLocked(std::string& result); - void recordBufferingStats(const char* layerName, - std::vector&& history); + void recordBufferingStats(const std::string& layerName, + std::vector&& history); void dumpBufferingStats(std::string& result) const; void dumpDisplayIdentificationData(std::string& result) const; void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index a02d14cc4d..7e6c472d7f 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -165,10 +165,6 @@ const sp SurfaceInterceptor::getLayer(const wp& weak return layer; } -const std::string SurfaceInterceptor::getLayerName(const sp& layer) const { - return layer->getName().string(); -} - int32_t SurfaceInterceptor::getLayerId(const sp& layer) const { return layer->sequence; } @@ -490,7 +486,7 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, { SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); - creation->set_name(getLayerName(layer)); + creation->set_name(layer->getName()); creation->set_w(layer->mCurrentState.active_legacy.w); creation->set_h(layer->mCurrentState.active_legacy.h); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 6858c4d5a6..72b734b8fd 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -123,7 +123,6 @@ private: status_t writeProtoFileLocked(); const sp getLayer(const wp& weakHandle) const; - const std::string getLayerName(const sp& layer) const; int32_t getLayerId(const sp& layer) const; int32_t getLayerIdFromWeakRef(const wp& layer) const; int32_t getLayerIdFromHandle(const sp& weakHandle) const; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 8aff096d5e..60da70fd25 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -839,7 +839,7 @@ struct ColorLayerVariant : public BaseLayerVariant { static FlingerLayerType createLayer(CompositionTest* test) { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, + "test-layer", LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata())); }); @@ -879,11 +879,9 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { sp client; - String8 name("test-layer"); - LayerCreationArgs args = - LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, - LayerProperties::WIDTH, LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata()); + LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer", + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); args.textureName = test->mFlinger.mutableTexturePool().back(); return new BufferQueueLayer(args); }); -- cgit v1.2.3-59-g8ed1b From f7a09ed2b7f85378e3043b1ce21617fc0a2bde12 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 7 Oct 2019 13:54:18 -0700 Subject: SF: Optimize layer history in scheduler Register layers with LayerHistory by storing a weak pointer rather than allocating a LayerHandle. Query layer visibility when needed instead of synchronizing it to LayerInfo whenever Layer::isVisible is called. Store active/inactive layers in contiguous memory instead of two hash maps for cache efficiency, and minimal allocation and run time of operations like clearing history. Remove redundant ref-counting, locking, and frequency- period conversion in LayerInfo. Avoid sleeping in unit tests. This is also prework for per-display layer history. Bug: 130554049 Bug: 134772048 Test: go/wm-smoke with debug.sf.layer_history_trace Test: C2/F2 test cases from spreadsheet Test: LayerHistoryTest with new test cases Change-Id: Ibfcfe46cd76ebd93b916d4a0c737a19e837d4ff1 --- services/surfaceflinger/BufferLayer.cpp | 5 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferStateLayer.cpp | 4 +- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 217 +++++++-------- services/surfaceflinger/Scheduler/LayerHistory.h | 100 +++---- services/surfaceflinger/Scheduler/LayerInfo.cpp | 35 +-- services/surfaceflinger/Scheduler/LayerInfo.h | 170 +++++------- services/surfaceflinger/Scheduler/Scheduler.cpp | 47 ++-- services/surfaceflinger/Scheduler/Scheduler.h | 16 +- services/surfaceflinger/Scheduler/SchedulerUtils.h | 16 -- services/surfaceflinger/SurfaceFlinger.cpp | 10 + services/surfaceflinger/SurfaceFlinger.h | 7 +- .../tests/unittests/LayerHistoryTest.cpp | 291 ++++++++++++++------- .../tests/unittests/TestableScheduler.h | 1 + .../tests/unittests/TestableSurfaceFlinger.h | 6 +- .../tests/unittests/mock/MockLayer.h | 35 +++ 18 files changed, 502 insertions(+), 470 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/mock/MockLayer.h (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 603a9f7f70..a25709ceee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -107,11 +107,8 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } bool BufferLayer::isVisible() const { - bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && + return !isHiddenByPolicy() && getAlpha() > 0.0f && (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); - mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); - - return visible; } bool BufferLayer::isFixedSize() const { diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 8cc1831d0f..c24cdaa617 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -389,8 +389,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { { // Autolock scope if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - item.mHdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + item.mHdrMetadata.validTypes != 0); } Mutex::Autolock lock(mQueueItemLock); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 85d2253bf5..5768edd744 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -249,8 +249,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = (desiredPresentTime == -1) ? 0 : desiredPresentTime; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - mCurrentState.hdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + mCurrentState.hdrMetadata.validTypes != 0); } return true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 37caab2b3f..e19b79b7c5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,10 +118,9 @@ Layer::Layer(const LayerCreationArgs& args) mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); - mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType); mCallingPid = args.callingPid; mCallingUid = args.callingUid; - mFlinger->onLayerCreated(); + mFlinger->onLayerCreated(this); } Layer::~Layer() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ad81920dc9..fdac98f317 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -221,6 +221,8 @@ public: explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); + int getWindowType() const { return mWindowType; } + void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } bool getPrimaryDisplayOnly() const { return mPrimaryDisplayOnly; } @@ -886,9 +888,6 @@ protected: // Window types from WindowManager.LayoutParams const int mWindowType; - // This is populated if the layer is registered with Scheduler for tracking purposes. - std::unique_ptr mSchedulerLayerHandle; - private: /** * Returns an unsorted vector of all layers that are part of this tree. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 5473db6974..8b717289c6 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -14,183 +14,150 @@ * limitations under the License. */ +#undef LOG_TAG +#define LOG_TAG "LayerHistory" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "LayerHistory.h" -#include -#include -#include -#include -#include -#include - #include #include #include #include +#include +#include +#include +#include + +#include "../Layer.h" +#include "LayerInfo.h" #include "SchedulerUtils.h" -namespace android { -namespace scheduler { +namespace android::scheduler { -std::atomic LayerHistory::sNextId = 0; +namespace { -LayerHistory::LayerHistory() { +bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { + return layer.isVisible() && (info.isHDR() || info.getLastUpdatedTime() >= threshold); +} + +bool traceEnabled() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.layer_history_trace", value, "0"); - mTraceEnabled = static_cast(atoi(value)); + return atoi(value); } -LayerHistory::~LayerHistory() = default; +void trace(const wp& weak, int fps) { + const auto layer = weak.promote(); + if (!layer) return; + + const auto& name = layer->getName(); + const auto tag = "LFPS " + name; + ATRACE_INT(tag.c_str(), fps); + ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps); +} -std::unique_ptr LayerHistory::createLayer(const std::string name, - float minRefreshRate, - float maxRefreshRate) { - const int64_t id = sNextId++; +} // namespace +LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()) {} +LayerHistory::~LayerHistory() = default; + +void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { + auto info = std::make_unique(lowRefreshRate, highRefreshRate); std::lock_guard lock(mLock); - mInactiveLayerInfos.emplace(id, - std::make_shared(name, minRefreshRate, maxRefreshRate)); - return std::make_unique(*this, id); + mLayerInfos.emplace_back(layer, std::move(info)); } -void LayerHistory::destroyLayer(const int64_t id) { +void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t now) { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.find(id); - if (it != mActiveLayerInfos.end()) { - mActiveLayerInfos.erase(it); - } - it = mInactiveLayerInfos.find(id); - if (it != mInactiveLayerInfos.end()) { - mInactiveLayerInfos.erase(it); - } -} + const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), + [layer](const auto& pair) { return pair.first == layer; }); + LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); -void LayerHistory::insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, - bool isHdr) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } - } - layerInfo->setLastPresentTime(presentTime); - layerInfo->setHDRContent(isHdr); -} + const auto& info = it->second; + info->setLastPresentTime(presentTime, now); + info->setIsHDR(isHDR); -void LayerHistory::setVisibility(const std::unique_ptr& layerHandle, bool visible) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - if (visible) { - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } + // Activate layer if inactive. + if (const auto end = activeLayers().end(); it >= end) { + std::iter_swap(it, end); + mActiveLayersEnd++; } - layerInfo->setVisibility(visible); } -std::pair LayerHistory::getDesiredRefreshRateAndHDR() { +LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { + float maxRefreshRate = 0; bool isHDR = false; - float newRefreshRate = 0.f; + std::lock_guard lock(mLock); - removeIrrelevantLayers(); + partitionLayers(now); - // Iterate through all layers that have been recently updated, and find the max refresh rate. - for (const auto& [layerId, layerInfo] : mActiveLayerInfos) { - const bool recent = layerInfo->isRecentlyActive(); + // Find the maximum refresh rate among recently active layers. + for (const auto& [layer, info] : activeLayers()) { + const bool recent = info->isRecentlyActive(now); if (recent || CC_UNLIKELY(mTraceEnabled)) { - const float refreshRate = layerInfo->getDesiredRefreshRate(); - if (recent && refreshRate > newRefreshRate) { - newRefreshRate = refreshRate; + const float refreshRate = info->getRefreshRate(now); + if (recent && refreshRate > maxRefreshRate) { + maxRefreshRate = refreshRate; } if (CC_UNLIKELY(mTraceEnabled)) { - std::string name = "LFPS " + layerInfo->getName(); - const float rate = std::round(refreshRate); - ATRACE_INT(name.c_str(), rate); - ALOGD("%s: %f", name.c_str(), rate); + trace(layer, std::round(refreshRate)); } } - isHDR |= layerInfo->getHDRContent(); + isHDR |= info->isHDR(); } if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate); + ALOGD("%s: maxRefreshRate=%.2f, isHDR=%d", __FUNCTION__, maxRefreshRate, isHDR); } - return {newRefreshRate, isHDR}; + return {maxRefreshRate, isHDR}; } -void LayerHistory::removeIrrelevantLayers() { - const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - // Iterator pointing to first element in map - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - // If last updated was before the obsolete time, remove it. - // Keep HDR layer around as long as they are visible. - if (!it->second->isVisible() || - (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) { - // erase() function returns the iterator of the next - // to last deleted element. - if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("Layer %s obsolete", it->second->getName().c_str()); - // Make sure to update systrace to indicate that the layer was erased. - std::string layerName = "LFPS " + it->second->getName(); - ATRACE_INT(layerName.c_str(), 0); - } - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); +void LayerHistory::partitionLayers(nsecs_t now) { + const nsecs_t threshold = getActiveLayerThreshold(now); + + // Collect expired and inactive layers after active layers. + size_t i = 0; + while (i < mActiveLayersEnd) { + auto& [weak, info] = mLayerInfos[i]; + if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) { + i++; + continue; + } + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(weak, 0); + } + + info->clearHistory(); + std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]); + } + + // Collect expired layers after inactive layers. + size_t end = mLayerInfos.size(); + while (i < end) { + if (mLayerInfos[i].first.promote()) { + i++; } else { - ++it; + std::swap(mLayerInfos[i], mLayerInfos[--end]); } } + + mLayerInfos.erase(mLayerInfos.begin() + end, mLayerInfos.end()); } -void LayerHistory::clearHistory() { +void LayerHistory::clear() { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); + for (const auto& [layer, info] : activeLayers()) { + info->clearHistory(); } + + mActiveLayersEnd = 0; } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 5598cc1cf5..15ac8caccb 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -16,76 +16,78 @@ #pragma once -#include -#include -#include -#include -#include -#include - +#include +#include #include -#include "LayerInfo.h" -#include "SchedulerUtils.h" +#include +#include +#include +#include namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about layers that are considered current. We keep an - * unordered map between layer name and LayerInfo. - */ +class LayerInfo; + +// Records per-layer history of scheduling-related information (primarily present time), +// heuristically categorizes layers as active or inactive, and summarizes stats about +// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler. class LayerHistory { public: - // Handle for each layer we keep track of. - class LayerHandle { - public: - LayerHandle(LayerHistory& lh, int64_t id) : mId(id), mLayerHistory(lh) {} - ~LayerHandle() { mLayerHistory.destroyLayer(mId); } + LayerHistory(); + ~LayerHistory(); - const int64_t mId; + // Layers are unregistered when the weak reference expires. + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate); - private: - LayerHistory& mLayerHistory; + // Marks the layer as active, and records the given state to its history. + void record(Layer*, nsecs_t presentTime, bool isHDR, nsecs_t now); + + struct Summary { + float maxRefreshRate; // Maximum refresh rate among recently active layers. + bool isHDR; // True if any recently active layer has HDR content. }; - LayerHistory(); - ~LayerHistory(); + // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. + Summary summarize(nsecs_t now); - // When the layer is first created, register it. - std::unique_ptr createLayer(const std::string name, float minRefreshRate, - float maxRefreshRate); + void clear(); - // Method for inserting layers and their requested present time into the unordered map. - void insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, bool isHdr); - // Method for setting layer visibility - void setVisibility(const std::unique_ptr& layerHandle, bool visible); +private: + friend class LayerHistoryTest; - // Returns the desired refresh rate, which is a max refresh rate of all the current - // layers. See go/content-fps-detection-in-scheduler for more information. - std::pair getDesiredRefreshRateAndHDR(); + using LayerPair = std::pair, std::unique_ptr>; + using LayerInfos = std::vector; - // Clears all layer history. - void clearHistory(); + struct ActiveLayers { + LayerInfos& infos; + const size_t index; - // Removes the handle and the object from the map. - void destroyLayer(const int64_t id); + auto begin() { return infos.begin(); } + auto end() { return begin() + index; } + }; -private: - // Removes the layers that have been idle for a given amount of time from mLayerInfos. - void removeIrrelevantLayers() REQUIRES(mLock); + ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; } + + // Iterates over layers in a single pass, swapping pairs such that active layers precede + // inactive layers, and inactive layers precede expired layers. Removes expired layers by + // truncating after inactive layers. + void partitionLayers(nsecs_t now) REQUIRES(mLock); - // Information about currently active layers. - std::mutex mLock; - std::unordered_map> mActiveLayerInfos GUARDED_BY(mLock); - std::unordered_map> mInactiveLayerInfos GUARDED_BY(mLock); + mutable std::mutex mLock; - // Each layer has it's own ID. This variable keeps track of the count. - static std::atomic sNextId; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active + // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. + LayerInfos mLayerInfos GUARDED_BY(mLock); + size_t mActiveLayersEnd GUARDED_BY(mLock) = 0; - // Flag whether to log layer FPS in systrace - bool mTraceEnabled = false; + // Whether to emit systrace output and debug logs. + const bool mTraceEnabled; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 723d71ff39..f3b0d56302 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -16,27 +16,17 @@ #include "LayerInfo.h" -#include -#include -#include -#include +#include +#include -namespace android { -namespace scheduler { +namespace android::scheduler { -LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate) - : mName(name), - mMinRefreshDuration(1e9f / maxRefreshRate), - mLowActivityRefreshDuration(1e9f / minRefreshRate), - mRefreshRateHistory(mMinRefreshDuration) {} - -LayerInfo::~LayerInfo() = default; - -void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { - std::lock_guard lock(mLock); +LayerInfo::LayerInfo(float lowRefreshRate, float highRefreshRate) + : mLowRefreshRate(lowRefreshRate), mHighRefreshRate(highRefreshRate) {} +void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { // Buffers can come with a present time far in the future. That keeps them relevant. - mLastUpdatedTime = std::max(lastPresentTime, systemTime()); + mLastUpdatedTime = std::max(lastPresentTime, now); mPresentTimeHistory.insertPresentTime(mLastUpdatedTime); if (mLastPresentTime == 0) { @@ -45,14 +35,13 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { return; } - const nsecs_t timeDiff = lastPresentTime - mLastPresentTime; + const nsecs_t period = lastPresentTime - mLastPresentTime; mLastPresentTime = lastPresentTime; // Ignore time diff that are too high - those are stale values - if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return; - const nsecs_t refreshDuration = std::max(timeDiff, mMinRefreshDuration); - const int fps = 1e9f / refreshDuration; + if (period > MAX_ACTIVE_LAYER_PERIOD_NS.count()) return; + + const float fps = std::min(1e9f / period, mHighRefreshRate); mRefreshRateHistory.insertRefreshRate(fps); } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 17afddac28..b86709fc9c 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -16,27 +16,37 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include - -#include #include +#include +#include + #include "SchedulerUtils.h" namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about individial layers. - */ +using namespace std::chrono_literals; + +// Maximum period between presents for a layer to be considered active. +constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms; + +// Earliest present time for a layer to be considered active. +constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) { + return now - MAX_ACTIVE_LAYER_PERIOD_NS.count(); +} + +// Stores history of present times and refresh rates for a layer. class LayerInfo { + // Layer is considered frequent if the earliest value in the window of most recent present times + // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in + // favor of a low refresh rate. + static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; + static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms; + /** * Struct that keeps the information about the refresh rate for last * HISTORY_SIZE frames. This is used to better determine the refresh rate @@ -44,9 +54,9 @@ class LayerInfo { */ class RefreshRateHistory { public: - explicit RefreshRateHistory(nsecs_t minRefreshDuration) - : mMinRefreshDuration(minRefreshDuration) {} - void insertRefreshRate(int refreshRate) { + explicit RefreshRateHistory(float highRefreshRate) : mHighRefreshRate(highRefreshRate) {} + + void insertRefreshRate(float refreshRate) { mElements.push_back(refreshRate); if (mElements.size() > HISTORY_SIZE) { mElements.pop_front(); @@ -54,19 +64,16 @@ class LayerInfo { } float getRefreshRateAvg() const { - if (mElements.empty()) { - return 1e9f / mMinRefreshDuration; - } - - return scheduler::calculate_mean(mElements); + return mElements.empty() ? mHighRefreshRate : calculate_mean(mElements); } void clearHistory() { mElements.clear(); } private: - std::deque mElements; + const float mHighRefreshRate; + static constexpr size_t HISTORY_SIZE = 30; - const nsecs_t mMinRefreshDuration; + std::deque mElements; }; /** @@ -76,6 +83,8 @@ class LayerInfo { */ class PresentTimeHistory { public: + static constexpr size_t HISTORY_SIZE = 90; + void insertPresentTime(nsecs_t presentTime) { mElements.push_back(presentTime); if (mElements.size() > HISTORY_SIZE) { @@ -83,60 +92,45 @@ class LayerInfo { } } - // Checks whether the present time that was inserted HISTORY_SIZE ago is within a - // certain threshold: TIME_EPSILON_NS. - bool isRelevant() const { + // Returns whether the earliest present time is within the active threshold. + bool isRecentlyActive(nsecs_t now) const { if (mElements.size() < 2) { return false; } // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates - if (mElements.size() != HISTORY_SIZE && - mElements.at(mElements.size() - 1) - mElements.at(0) < HISTORY_TIME.count()) { + if (mElements.size() < HISTORY_SIZE && + mElements.back() - mElements.front() < HISTORY_TIME.count()) { return false; } - // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds. - const int64_t obsoleteEpsilon = - systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) { - return false; - } - - return true; + return mElements.back() >= getActiveLayerThreshold(now); } - bool isLowActivityLayer() const { - // We want to make sure that we received more than two frames from the layer - // in order to check low activity. - if (mElements.size() < scheduler::LOW_ACTIVITY_BUFFERS + 1) { + bool isFrequent(nsecs_t now) const { + // Assume layer is infrequent if too few present times have been recorded. + if (mElements.size() < FREQUENT_LAYER_WINDOW_SIZE) { return false; } - const int64_t obsoleteEpsilon = - systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count(); - // Check the frame before last to determine whether there is low activity. - // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending - // infrequent updates. - if (mElements.at(mElements.size() - (scheduler::LOW_ACTIVITY_BUFFERS + 1)) < - obsoleteEpsilon) { - return true; - } - - return false; + // Layer is frequent if the earliest value in the window of most recent present times is + // within threshold. + const auto it = mElements.end() - FREQUENT_LAYER_WINDOW_SIZE; + const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count(); + return *it >= threshold; } void clearHistory() { mElements.clear(); } private: std::deque mElements; - static constexpr size_t HISTORY_SIZE = 90; static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; }; + friend class LayerHistoryTest; + public: - LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate); - ~LayerInfo(); + LayerInfo(float lowRefreshRate, float highRefreshRate); LayerInfo(const LayerInfo&) = delete; LayerInfo& operator=(const LayerInfo&) = delete; @@ -144,71 +138,37 @@ public: // Records the last requested oresent time. It also stores information about when // the layer was last updated. If the present time is farther in the future than the // updated time, the updated time is the present time. - void setLastPresentTime(nsecs_t lastPresentTime); + void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); - void setHDRContent(bool isHdr) { - std::lock_guard lock(mLock); - mIsHDR = isHdr; - } + bool isHDR() const { return mIsHDR; } + void setIsHDR(bool isHDR) { mIsHDR = isHDR; } - void setVisibility(bool visible) { - std::lock_guard lock(mLock); - mIsVisible = visible; - } + bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); } + bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); } - // Checks the present time history to see whether the layer is relevant. - bool isRecentlyActive() const { - std::lock_guard lock(mLock); - return mPresentTimeHistory.isRelevant(); - } - - // Calculate the average refresh rate. - float getDesiredRefreshRate() const { - std::lock_guard lock(mLock); - - if (mPresentTimeHistory.isLowActivityLayer()) { - return 1e9f / mLowActivityRefreshDuration; - } - return mRefreshRateHistory.getRefreshRateAvg(); - } - - bool getHDRContent() { - std::lock_guard lock(mLock); - return mIsHDR; - } - - bool isVisible() { - std::lock_guard lock(mLock); - return mIsVisible; + float getRefreshRate(nsecs_t now) const { + return isFrequent(now) ? mRefreshRateHistory.getRefreshRateAvg() : mLowRefreshRate; } // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. - nsecs_t getLastUpdatedTime() { - std::lock_guard lock(mLock); - return mLastUpdatedTime; - } - - std::string getName() const { return mName; } + nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } void clearHistory() { - std::lock_guard lock(mLock); mRefreshRateHistory.clearHistory(); mPresentTimeHistory.clearHistory(); } private: - const std::string mName; - const nsecs_t mMinRefreshDuration; - const nsecs_t mLowActivityRefreshDuration; - mutable std::mutex mLock; - nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0; - nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; - RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock); - PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock); - bool mIsHDR GUARDED_BY(mLock) = false; - bool mIsVisible GUARDED_BY(mLock) = false; + const float mLowRefreshRate; + const float mHighRefreshRate; + + nsecs_t mLastUpdatedTime = 0; + nsecs_t mLastPresentTime = 0; + RefreshRateHistory mRefreshRateHistory{mHighRefreshRate}; + PresentTimeHistory mPresentTimeHistory; + bool mIsHDR = false; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index d60e101fb4..71b35001b6 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -20,13 +20,6 @@ #include "Scheduler.h" -#include -#include -#include -#include -#include -#include - #include #include #include @@ -37,6 +30,14 @@ #include #include +#include +#include +#include +#include +#include +#include + +#include "../Layer.h" #include "DispSync.h" #include "DispSyncSource.h" #include "EventControlThread.h" @@ -325,37 +326,27 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { return mPrimaryDispSync->expectedPresentTime(); } -std::unique_ptr Scheduler::registerLayer( - std::string const& name, int windowType) { +void Scheduler::registerLayer(Layer* layer) { uint32_t defaultFps, performanceFps; if (mRefreshRateConfigs.refreshRateSwitchingSupported()) { defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - performanceFps = - mRefreshRateConfigs - .getRefreshRateFromType((windowType == InputWindowInfo::TYPE_WALLPAPER) - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE) - .fps; + const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? RefreshRateType::DEFAULT + : RefreshRateType::PERFORMANCE; + performanceFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; } else { defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps; performanceFps = defaultFps; } - return mLayerHistory.createLayer(name, defaultFps, performanceFps); -} - -void Scheduler::addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR) { - mLayerHistory.insert(layerHandle, presentTime, isHDR); + mLayerHistory.registerLayer(layer, defaultFps, performanceFps); } -void Scheduler::setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible) { - mLayerHistory.setVisibility(layerHandle, visible); +void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { + mLayerHistory.record(layer, presentTime, isHDR, systemTime()); } void Scheduler::updateFpsBasedOnContent() { - auto [refreshRate, isHDR] = mLayerHistory.getDesiredRefreshRateAndHDR(); + auto [refreshRate, isHDR] = mLayerHistory.summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); RefreshRateType newRefreshRateType; { @@ -402,7 +393,7 @@ void Scheduler::notifyTouchEvent() { // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::setDisplayPowerState(bool normal) { @@ -417,7 +408,7 @@ void Scheduler::setDisplayPowerState(bool normal) { // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::kernelIdleTimerCallback(TimerState state) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index a5971fed23..c98347522e 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -100,17 +100,11 @@ public: void addPresentFence(const std::shared_ptr&); void setIgnorePresentFences(bool ignore); nsecs_t getDispSyncExpectedPresentTime(); - // Registers the layer in the scheduler, and returns the handle for future references. - std::unique_ptr registerLayer(std::string const& name, - int windowType); - - // Stores present time for a layer. - void addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR); - // Stores visibility for a layer. - void setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible); + + // Layers are registered on creation, and unregistered when the weak reference expires. + void registerLayer(Layer*); + void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); + // Updates FPS based on the most content presented. void updateFpsBasedOnContent(); diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h index 3b7567ce8b..d301b9977b 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.h +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h @@ -16,7 +16,6 @@ #pragma once -#include #include #include #include @@ -38,21 +37,6 @@ inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) { return lhs.id == rhs.id; } -using namespace std::chrono_literals; - -// This number is used when we try to determine how long do we keep layer information around -// before we remove it. It is also used to determine how long the layer stays relevant. -// This time period captures infrequent updates when playing YouTube video with static image, -// or waiting idle in messaging app, when cursor is blinking. -static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms; - -// Layer is considered low activity if the LOW_ACTIVITY_BUFFERS buffers come more than -// LOW_ACTIVITY_EPSILON_NS apart. -// This is helping SF to vote for lower refresh rates when there is not activity -// in screen. -static constexpr int LOW_ACTIVITY_BUFFERS = 2; -static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms; - // Calculates the statistical mean (average) in the data structure (array, vector). The // function does not modify the contents of the array. template diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 057669b376..1acb2da051 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5505,6 +5505,16 @@ sp SurfaceFlinger::fromHandle(const sp& handle) { return nullptr; } +void SurfaceFlinger::onLayerCreated(Layer* layer) { + mNumLayers++; + mScheduler->registerLayer(layer); +} + +void SurfaceFlinger::onLayerDestroyed(Layer* layer) { + mNumLayers--; + mOffscreenLayers.erase(layer); +} + void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b719245caa..abb8b821ba 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -310,11 +310,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; - inline void onLayerCreated() { mNumLayers++; } - inline void onLayerDestroyed(Layer* layer) { - mNumLayers--; - mOffscreenLayers.erase(layer); - } + void onLayerCreated(Layer*); + void onLayerDestroyed(Layer*); TransactionCompletedThread& getTransactionCompletedThread() { return mTransactionCompletedThread; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 8e7440c2e3..9a962bcc0c 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1,140 +1,243 @@ #undef LOG_TAG -#define LOG_TAG "LayerHistoryUnittests" +#define LOG_TAG "LayerHistoryTest" #include #include - #include -#include -#include - #include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfo.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockLayer.h" using testing::_; using testing::Return; -namespace android { -namespace scheduler { +namespace android::scheduler { class LayerHistoryTest : public testing::Test { -public: - LayerHistoryTest(); - ~LayerHistoryTest() override; - protected: - std::unique_ptr mLayerHistory; + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::PresentTimeHistory::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfo::MAX_FREQUENT_LAYER_PERIOD_NS; - static constexpr float MIN_REFRESH_RATE = 30.f; - static constexpr float MAX_REFRESH_RATE = 90.f; - static constexpr auto RELEVANT_FRAME_THRESHOLD = 90u; - static constexpr uint64_t THIRTY_FPS_INTERVAL = 33'333'333; + static constexpr float LO_FPS = 30.f; + static constexpr nsecs_t LO_FPS_PERIOD = 33'333'333; - void forceRelevancy(const std::unique_ptr& testLayer) { - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); - } - }; -}; + static constexpr float HI_FPS = 90.f; + static constexpr nsecs_t HI_FPS_PERIOD = 11'111'111; -LayerHistoryTest::LayerHistoryTest() { - mLayerHistory = std::make_unique(); -} -LayerHistoryTest::~LayerHistoryTest() {} + LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } + + LayerHistory& history() { return mScheduler->mutableLayerHistory(); } + const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } + + size_t layerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mLayerInfos.size(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } + + size_t frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mLayerInfos; + return std::count_if(infos.begin(), infos.begin() + history().mActiveLayersEnd, + [now](const auto& pair) { return pair.second->isFrequent(now); }); + } + + auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + + RefreshRateConfigs mConfigs{true, + {RefreshRateConfigs::InputConfig{0, LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{1, HI_FPS_PERIOD}}, + 0}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; + TestableSurfaceFlinger mFlinger; + + const nsecs_t mTime = systemTime(); +}; namespace { + TEST_F(LayerHistoryTest, oneLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if no layers are active. + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if active layers have insufficient history. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } - // Add a few more. This time we should get MAX refresh rate as the layer - // becomes relevant - static constexpr auto A_FEW = 10; - for (auto i = 0u; i < A_FEW; i++) { - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + // High FPS is returned once enough history has been recorded. + for (int i = 0; i < 10; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } } TEST_F(LayerHistoryTest, oneHDRLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); + const auto layer = createLayer(); + constexpr bool isHDR = true; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + history().record(layer.get(), 0, isHDR, mTime); + auto summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_TRUE(summary.isHDR); + EXPECT_EQ(1, activeLayerCount()); - mLayerHistory->insert(testLayer, 0, true /*isHDR*/); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(true, mLayerHistory->getDesiredRefreshRateAndHDR().second); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - mLayerHistory->setVisibility(testLayer, false); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(false, mLayerHistory->getDesiredRefreshRateAndHDR().second); + summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_FALSE(summary.isHDR); + EXPECT_EQ(0, activeLayerCount()); } TEST_F(LayerHistoryTest, explicitTimestamp) { - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, multipleLayers) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - std::unique_ptr testLayer2 = - mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer2, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + auto layer1 = createLayer(); + auto layer2 = createLayer(); + auto layer3 = createLayer(); + constexpr bool isHDR = false; + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + + nsecs_t time = mTime; + + EXPECT_EQ(3, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer1.get(), time, isHDR, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - for (int i = 10; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + // layer1 is still active but infrequent. + history().record(layer1.get(), time, isHDR, time); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // This frame is only around for 9 occurrences, so it doesn't throw - // anything off. - for (int i = 0; i < 9; i++) { - mLayerHistory->insert(testLayer2, 0, false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + history().record(layer2.get(), time, isHDR, time); + } + + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + history().record(layer3.get(), time, isHDR, time); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + layer1.clear(); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + layer2.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // After 1200 ms frames become obsolete. - std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - - mLayerHistory->insert(test30FpsLayer, - startTime + (RELEVANT_FRAME_THRESHOLD * THIRTY_FPS_INTERVAL), - false /*isHDR*/); - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + layer3.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(0, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); } } // namespace -} // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index ae7246780a..ae6aa899af 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -48,6 +48,7 @@ public: auto& mutableEventControlThread() { return mEventControlThread; } auto& mutablePrimaryDispSync() { return mPrimaryDispSync; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } + auto& mutableLayerHistory() { return mLayerHistory; } ~TestableScheduler() { // All these pointer and container clears help ensure that GMock does diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c7664fb9ac..94fc5f7273 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "BufferQueueLayer.h" #include "BufferStateLayer.h" @@ -173,6 +174,7 @@ public: class TestableSurfaceFlinger { public: + SurfaceFlinger* flinger() { return mFlinger.get(); } TestableScheduler* scheduler() { return mScheduler; } // Extend this as needed for accessing SurfaceFlinger private (and public) @@ -207,13 +209,15 @@ public: mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); + resetScheduler(mScheduler); - mFlinger->mScheduler.reset(mScheduler); mFlinger->mVSyncModulator.emplace(*mScheduler, mFlinger->mAppConnectionHandle, mFlinger->mSfConnectionHandle, mFlinger->mPhaseOffsets->getCurrentOffsets()); } + void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } + using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { mFactory.mCreateBufferQueue = f; diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h new file mode 100644 index 0000000000..f375e23700 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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 + +#include "Layer.h" + +namespace android::mock { + +class MockLayer : public Layer { +public: + explicit MockLayer(SurfaceFlinger* flinger) + : Layer(LayerCreationArgs(flinger, nullptr, "TestLayer", 800, 600, 0, {})) {} + + MOCK_CONST_METHOD0(getType, const char*()); + MOCK_CONST_METHOD0(isVisible, bool()); + MOCK_METHOD0(createClone, sp()); +}; + +} // namespace android::mock -- cgit v1.2.3-59-g8ed1b From 1a88c40d5623b61bd66338f5df0e8857d249fa79 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 18 Nov 2019 10:43:58 -0800 Subject: TimeStats & FrameTracer: refactor layerID to layerId Test: build, flash and boot Test: atest libsurfaceflinger_unittest Change-Id: I297dce08dbaf625b56e1e6d47cffead1de440ab7 --- services/surfaceflinger/BufferLayer.cpp | 18 ++-- services/surfaceflinger/BufferQueueLayer.cpp | 38 +++---- services/surfaceflinger/BufferStateLayer.cpp | 24 ++--- .../surfaceflinger/FrameTracer/FrameTracer.cpp | 54 +++++----- services/surfaceflinger/FrameTracer/FrameTracer.h | 14 +-- services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/TimeStats/TimeStats.cpp | 110 ++++++++++----------- services/surfaceflinger/TimeStats/TimeStats.h | 42 ++++---- .../tests/unittests/FrameTracerTest.cpp | 74 +++++++------- .../tests/unittests/TimeStatsTest.cpp | 14 +-- 10 files changed, 197 insertions(+), 197 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a25709ceee..31462569e2 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -77,9 +77,9 @@ BufferLayer::~BufferLayer() { // with the clone layer trying to use the deleted texture. mFlinger->deleteTextureAsync(mTextureName); } - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void BufferLayer::useSurfaceDamage() { @@ -305,8 +305,8 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime); std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { @@ -318,16 +318,16 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } if (presentFence->isValid()) { - mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence); + mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); - mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, actualPresentTime, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc61e498df..37096f8024 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -223,7 +223,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // BufferItem's that weren't actually queued. This can happen in shared // buffer mode. bool queuedBuffer = false; - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); @@ -264,7 +264,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } @@ -278,8 +278,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); mQueuedFrames = 0; - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } // Once we have hit this state, the shadow queue may no longer @@ -301,19 +301,19 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); - mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, + mFlinger->mTimeStats->setAcquireFence(layerId, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber, mQueueItems[0].mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); @@ -373,28 +373,28 @@ void BufferQueueLayer::latchPerFrameState( // ----------------------------------------------------------------------- void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DEQUEUE); } void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DETACH); } void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::CANCEL); } void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber, systemTime(), FrameTracer::FrameEvent::QUEUE); ATRACE_CALL(); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5768edd744..2f3906b348 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -240,10 +240,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setPostTime(layerId, mFrameNumber, getName().c_str(), postTime); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mFrameNumber, postTime, FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; @@ -461,7 +461,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return NO_ERROR; } - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); // Reject if the layer is invalid uint32_t bufferWidth = s.buffer->width; @@ -483,7 +483,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mFrameNumber); return BAD_VALUE; } @@ -500,18 +500,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // a GL-composited layer) not at all. status_t err = bindTextureImage(); if (err != NO_ERROR) { - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, + mFlinger->mTimeStats->setAcquireFence(layerId, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerId, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, mFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, mFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 3a0408edbd..6f918438bc 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -44,52 +44,52 @@ void FrameTracer::registerDataSource() { FrameTracerDataSource::Register(dsd); } -void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { - FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { +void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; + mTraceTracker[layerId].layerName = layerName; } }); } -void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type, duration](FrameTracerDataSource::TraceContext ctx) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); }); } -void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type, startTime](FrameTracerDataSource::TraceContext ctx) { const nsecs_t signalTime = fence->getSignalTime(); if (signalTime != Fence::SIGNAL_TIME_INVALID) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime); } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( + mTraceTracker[layerId].pendingFences[bufferID].push_back( {.frameNumber = frameNumber, .type = type, .fence = fence, @@ -100,9 +100,9 @@ void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameN } void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, - int32_t layerID, uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + int32_t layerId, uint64_t bufferID) { + if (mTraceTracker[layerId].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID]; for (size_t i = 0; i < pendingFences.size(); ++i) { auto& pendingFence = pendingFences[i]; @@ -116,7 +116,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& if (signalTime != Fence::SIGNAL_TIME_INVALID && systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type, pendingFence.startTime, signalTime); } @@ -126,7 +126,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& } } -void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { auto packet = ctx.NewTracePacket(); @@ -138,9 +138,9 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } event->set_type(type); - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; + if (mTraceTracker.find(layerId) != mTraceTracker.end() && + !mTraceTracker[layerId].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerId].layerName; event->set_layer_name(layerName.c_str(), layerName.size()); } @@ -149,7 +149,7 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } } -void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime) { @@ -159,12 +159,12 @@ void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int3 timestamp = startTime; duration = endTime - startTime; } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); } -void FrameTracer::onDestroy(int32_t layerID) { +void FrameTracer::onDestroy(int32_t layerId) { std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); + mTraceTracker.erase(layerId); } std::string FrameTracer::miniDump() { diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h index e91a7503cd..ef5df90fea 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.h +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -47,21 +47,21 @@ public: void registerDataSource(); // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or // traceFence() for each layer. - void traceNewLayer(int32_t layerID, const std::string& layerName); + void traceNewLayer(int32_t layerId, const std::string& layerName); // Creates a trace point at the timestamp provided. - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + void traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); // Creates a trace point after the provided fence has been signalled. If a startTime is provided // the trace will have be timestamped from startTime until fence signalling time. If no // startTime is provided, a durationless trace point will be created timestamped at fence // signalling time. If the fence hasn't signalled yet, the trace point will be created the next // time after signalling a trace call for this buffer occurs. - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + void traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime = 0); // Takes care of cleanup when a layer is destroyed. - void onDestroy(int32_t layerID); + void onDestroy(int32_t layerId); std::string miniDump(); @@ -88,15 +88,15 @@ private: // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates // trace points for them. - void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID); // Creates a trace point by translating a start time and an end time to a timestamp and // duration. If startTime is later than end time it sets end time as the timestamp and the // duration to 0. Used by traceFence(). - void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime); - void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d5a9ae1b3b..3757fc7c00 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1356,9 +1356,9 @@ void Layer::dumpCallingUidPid(std::string& result) const { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 3e47ec6856..611afce604 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -113,9 +113,9 @@ void TimeStats::incrementClientCompositionFrames() { mTimeStats.clientCompositionFrames++; } -bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { +bool TimeStats::recordReadyLocked(int32_t layerId, TimeRecord* timeRecord) { if (!timeRecord->ready) { - ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerId, timeRecord->frameTime.frameNumber); return false; } @@ -128,7 +128,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime(); timeRecord->acquireFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -141,7 +141,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime(); timeRecord->presentFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -155,15 +155,15 @@ static int32_t msBetween(nsecs_t start, nsecs_t end) { return static_cast(delta); } -void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { +void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId) { ATRACE_CALL(); - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque& timeRecords = layerRecord.timeRecords; while (!timeRecords.empty()) { - if (!recordReadyLocked(layerID, &timeRecords[0])) break; - ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID, + if (!recordReadyLocked(layerId, &timeRecords[0])) break; + ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerId, timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime); if (prevTimeRecord.ready) { @@ -178,37 +178,37 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.acquireTime); - ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToAcquireMs); timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs); const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToPresentMs); timeStatsLayer.deltas["post2present"].insert(postToPresentMs); const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, acquireToPresentMs); timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, latchToPresentMs); timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, desiredToPresentMs); timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, presentToPresentMs); timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); } @@ -227,28 +227,28 @@ static bool layerNameIsValid(const std::string& layerName) { layerName.compare(0, kMinLenLayerName, kPopupWindowPrefix) != 0; } -void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, +void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerId, frameNumber, layerName.c_str(), postTime); std::lock_guard lock(mMutex); if (!mTimeStats.stats.count(layerName) && mTimeStats.stats.size() >= MAX_NUM_LAYER_STATS) { return; } - if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && + if (!mTimeStatsTracker.count(layerId) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && layerNameIsValid(layerName)) { - mTimeStatsTracker[layerID].layerName = layerName; + mTimeStatsTracker[layerId].layerName = layerName; } - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { ALOGE("[%d]-[%s]-timeRecords is at its maximum size[%zu]. Ignore this when unittesting.", - layerID, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); - mTimeStatsTracker.erase(layerID); + layerId, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); + mTimeStatsTracker.erase(layerId); return; } // For most media content, the acquireFence is invalid because the buffer is @@ -270,15 +270,15 @@ void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::st layerRecord.waitData = layerRecord.timeRecords.size() - 1; } -void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) { +void TimeStats::setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerID, frameNumber, latchTime); + ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerId, frameNumber, latchTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -288,15 +288,15 @@ void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latc } } -void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) { +void TimeStats::setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerID, frameNumber, desiredTime); + ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerId, frameNumber, desiredTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -306,15 +306,15 @@ void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t de } } -void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) { +void TimeStats::setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerID, frameNumber, acquireTime); + ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerId, frameNumber, acquireTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -324,17 +324,17 @@ void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t ac } } -void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerId, frameNumber, acquireFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -344,15 +344,15 @@ void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, } } -void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) { +void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerID, frameNumber, presentTime); + ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerId, frameNumber, presentTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -363,20 +363,20 @@ void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t pr layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerId, frameNumber, presentFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -387,25 +387,25 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::onDestroy(int32_t layerID) { +void TimeStats::onDestroy(int32_t layerId) { ATRACE_CALL(); - ALOGV("[%d]-onDestroy", layerID); + ALOGV("[%d]-onDestroy", layerId); std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); + mTimeStatsTracker.erase(layerId); } -void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { +void TimeStats::removeTimeRecord(int32_t layerId, uint64_t frameNumber) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerID, frameNumber); + ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerId, frameNumber); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; size_t removeAt = 0; for (const TimeRecord& record : layerRecord.timeRecords) { if (record.frameTime.frameNumber == frameNumber) break; diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 1313132920..6e71f5a14e 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -44,20 +44,20 @@ public: virtual void incrementMissedFrames() = 0; virtual void incrementClientCompositionFrames() = 0; - virtual void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + virtual void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) = 0; - virtual void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) = 0; - virtual void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) = 0; - virtual void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) = 0; - virtual void setAcquireFence(int32_t layerID, uint64_t frameNumber, + virtual void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) = 0; + virtual void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) = 0; + virtual void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) = 0; + virtual void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) = 0; - virtual void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) = 0; - virtual void setPresentFence(int32_t layerID, uint64_t frameNumber, + virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) = 0; + virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) = 0; // Clean up the layer record - virtual void onDestroy(int32_t layerID) = 0; + virtual void onDestroy(int32_t layerId) = 0; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - virtual void removeTimeRecord(int32_t layerID, uint64_t frameNumber) = 0; + virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0; virtual void setPowerMode(int32_t powerMode) = 0; // Source of truth is RefrehRateStats. @@ -116,20 +116,20 @@ public: void incrementMissedFrames() override; void incrementClientCompositionFrames() override; - void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) override; - void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) override; - void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) override; - void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) override; - void setAcquireFence(int32_t layerID, uint64_t frameNumber, + void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) override; + void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) override; + void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override; + void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) override; - void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) override; - void setPresentFence(int32_t layerID, uint64_t frameNumber, + void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) override; + void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) override; // Clean up the layer record - void onDestroy(int32_t layerID) override; + void onDestroy(int32_t layerId) override; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - void removeTimeRecord(int32_t layerID, uint64_t frameNumber) override; + void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override; void setPowerMode(int32_t powerMode) override; // Source of truth is RefrehRateStats. @@ -139,8 +139,8 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); - void flushAvailableRecordsToStatsLocked(int32_t layerID); + bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(int32_t layerId); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); @@ -152,7 +152,7 @@ private: std::atomic mEnabled = false; std::mutex mMutex; TimeStatsHelper::TimeStatsGlobal mTimeStats; - // Hashmap for LayerRecord with layerID as the hash key + // Hashmap for LayerRecord with layerId as the hash key std::unordered_map mTimeStatsTracker; PowerTime mPowerTime; GlobalRecord mGlobalRecord; diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index b5af591e25..c334bcf85d 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -82,8 +82,8 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mFrameTracer->traceNewLayer(layerID, layerName); + const int32_t layerId = 5; + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); @@ -92,7 +92,7 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { tracingSession->StartBlocking(); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); tracingSession->StopBlocking(); @@ -103,31 +103,31 @@ TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; + const int32_t layerId = 5; + const int32_t secondlayerId = 6; auto tracingSession = getTracingSessionForTest(); tracingSession->StartBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceNewLayer(secondLayerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceNewLayer(secondlayerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); tracingSession->StopBlocking(); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(secondLayerID); + mFrameTracer->onDestroy(secondlayerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); } TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; + const int32_t layerId = 1; const uint32_t bufferID = 2; const uint64_t frameNumber = 3; const nsecs_t timestamp = 4; @@ -141,9 +141,9 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -157,10 +157,10 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -191,7 +191,7 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -204,10 +204,10 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); // Trace. - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); EXPECT_EQ(raw_trace.size(), 0); @@ -219,12 +219,12 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); const nsecs_t timestamp = systemTime(); fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -254,7 +254,7 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -264,24 +264,24 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 + 100000; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 + 100000; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -309,7 +309,7 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -321,11 +321,11 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence, type); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); // Create extra trace packet to trigger and finalize any previous fence packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -334,7 +334,7 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -345,24 +345,24 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 - duration; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 - duration; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 4eb9ec3672..7b60fa2ea6 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -170,8 +170,8 @@ std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { return result; } -static std::string genLayerName(int32_t layerID) { - return (layerID < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerID); +static std::string genLayerName(int32_t layerId) { + return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerId); } void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) { @@ -560,22 +560,22 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); for (size_t i = 0; i < 10000000; ++i) { - const int32_t layerID = genRandomInt32(-1, 10); + const int32_t layerId = genRandomInt32(-1, 10); const int32_t frameNumber = genRandomInt32(1, 10); switch (genRandomInt32(0, 100)) { case 0: ALOGV("removeTimeRecord"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber)); continue; case 1: ALOGV("onDestroy"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId)); continue; } TimeStamp type = static_cast(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END)); const int32_t ts = genRandomInt32(1, 1000000000); - ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts); - setTimeStamp(type, layerID, frameNumber, ts); + ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts); + setTimeStamp(type, layerId, frameNumber, ts); } } -- cgit v1.2.3-59-g8ed1b From b69e076883fb1f11466dabddc7053b213fde84b5 Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Mon, 11 Nov 2019 18:39:53 -0800 Subject: Add trace event for fallback composition When the HWC rejects composition of any layer, it is returned to surfaceflinger and queued to the GPU for doing client composition. This event is important to track as it can show why the GPU is busy at that time. Test: Set fallback composition in the middle of a GAPID trace from the commandline Bug: 140236090 Change-Id: Id1cb71f301023743dc9fa6a1396f8a525b5de7bd --- services/surfaceflinger/BufferLayer.cpp | 11 ++++++++++- services/surfaceflinger/BufferLayer.h | 2 +- .../compositionengine/impl/OutputLayerCompositionState.h | 3 +++ services/surfaceflinger/CompositionEngine/src/Output.cpp | 1 + .../surfaceflinger/CompositionEngine/tests/OutputTest.cpp | 5 +++++ services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 5 ++--- 7 files changed, 23 insertions(+), 6 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 31462569e2..94c4a81df2 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -286,7 +286,7 @@ bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { return hasReadyFrame(); } -bool BufferLayer::onPostComposition(const std::optional& displayId, +bool BufferLayer::onPostComposition(sp displayDevice, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) { @@ -308,6 +308,14 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, const int32_t layerId = getSequence(); mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime); + const auto outputLayer = findOutputLayerForDisplay(displayDevice); + if (outputLayer && outputLayer->requiresClientComposition()) { + nsecs_t clientCompositionTimestamp = outputLayer->getState().clientCompositionTimestamp; + mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, + clientCompositionTimestamp, + FrameTracer::FrameEvent::FALLBACK_COMPOSITION); + } + std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); @@ -317,6 +325,7 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, mFrameTracker.setFrameReadyTime(desiredPresentTime); } + const auto displayId = displayDevice->getId(); if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence); mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 656ba12a19..16855d20e3 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -78,7 +78,7 @@ public: bool isHdrY410() const override; - bool onPostComposition(const std::optional& displayId, + bool onPostComposition(sp displayDevice, const std::shared_ptr& glDoneFence, const std::shared_ptr& presentFence, const CompositorTiming& compositorTiming) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 13474492af..11cfccc504 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -98,6 +98,9 @@ struct OutputLayerCompositionState { // Debugging void dump(std::string& result) const; + + // Timestamp for when the layer is queued for client composition + nsecs_t clientCompositionTimestamp; }; } // namespace compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 195300580e..6877f8bba0 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -904,6 +904,7 @@ std::vector Output::generateClientCompositionReques layerSettings.disableBlending = true; } + layer->editState().clientCompositionTimestamp = systemTime(); clientCompositionLayers.push_back(*result); } } diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 7fce520000..bac7c75c63 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -805,6 +805,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings)); + EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState)); EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer)); @@ -813,6 +814,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); + EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u)); EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)) @@ -865,6 +867,7 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit EXPECT_CALL(outputLayer, needsFiltering()).WillRepeatedly(Return(false)); EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0); + EXPECT_CALL(outputLayer, editState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u)); EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)).WillRepeatedly(Return(&outputLayer)); @@ -930,6 +933,7 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { EXPECT_CALL(leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); + EXPECT_CALL(leftOutputLayer, editState()).WillRepeatedly(ReturnRef(leftOutputLayerState)); EXPECT_CALL(rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer)); @@ -938,6 +942,7 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { EXPECT_CALL(rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); + EXPECT_CALL(rightOutputLayer, editState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(2u)); EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u)) diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3bd9545af2..286311b03f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -531,7 +531,7 @@ public: * called after composition. * returns true if the layer latched a new buffer this frame. */ - virtual bool onPostComposition(const std::optional& /*displayId*/, + virtual bool onPostComposition(sp /*displayDevice*/, const std::shared_ptr& /*glDoneFence*/, const std::shared_ptr& /*presentFence*/, const CompositorTiming& /*compositorTiming*/) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e0e57116cc..b4d748d50e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1901,9 +1901,8 @@ void SurfaceFlinger::postComposition() } mDrawingState.traverseInZOrder([&](Layer* layer) { - bool frameLatched = - layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime, - presentFenceTime, compositorTiming); + bool frameLatched = layer->onPostComposition(displayDevice, glCompositionDoneFenceTime, + presentFenceTime, compositorTiming); if (frameLatched) { recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); } -- cgit v1.2.3-59-g8ed1b From 1a70eca966bd52868d5599c5100c380d88f86b6d Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Fri, 15 Nov 2019 09:33:33 -0800 Subject: Use max mastering luminance and max content luminance from HdrMetadata. Previously we hard coded 1000.0 nits as the max mastering luminance and max content luminance. However, this causes bad experience especially when the max content luminance is lower than 1000.0 nits. BUG: b/141647818 Test: manual Change-Id: I630469a4e3e95b2ca8c776dc1284208397b385ad --- libs/renderengine/gl/GLESRenderEngine.cpp | 3 ++- libs/renderengine/gl/Program.cpp | 8 ++++++++ libs/renderengine/gl/Program.h | 4 ++++ libs/renderengine/gl/ProgramCache.cpp | 9 +++++---- libs/renderengine/include/renderengine/LayerSettings.h | 2 ++ libs/renderengine/include/renderengine/private/Description.h | 2 ++ services/surfaceflinger/BufferLayer.cpp | 11 +++++++++++ 7 files changed, 34 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 15d025b6f7..394d05a876 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -983,6 +983,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, Mesh mesh(Mesh::TRIANGLE_FAN, 4, 2, 2); for (auto layer : layers) { + mState.maxMasteringLuminance = layer.source.buffer.maxMasteringLuminance; + mState.maxContentLuminance = layer.source.buffer.maxContentLuminance; mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; const FloatRect bounds = layer.geometry.boundaries; @@ -998,7 +1000,6 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, bool usePremultipliedAlpha = true; bool disableTexture = true; bool isOpaque = false; - if (layer.source.buffer.buffer != nullptr) { disableTexture = false; isOpaque = layer.source.buffer.isOpaque; diff --git a/libs/renderengine/gl/Program.cpp b/libs/renderengine/gl/Program.cpp index fe9d909923..4eb5eb6a25 100644 --- a/libs/renderengine/gl/Program.cpp +++ b/libs/renderengine/gl/Program.cpp @@ -65,6 +65,8 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c mSamplerLoc = glGetUniformLocation(programId, "sampler"); mColorLoc = glGetUniformLocation(programId, "color"); mDisplayMaxLuminanceLoc = glGetUniformLocation(programId, "displayMaxLuminance"); + mMaxMasteringLuminanceLoc = glGetUniformLocation(programId, "maxMasteringLuminance"); + mMaxContentLuminanceLoc = glGetUniformLocation(programId, "maxContentLuminance"); mInputTransformMatrixLoc = glGetUniformLocation(programId, "inputTransformMatrix"); mOutputTransformMatrixLoc = glGetUniformLocation(programId, "outputTransformMatrix"); mCornerRadiusLoc = glGetUniformLocation(programId, "cornerRadius"); @@ -138,6 +140,12 @@ void Program::setUniforms(const Description& desc) { if (mDisplayMaxLuminanceLoc >= 0) { glUniform1f(mDisplayMaxLuminanceLoc, desc.displayMaxLuminance); } + if (mMaxMasteringLuminanceLoc >= 0) { + glUniform1f(mMaxMasteringLuminanceLoc, desc.maxMasteringLuminance); + } + if (mMaxContentLuminanceLoc >= 0) { + glUniform1f(mMaxContentLuminanceLoc, desc.maxContentLuminance); + } if (mCornerRadiusLoc >= 0) { glUniform1f(mCornerRadiusLoc, desc.cornerRadius); } diff --git a/libs/renderengine/gl/Program.h b/libs/renderengine/gl/Program.h index bc9cf08b8b..c9beb6844f 100644 --- a/libs/renderengine/gl/Program.h +++ b/libs/renderengine/gl/Program.h @@ -90,6 +90,10 @@ private: /* location of display luminance uniform */ GLint mDisplayMaxLuminanceLoc; + /* location of max mastering luminance uniform */ + GLint mMaxMasteringLuminanceLoc; + /* location of max content luminance uniform */ + GLint mMaxContentLuminanceLoc; /* location of transform matrix */ GLint mInputTransformMatrixLoc; diff --git a/libs/renderengine/gl/ProgramCache.cpp b/libs/renderengine/gl/ProgramCache.cpp index 494623e67e..e2757e181b 100644 --- a/libs/renderengine/gl/ProgramCache.cpp +++ b/libs/renderengine/gl/ProgramCache.cpp @@ -339,9 +339,9 @@ void ProgramCache::generateToneMappingProcess(Formatter& fs, const Key& needs) { default: fs << R"__SHADER__( highp vec3 ToneMap(highp vec3 color) { - const float maxMasteringLumi = 1000.0; - const float maxContentLumi = 1000.0; - const float maxInLumi = min(maxMasteringLumi, maxContentLumi); + float maxMasteringLumi = maxMasteringLuminance; + float maxContentLumi = maxContentLuminance; + float maxInLumi = min(maxMasteringLumi, maxContentLumi); float maxOutLumi = displayMaxLuminance; float nits = color.y; @@ -633,9 +633,10 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) { } if (needs.hasTransformMatrix() || (needs.getInputTF() != needs.getOutputTF())) { - // Currently, display maximum luminance is needed when doing tone mapping. if (needs.needsToneMapping()) { fs << "uniform float displayMaxLuminance;"; + fs << "uniform float maxMasteringLuminance;"; + fs << "uniform float maxContentLuminance;"; } if (needs.hasInputTransformMatrix()) { diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index b8bf8019de..f76966bf12 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -60,6 +60,8 @@ struct Buffer { // HDR color-space setting for Y410. bool isY410BT2020 = false; + float maxMasteringLuminance = 0.0; + float maxContentLuminance = 0.0; }; // Metadata describing the layer geometry. diff --git a/libs/renderengine/include/renderengine/private/Description.h b/libs/renderengine/include/renderengine/private/Description.h index bd2055f4e5..bad64c2f13 100644 --- a/libs/renderengine/include/renderengine/private/Description.h +++ b/libs/renderengine/include/renderengine/private/Description.h @@ -71,6 +71,8 @@ struct Description { TransferFunction outputTransferFunction = TransferFunction::LINEAR; float displayMaxLuminance; + float maxMasteringLuminance; + float maxContentLuminance; // projection matrix mat4 projectionMatrix; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 94c4a81df2..054acc5069 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -56,6 +56,9 @@ namespace android { +static constexpr float defaultMaxMasteringLuminance = 1000.0; +static constexpr float defaultMaxContentLuminance = 1000.0; + BufferLayer::BufferLayer(const LayerCreationArgs& args) : Layer(args), mTextureName(args.textureName), @@ -184,6 +187,14 @@ std::optional BufferLayer::prepareClientComposition layer.source.buffer.textureName = mTextureName; layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); + bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086; + bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3; + layer.source.buffer.maxMasteringLuminance = hasSmpte2086 + ? mBufferInfo.mHdrMetadata.smpte2086.maxLuminance + : defaultMaxMasteringLuminance; + layer.source.buffer.maxContentLuminance = hasCta861_3 + ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel + : defaultMaxContentLuminance; // TODO: we could be more subtle with isFixedSize() const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || isFixedSize(); -- cgit v1.2.3-59-g8ed1b From af87b3e09141558215e28f84d954590b5e7f2f16 Mon Sep 17 00:00:00 2001 From: chaviw Date: Tue, 1 Oct 2019 16:59:28 -0700 Subject: Added input support for cloned layers This was done with a few changes: 1. Added a layerId in the input info so the InputInfo objects can be uniquely identified as per layer 2. When setting input info in InputDispatcher, compare InputInfo objects using layer id instead of input token. 3. Updated the crop region for layers based on the cloned hierarchy so the input is cropped to the correct region. Bug: 140756730 Test: InputDispatcherMultiWindowSameTokenTests Change-Id: I980f5d29d091fecb407f5cd6a289615505800927 --- include/input/InputWindow.h | 6 + libs/input/InputWindow.cpp | 2 + libs/input/tests/InputWindow_test.cpp | 2 + .../inputflinger/dispatcher/InputDispatcher.cpp | 22 ++- .../inputflinger/tests/InputDispatcher_test.cpp | 149 +++++++++++++++++++++ services/surfaceflinger/BufferLayer.cpp | 15 ++- services/surfaceflinger/Layer.cpp | 63 ++++++--- services/surfaceflinger/Layer.h | 7 +- 8 files changed, 239 insertions(+), 27 deletions(-) (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index f852cd0540..cbd64d520e 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -119,7 +119,11 @@ struct InputWindowInfo { /* These values are filled in by the WM and passed through SurfaceFlinger * unless specified otherwise. */ + // This value should NOT be used to uniquely identify the window. There may be different + // input windows that have the same token. sp token; + // This uniquely identifies the input window. + int32_t id = 0; std::string name; int32_t layoutParamsFlags; int32_t layoutParamsType; @@ -203,6 +207,8 @@ public: sp getToken() const; + int32_t getId() const { return mInfo.id; } + sp getApplicationToken() { return mInfo.applicationInfo.token; } diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp index ec28757933..74a05055eb 100644 --- a/libs/input/InputWindow.cpp +++ b/libs/input/InputWindow.cpp @@ -73,6 +73,7 @@ status_t InputWindowInfo::write(Parcel& output) const { status_t s = output.writeStrongBinder(token); if (s != OK) return s; + output.writeInt32(id); output.writeString8(String8(name.c_str())); output.writeInt32(layoutParamsFlags); output.writeInt32(layoutParamsType); @@ -116,6 +117,7 @@ InputWindowInfo InputWindowInfo::read(const Parcel& from) { } ret.token = token; + ret.id = from.readInt32(); ret.name = from.readString8().c_str(); ret.layoutParamsFlags = from.readInt32(); ret.layoutParamsType = from.readInt32(); diff --git a/libs/input/tests/InputWindow_test.cpp b/libs/input/tests/InputWindow_test.cpp index 6db18abacf..cdc81d2f04 100644 --- a/libs/input/tests/InputWindow_test.cpp +++ b/libs/input/tests/InputWindow_test.cpp @@ -40,6 +40,7 @@ TEST(InputWindowInfo, Parcelling) { sp touchableRegionCropHandle = new BBinder(); InputWindowInfo i; i.token = new BBinder(); + i.id = 1; i.name = "Foobar"; i.layoutParamsFlags = 7; i.layoutParamsType = 39; @@ -72,6 +73,7 @@ TEST(InputWindowInfo, Parcelling) { p.setDataPosition(0); InputWindowInfo i2 = InputWindowInfo::read(p); ASSERT_EQ(i.token, i2.token); + ASSERT_EQ(i.id, i2.id); ASSERT_EQ(i.name, i2.name); ASSERT_EQ(i.layoutParamsFlags, i2.layoutParamsFlags); ASSERT_EQ(i.layoutParamsType, i2.layoutParamsType); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 5a49b5e16a..116625c03e 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -240,6 +240,18 @@ static bool removeByValue(std::unordered_map& map, const V& value) { return removed; } +static bool haveSameToken(const sp& first, const sp& second) { + if (first == second) { + return true; + } + + if (first == nullptr || second == nullptr) { + return false; + } + + return first->getToken() == second->getToken(); +} + // --- InputDispatcherThread --- class InputDispatcher::InputDispatcherThread : public Thread { @@ -3278,9 +3290,9 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( // Since we compare the pointer of input window handles across window updates, we need // to make sure the handle object for the same window stays unchanged across updates. const std::vector>& oldHandles = getWindowHandlesLocked(displayId); - std::unordered_map, sp, IBinderHash> oldHandlesByTokens; + std::unordered_map> oldHandlesById; for (const sp& handle : oldHandles) { - oldHandlesByTokens[handle->getToken()] = handle; + oldHandlesById[handle->getId()] = handle; } std::vector> newHandles; @@ -3311,8 +3323,8 @@ void InputDispatcher::updateWindowHandlesForDisplayLocked( continue; } - if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) { - const sp oldHandle = oldHandlesByTokens.at(handle->getToken()); + if (oldHandlesById.find(handle->getId()) != oldHandlesById.end()) { + const sp& oldHandle = oldHandlesById.at(handle->getId()); oldHandle->updateFrom(handle); newHandles.push_back(oldHandle); } else { @@ -3370,7 +3382,7 @@ void InputDispatcher::setInputWindows(const std::vector>& sp oldFocusedWindowHandle = getValueByKey(mFocusedWindowHandlesByDisplay, displayId); - if (oldFocusedWindowHandle != newFocusedWindowHandle) { + if (!haveSameToken(oldFocusedWindowHandle, newFocusedWindowHandle)) { if (oldFocusedWindowHandle != nullptr) { if (DEBUG_FOCUS) { ALOGD("Focus left window: %s in display %" PRId32, diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index b4d7608770..c25122c72b 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -526,6 +526,7 @@ public: mInfo.applicationInfo = *inputApplicationHandle->getInfo(); mInfo.token = token; + mInfo.id = 0; mInfo.name = name; mInfo.layoutParamsFlags = 0; mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION; @@ -564,6 +565,13 @@ public: void setLayoutParamFlags(int32_t flags) { mInfo.layoutParamsFlags = flags; } + void setId(int32_t id) { mInfo.id = id; } + + void setWindowScale(float xScale, float yScale) { + mInfo.windowXScale = xScale; + mInfo.windowYScale = yScale; + } + void consumeKeyDown(int32_t expectedDisplayId, int32_t expectedFlags = 0) { consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_DOWN, expectedDisplayId, expectedFlags); @@ -586,12 +594,21 @@ public: expectedFlags); } + InputEvent* consume() { + if (mInputReceiver == nullptr) { + return nullptr; + } + return mInputReceiver->consume(); + } + void assertNoEvents() { ASSERT_NE(mInputReceiver, nullptr) << "Call 'assertNoEvents' on a window with an InputReceiver"; mInputReceiver->assertNoEvents(); } + sp getToken() { return mInfo.token; } + private: std::unique_ptr mInputReceiver; }; @@ -667,6 +684,10 @@ static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLA static NotifyMotionArgs generateMotionArgs(int32_t action, int32_t source, int32_t displayId, const std::vector& points) { size_t pointerCount = points.size(); + if (action == AMOTION_EVENT_ACTION_DOWN || action == AMOTION_EVENT_ACTION_UP) { + EXPECT_EQ(1U, pointerCount) << "Actions DOWN and UP can only contain a single pointer"; + } + PointerProperties pointerProperties[pointerCount]; PointerCoords pointerCoords[pointerCount]; @@ -1291,4 +1312,132 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, mFakePolicy->assertOnPointerDownWasNotCalled(); } +// These tests ensures we can send touch events to a single client when there are multiple input +// windows that point to the same client token. +class InputDispatcherMultiWindowSameTokenTests : public InputDispatcherTest { + virtual void SetUp() override { + InputDispatcherTest::SetUp(); + + sp application = new FakeApplicationHandle(); + mWindow1 = new FakeWindowHandle(application, mDispatcher, "Fake Window 1", + ADISPLAY_ID_DEFAULT); + // Adding FLAG_NOT_TOUCH_MODAL otherwise all taps will go to the top most window. + // We also need FLAG_SPLIT_TOUCH or we won't be able to get touches for both windows. + mWindow1->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | + InputWindowInfo::FLAG_SPLIT_TOUCH); + mWindow1->setId(0); + mWindow1->setFrame(Rect(0, 0, 100, 100)); + + mWindow2 = new FakeWindowHandle(application, mDispatcher, "Fake Window 2", + ADISPLAY_ID_DEFAULT, mWindow1->getToken()); + mWindow2->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL | + InputWindowInfo::FLAG_SPLIT_TOUCH); + mWindow2->setId(1); + mWindow2->setFrame(Rect(100, 100, 200, 200)); + + mDispatcher->setInputWindows({mWindow1, mWindow2}, ADISPLAY_ID_DEFAULT); + } + +protected: + sp mWindow1; + sp mWindow2; + + // Helper function to convert the point from screen coordinates into the window's space + static PointF getPointInWindow(const InputWindowInfo* windowInfo, const PointF& point) { + float x = windowInfo->windowXScale * (point.x - windowInfo->frameLeft); + float y = windowInfo->windowYScale * (point.y - windowInfo->frameTop); + return {x, y}; + } + + void consumeMotionEvent(const sp& window, int32_t expectedAction, + const std::vector& points) { + std::string name = window->mName; + InputEvent* event = window->consume(); + + ASSERT_NE(nullptr, event) << name.c_str() + << ": consumer should have returned non-NULL event."; + + ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType()) + << name.c_str() << "expected " << inputEventTypeToString(AINPUT_EVENT_TYPE_MOTION) + << " event, got " << inputEventTypeToString(event->getType()) << " event"; + + const MotionEvent& motionEvent = static_cast(*event); + EXPECT_EQ(expectedAction, motionEvent.getAction()); + + for (size_t i = 0; i < points.size(); i++) { + float expectedX = points[i].x; + float expectedY = points[i].y; + + EXPECT_EQ(expectedX, motionEvent.getX(i)) + << "expected " << expectedX << " for x[" << i << "] coord of " << name.c_str() + << ", got " << motionEvent.getX(i); + EXPECT_EQ(expectedY, motionEvent.getY(i)) + << "expected " << expectedY << " for y[" << i << "] coord of " << name.c_str() + << ", got " << motionEvent.getY(i); + } + } +}; + +TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchSameScale) { + // Touch Window 1 + PointF touchedPoint = {10, 10}; + PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint); + + NotifyMotionArgs motionArgs = + generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); + + // Release touch on Window 1 + motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + // consume the UP event + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint}); + + // Touch Window 2 + touchedPoint = {150, 150}; + expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint); + + motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + + // Consuming from window1 since it's the window that has the InputReceiver + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); +} + +TEST_F(InputDispatcherMultiWindowSameTokenTests, SingleTouchDifferentScale) { + mWindow2->setWindowScale(0.5f, 0.5f); + + // Touch Window 1 + PointF touchedPoint = {10, 10}; + PointF expectedPoint = getPointInWindow(mWindow1->getInfo(), touchedPoint); + + NotifyMotionArgs motionArgs = + generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); + + // Release touch on Window 1 + motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + // consume the UP event + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_UP, {expectedPoint}); + + // Touch Window 2 + touchedPoint = {150, 150}; + expectedPoint = getPointInWindow(mWindow2->getInfo(), touchedPoint); + + motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, + ADISPLAY_ID_DEFAULT, {touchedPoint}); + mDispatcher->notifyMotion(&motionArgs); + + // Consuming from window1 since it's the window that has the InputReceiver + consumeMotionEvent(mWindow1, AMOTION_EVENT_ACTION_DOWN, {expectedPoint}); +} + } // namespace android::inputdispatcher diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 054acc5069..bdecdb78d0 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -770,17 +770,20 @@ void BufferLayer::updateCloneBufferInfo() { // After buffer info is updated, the drawingState from the real layer needs to be copied into // the cloned. This is because some properties of drawingState can change when latchBuffer is - // called. However, copying the drawingState would also overwrite the cloned layer's relatives. - // Therefore, temporarily store the relatives so they can be set in the cloned drawingState - // again. + // called. However, copying the drawingState would also overwrite the cloned layer's relatives + // and touchableRegionCrop. Therefore, temporarily store the relatives so they can be set in + // the cloned drawingState again. wp tmpZOrderRelativeOf = mDrawingState.zOrderRelativeOf; SortedVector> tmpZOrderRelatives = mDrawingState.zOrderRelatives; + wp tmpTouchableRegionCrop = mDrawingState.touchableRegionCrop; + InputWindowInfo tmpInputInfo = mDrawingState.inputInfo; + mDrawingState = clonedFrom->mDrawingState; - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; + + mDrawingState.touchableRegionCrop = tmpTouchableRegionCrop; mDrawingState.zOrderRelativeOf = tmpZOrderRelativeOf; mDrawingState.zOrderRelatives = tmpZOrderRelatives; + mDrawingState.inputInfo = tmpInputInfo; } } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 35fc4be056..e7572f0054 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2025,6 +2025,7 @@ bool Layer::isRemovedFromCurrentState() const { InputWindowInfo Layer::fillInputInfo() { InputWindowInfo info = mDrawingState.inputInfo; + info.id = sequence; if (info.displayId == ADISPLAY_ID_NONE) { info.displayId = getLayerStack(); @@ -2081,9 +2082,29 @@ InputWindowInfo Layer::fillInputInfo() { info.touchableRegion = info.touchableRegion.intersect(Rect{cropLayer->mScreenBounds}); } + // If the layer is a clone, we need to crop the input region to cloned root to prevent + // touches from going outside the cloned area. + if (isClone()) { + sp clonedRoot = getClonedRoot(); + if (clonedRoot != nullptr) { + Rect rect(clonedRoot->mScreenBounds); + info.touchableRegion = info.touchableRegion.intersect(rect); + } + } + return info; } +sp Layer::getClonedRoot() { + if (mClonedChild != nullptr) { + return this; + } + if (mDrawingParent == nullptr || mDrawingParent.promote() == nullptr) { + return nullptr; + } + return mDrawingParent.promote()->getClonedRoot(); +} + bool Layer::hasInput() const { return mDrawingState.inputInfo.token != nullptr; } @@ -2119,10 +2140,6 @@ void Layer::setInitialValuesForClone(const sp& clonedFrom) { // copy drawing state from cloned layer mDrawingState = clonedFrom->mDrawingState; mClonedFrom = clonedFrom; - - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; } void Layer::updateMirrorInfo() { @@ -2157,9 +2174,6 @@ void Layer::updateClonedDrawingState(std::map, sp>& clonedLayer if (isClonedFromAlive()) { sp clonedFrom = getClonedFrom(); mDrawingState = clonedFrom->mDrawingState; - // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple - // InputWindows per client token yet. - mDrawingState.inputInfo.token = nullptr; clonedLayersMap.emplace(clonedFrom, this); } @@ -2198,7 +2212,24 @@ void Layer::updateClonedChildren(const sp& mirrorRoot, } } -void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap) { +void Layer::updateClonedInputInfo(const std::map, sp>& clonedLayersMap) { + auto cropLayer = mDrawingState.touchableRegionCrop.promote(); + if (cropLayer != nullptr) { + if (clonedLayersMap.count(cropLayer) == 0) { + // Real layer had a crop layer but it's not in the cloned hierarchy. Just set to + // self as crop layer to avoid going outside bounds. + mDrawingState.touchableRegionCrop = this; + } else { + const sp& clonedCropLayer = clonedLayersMap.at(cropLayer); + mDrawingState.touchableRegionCrop = clonedCropLayer; + } + } + // Cloned layers shouldn't handle watch outside since their z order is not determined by + // WM or the client. + mDrawingState.inputInfo.layoutParamsFlags &= ~InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH; +} + +void Layer::updateClonedRelatives(const std::map, sp>& clonedLayersMap) { mDrawingState.zOrderRelativeOf = nullptr; mDrawingState.zOrderRelatives.clear(); @@ -2206,11 +2237,11 @@ void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap return; } - sp clonedFrom = getClonedFrom(); + const sp& clonedFrom = getClonedFrom(); for (wp& relativeWeak : clonedFrom->mDrawingState.zOrderRelatives) { - sp relative = relativeWeak.promote(); - auto clonedRelative = clonedLayersMap[relative]; - if (clonedRelative != nullptr) { + const sp& relative = relativeWeak.promote(); + if (clonedLayersMap.count(relative) > 0) { + auto& clonedRelative = clonedLayersMap.at(relative); mDrawingState.zOrderRelatives.add(clonedRelative); } } @@ -2220,12 +2251,14 @@ void Layer::updateClonedRelatives(std::map, sp> clonedLayersMap // In that case, we treat the layer as if the relativeOf has been removed. This way, it will // still traverse the children, but the layer with the missing relativeOf will not be shown // on screen. - sp relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); - sp clonedRelativeOf = clonedLayersMap[relativeOf]; - if (clonedRelativeOf != nullptr) { + const sp& relativeOf = clonedFrom->mDrawingState.zOrderRelativeOf.promote(); + if (clonedLayersMap.count(relativeOf) > 0) { + const sp& clonedRelativeOf = clonedLayersMap.at(relativeOf); mDrawingState.zOrderRelativeOf = clonedRelativeOf; } + updateClonedInputInfo(clonedLayersMap); + for (sp& child : mDrawingChildren) { child->updateClonedRelatives(clonedLayersMap); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 843d3ae88e..d697a6a182 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -497,8 +497,9 @@ protected: void updateClonedDrawingState(std::map, sp>& clonedLayersMap); void updateClonedChildren(const sp& mirrorRoot, std::map, sp>& clonedLayersMap); - void updateClonedRelatives(std::map, sp> clonedLayersMap); + void updateClonedRelatives(const std::map, sp>& clonedLayersMap); void addChildToDrawing(const sp& layer); + void updateClonedInputInfo(const std::map, sp>& clonedLayersMap); public: /* @@ -972,6 +973,10 @@ private: // Returns true if the layer can draw shadows on its border. virtual bool canDrawShadows() const { return true; } + + // Find the root of the cloned hierarchy, this means the first non cloned parent. + // This will return null if first non cloned parent is not found. + sp getClonedRoot(); }; } // namespace android -- cgit v1.2.3-59-g8ed1b From 718f9601c611f657fd872f84f27d5cc9aec533b4 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 9 Nov 2019 20:01:35 -0800 Subject: ui: Deduplicate rotation types Introduce ui::Rotation, replacing ISurfaceComposer::Rotation as well as DISPLAY_ORIENTATION_* and DisplayState::eOrientation* constants. libinput has widespread use of int32_t for orientation, so move DISPLAY_ORIENTATION_* to input/DisplayViewport.h for now. Bug: 144601064 Test: go/wm-smoke Test: screencap Change-Id: Ic4b8494e37c9d79c00d5b4be5eb88585f09efebf --- cmds/surfacereplayer/replayer/Replayer.cpp | 2 +- include/input/DisplayViewport.h | 13 +- include/input/TouchVideoFrame.h | 1 - libs/gui/ISurfaceComposer.cpp | 9 +- libs/gui/LayerState.cpp | 5 +- libs/gui/SurfaceComposerClient.cpp | 39 +++-- libs/gui/include/gui/ISurfaceComposer.h | 22 +-- libs/gui/include/gui/LayerState.h | 12 +- libs/gui/include/gui/SurfaceComposerClient.h | 33 ++-- libs/gui/tests/BLASTBufferQueue_test.cpp | 10 +- libs/gui/tests/Surface_test.cpp | 9 +- libs/input/TouchVideoFrame.cpp | 1 + libs/input/tests/TouchVideoFrame_test.cpp | 1 + libs/ui/include/ui/DisplayInfo.h | 11 +- libs/ui/include/ui/Rotation.h | 57 +++++++ libs/ui/include/ui/Transform.h | 39 +++-- libs/ui/include_vndk/ui/Rotation.h | 1 + opengl/tests/lib/WindowSurface.cpp | 3 +- services/surfaceflinger/BufferLayer.cpp | 6 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/DisplayDevice.cpp | 75 +++------ services/surfaceflinger/DisplayDevice.h | 169 +++++++++------------ services/surfaceflinger/LayerRejecter.cpp | 2 +- services/surfaceflinger/RegionSamplingThread.cpp | 14 +- services/surfaceflinger/RenderArea.h | 16 +- services/surfaceflinger/SurfaceFlinger.cpp | 101 ++++++------ services/surfaceflinger/SurfaceFlinger.h | 10 +- services/surfaceflinger/SurfaceInterceptor.cpp | 8 +- services/surfaceflinger/tests/Credentials_test.cpp | 3 +- .../tests/LayerRenderTypeTransaction_test.cpp | 4 +- .../surfaceflinger/tests/LayerTransaction_test.cpp | 2 +- .../tests/unittests/DisplayTransactionTest.cpp | 12 +- .../tests/unittests/TestableSurfaceFlinger.h | 1 - 33 files changed, 329 insertions(+), 364 deletions(-) create mode 100644 libs/ui/include/ui/Rotation.h create mode 120000 libs/ui/include_vndk/ui/Rotation.h (limited to 'services/surfaceflinger/BufferLayer.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 0d6c31ee2f..675aad6f81 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -606,7 +606,7 @@ void Replayer::setDisplayProjection(SurfaceComposerClient::Transaction& t, pc.viewport().bottom()); Rect frame = Rect(pc.frame().left(), pc.frame().top(), pc.frame().right(), pc.frame().bottom()); - t.setDisplayProjection(mDisplays[id], pc.orientation(), viewport, frame); + t.setDisplayProjection(mDisplays[id], ui::toRotation(pc.orientation()), viewport, frame); } status_t Replayer::createSurfaceControl( diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index fa456bb213..610062697c 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -17,16 +17,23 @@ #ifndef _LIBINPUT_DISPLAY_VIEWPORT_H #define _LIBINPUT_DISPLAY_VIEWPORT_H +#include +#include + #include -#include #include