diff options
author | 2022-07-26 00:01:48 +0000 | |
---|---|---|
committer | 2022-07-27 22:34:58 +0000 | |
commit | 397a0e373f8e1d60586c93efbdbdcc309034cce8 (patch) | |
tree | d454b10f28f265006242dd4f686627f50a40b8cd | |
parent | a7dfc93a0f15637a95e999dd1f208626a14fdd61 (diff) |
SF: BufferStateLayer cleanup
Clean up some of the logic now that
BufferLayer has been merged into BufferStateLayer.
Test: presubmit
Bug: 238781169
Change-Id: I5114dd8d457638f810fe02d29bfab3444e042d2d
-rw-r--r-- | services/surfaceflinger/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.cpp | 340 | ||||
-rw-r--r-- | services/surfaceflinger/BufferStateLayer.h | 69 | ||||
-rw-r--r-- | services/surfaceflinger/HwcSlotGenerator.cpp | 104 | ||||
-rw-r--r-- | services/surfaceflinger/HwcSlotGenerator.h | 58 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 13 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 11 | ||||
-rw-r--r-- | services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/CachingTest.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/CompositionTest.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp | 3 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp | 21 |
13 files changed, 281 insertions, 349 deletions
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index f1457bfffe..a8ba15f36d 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -163,6 +163,7 @@ filegroup { "FrameTracer/FrameTracer.cpp", "FrameTracker.cpp", "HdrLayerInfoReporter.cpp", + "HwcSlotGenerator.cpp", "WindowInfosListenerInvoker.cpp", "Layer.cpp", "LayerProtoHelper.cpp", diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 59e2d18d88..5656e05605 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -25,7 +25,6 @@ #include <FrameTimeline/FrameTimeline.h> #include <compositionengine/CompositionEngine.h> -#include <compositionengine/LayerFECompositionState.h> #include <gui/BufferQueue.h> #include <private/gui/SyncFeatures.h> #include <renderengine/Image.h> @@ -71,22 +70,64 @@ namespace android { using PresentState = frametimeline::SurfaceFrame::PresentState; using gui::WindowInfo; -void BufferStateLayer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener, - const sp<GraphicBuffer>& buffer, - uint64_t framenumber, - const sp<Fence>& releaseFence, - uint32_t currentMaxAcquiredBufferCount) { - if (!listener) { - return; +namespace { +static constexpr float defaultMaxLuminance = 1000.0; + +constexpr mat4 inverseOrientation(uint32_t transform) { + const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1); + const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1); + const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1); + mat4 tr; + + if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + tr = tr * rot90; } - ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber); - listener->onReleaseBuffer({buffer->getId(), framenumber}, - releaseFence ? releaseFence : Fence::NO_FENCE, - currentMaxAcquiredBufferCount); + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { + tr = tr * flipH; + } + if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { + tr = tr * flipV; + } + return inverse(tr); } -namespace { -static constexpr float defaultMaxLuminance = 1000.0; +bool assignTransform(ui::Transform* dst, ui::Transform& from) { + if (*dst == from) { + return false; + } + *dst = from; + return true; +} + +TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) { + using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility; + using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness; + const auto frameRateCompatibility = [frameRate] { + switch (frameRate.type) { + case Layer::FrameRateCompatibility::Default: + return FrameRateCompatibility::Default; + case Layer::FrameRateCompatibility::ExactOrMultiple: + return FrameRateCompatibility::ExactOrMultiple; + default: + return FrameRateCompatibility::Undefined; + } + }(); + + const auto seamlessness = [frameRate] { + switch (frameRate.seamlessness) { + case scheduler::Seamlessness::OnlySeamless: + return Seamlessness::ShouldBeSeamless; + case scheduler::Seamlessness::SeamedAndSeamless: + return Seamlessness::NotRequired; + default: + return Seamlessness::Undefined; + } + }(); + + return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(), + .frameRateCompatibility = frameRateCompatibility, + .seamlessness = seamlessness}; +} } // namespace BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) @@ -97,7 +138,6 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) ALOGV("Creating Layer %s", getDebugName()); mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); - mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow; mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp; mDrawingState.dataspace = ui::Dataspace::V0_SRGB; @@ -127,6 +167,20 @@ BufferStateLayer::~BufferStateLayer() { mFlinger->mFrameTracer->onDestroy(layerId); } +void BufferStateLayer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener, + const sp<GraphicBuffer>& buffer, + uint64_t framenumber, + const sp<Fence>& releaseFence, + uint32_t currentMaxAcquiredBufferCount) { + if (!listener) { + return; + } + ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber); + listener->onReleaseBuffer({buffer->getId(), framenumber}, + releaseFence ? releaseFence : Fence::NO_FENCE, + currentMaxAcquiredBufferCount); +} + // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- @@ -239,14 +293,6 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mDrawingState.callbackHandles = {}; } -void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, - const CompositorTiming& compositorTiming) { - for (const auto& handle : mDrawingState.callbackHandles) { - handle->gpuCompositionDoneFence = glDoneFence; - handle->compositorTiming = compositorTiming; - } -} - bool BufferStateLayer::willPresentCurrentTransaction() const { // Returns true if the most recent Transaction applied to CurrentState will be presented. return (getSidebandStreamChanged() || getAutoRefresh() || @@ -307,14 +353,6 @@ bool BufferStateLayer::setDestinationFrame(const Rect& destinationFrame) { return true; } -static bool assignTransform(ui::Transform* dst, ui::Transform& from) { - if (*dst == from) { - return false; - } - *dst = from; - return true; -} - // Translate destination frame into scale and position. If a destination frame is not set, use the // provided scale and position bool BufferStateLayer::updateGeometry() { @@ -641,14 +679,6 @@ bool BufferStateLayer::fenceHasSignaled() const { return fenceSignaled; } -bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { - if (!hasFrameUpdate() || isRemovedFromCurrentState()) { - return true; - } - - return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime; -} - bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { for (const auto& handle : mDrawingState.callbackHandles) { handle->refreshStartTime = refreshStartTime; @@ -685,8 +715,7 @@ bool BufferStateLayer::hasFrameUpdate() const { return (mDrawingStateModified || mDrawingState.modified) && (c.buffer != nullptr || c.bgColorLayer != nullptr); } -status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, - nsecs_t /*expectedPresentTime*/) { +void BufferStateLayer::updateTexImage(nsecs_t latchTime) { const State& s(getDrawingState()); if (!s.buffer) { @@ -695,7 +724,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse handle->latchTime = latchTime; } } - return NO_ERROR; + return; } for (auto& handle : mDrawingState.callbackHandles) { @@ -734,135 +763,36 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse mDrawingState.callbackHandles = remainingHandles; mDrawingStateModified = false; - - return NO_ERROR; } -status_t BufferStateLayer::updateActiveBuffer() { - const State& s(getDrawingState()); - - if (s.buffer == nullptr) { - return BAD_VALUE; - } - - if (!mBufferInfo.mBuffer || !s.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) { +void BufferStateLayer::gatherBufferInfo() { + if (!mBufferInfo.mBuffer || !mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) { decrementPendingBufferCount(); } mPreviousReleaseCallbackId = {getCurrentBufferId(), mBufferInfo.mFrameNumber}; - mBufferInfo.mBuffer = s.buffer; - mBufferInfo.mFence = s.acquireFence; - mBufferInfo.mFrameNumber = s.frameNumber; - - return NO_ERROR; -} - -status_t BufferStateLayer::updateFrameNumber() { - // TODO(marissaw): support frame history events - mPreviousFrameNumber = mCurrentFrameNumber; - mCurrentFrameNumber = mDrawingState.frameNumber; - return NO_ERROR; -} - -void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { - std::lock_guard lock(mMutex); - if (!clientCacheId.isValid()) { - ALOGE("invalid process, failed to erase buffer"); - return; - } - eraseBufferLocked(clientCacheId); -} - -int BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) { - std::lock_guard<std::mutex> lock(mMutex); - auto itr = mCachedBuffers.find(clientCacheId); - if (itr == mCachedBuffers.end()) { - return addCachedBuffer(clientCacheId); - } - auto& [hwcCacheSlot, counter] = itr->second; - counter = mCounter++; - return hwcCacheSlot; -} - -int BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId) - REQUIRES(mMutex) { - if (!clientCacheId.isValid()) { - ALOGE("invalid process, returning invalid slot"); - return BufferQueue::INVALID_BUFFER_SLOT; - } - - ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this)); - - int hwcCacheSlot = getFreeHwcCacheSlot(); - mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++}; - return hwcCacheSlot; -} - -int BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) { - if (mFreeHwcCacheSlots.empty()) { - evictLeastRecentlyUsed(); - } - - int hwcCacheSlot = mFreeHwcCacheSlots.top(); - mFreeHwcCacheSlots.pop(); - return hwcCacheSlot; -} - -void BufferStateLayer::HwcSlotGenerator::evictLeastRecentlyUsed() REQUIRES(mMutex) { - uint64_t minCounter = UINT_MAX; - client_cache_t minClientCacheId = {}; - for (const auto& [clientCacheId, slotCounter] : mCachedBuffers) { - const auto& [hwcCacheSlot, counter] = slotCounter; - if (counter < minCounter) { - minCounter = counter; - minClientCacheId = clientCacheId; - } - } - eraseBufferLocked(minClientCacheId); - - ClientCache::getInstance().unregisterErasedRecipient(minClientCacheId, this); -} - -void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& clientCacheId) - REQUIRES(mMutex) { - auto itr = mCachedBuffers.find(clientCacheId); - if (itr == mCachedBuffers.end()) { - return; - } - auto& [hwcCacheSlot, counter] = itr->second; - - // TODO send to hwc cache and resources - - mFreeHwcCacheSlots.push(hwcCacheSlot); - mCachedBuffers.erase(clientCacheId); -} - -void BufferStateLayer::gatherBufferInfo() { + mBufferInfo.mBuffer = mDrawingState.buffer; + mBufferInfo.mFence = mDrawingState.acquireFence; + mBufferInfo.mFrameNumber = mDrawingState.frameNumber; mBufferInfo.mPixelFormat = !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getPixelFormat(); mBufferInfo.mFrameLatencyNeeded = true; - - const State& s(getDrawingState()); - mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; - mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence); - mBufferInfo.mFence = s.acquireFence; - mBufferInfo.mTransform = s.bufferTransform; + mBufferInfo.mDesiredPresentTime = mDrawingState.desiredPresentTime; + mBufferInfo.mFenceTime = std::make_shared<FenceTime>(mDrawingState.acquireFence); + mBufferInfo.mFence = mDrawingState.acquireFence; + mBufferInfo.mTransform = mDrawingState.bufferTransform; auto lastDataspace = mBufferInfo.mDataspace; - mBufferInfo.mDataspace = translateDataspace(s.dataspace); + mBufferInfo.mDataspace = translateDataspace(mDrawingState.dataspace); if (lastDataspace != mBufferInfo.mDataspace) { mFlinger->mSomeDataspaceChanged = true; } - mBufferInfo.mCrop = computeBufferCrop(s); + mBufferInfo.mCrop = computeBufferCrop(mDrawingState); mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; - mBufferInfo.mHdrMetadata = s.hdrMetadata; - mBufferInfo.mApi = s.api; - mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; - mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); -} - -uint32_t BufferStateLayer::getEffectiveScalingMode() const { - return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + mBufferInfo.mSurfaceDamage = mDrawingState.surfaceDamageRegion; + mBufferInfo.mHdrMetadata = mDrawingState.hdrMetadata; + mBufferInfo.mApi = mDrawingState.api; + mBufferInfo.mTransformToDisplayInverse = mDrawingState.transformToDisplayInverse; + mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(mDrawingState.clientCacheId); } Rect BufferStateLayer::computeBufferCrop(const State& s) { @@ -1178,32 +1108,6 @@ bool BufferStateLayer::isVisible() const { (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); } -bool BufferStateLayer::isFixedSize() const { - return true; -} - -bool BufferStateLayer::usesSourceCrop() const { - return true; -} - -static constexpr mat4 inverseOrientation(uint32_t transform) { - const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1); - const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1); - const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1); - mat4 tr; - - if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) { - tr = tr * rot90; - } - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) { - tr = tr * flipH; - } - if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) { - tr = tr * flipV; - } - return inverse(tr); -} - std::optional<compositionengine::LayerFE::LayerSettings> BufferStateLayer::prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) { ATRACE_CALL(); @@ -1373,38 +1277,6 @@ void BufferStateLayer::preparePerFrameCompositionState() { compositionState->sidebandStreamHasFrame = false; } -namespace { -TimeStats::SetFrameRateVote frameRateToSetFrameRateVotePayload(Layer::FrameRate frameRate) { - using FrameRateCompatibility = TimeStats::SetFrameRateVote::FrameRateCompatibility; - using Seamlessness = TimeStats::SetFrameRateVote::Seamlessness; - const auto frameRateCompatibility = [frameRate] { - switch (frameRate.type) { - case Layer::FrameRateCompatibility::Default: - return FrameRateCompatibility::Default; - case Layer::FrameRateCompatibility::ExactOrMultiple: - return FrameRateCompatibility::ExactOrMultiple; - default: - return FrameRateCompatibility::Undefined; - } - }(); - - const auto seamlessness = [frameRate] { - switch (frameRate.seamlessness) { - case scheduler::Seamlessness::OnlySeamless: - return Seamlessness::ShouldBeSeamless; - case scheduler::Seamlessness::SeamedAndSeamless: - return Seamlessness::NotRequired; - default: - return Seamlessness::Undefined; - } - }(); - - return TimeStats::SetFrameRateVote{.frameRate = frameRate.rate.getValue(), - .frameRateCompatibility = frameRateCompatibility, - .seamlessness = seamlessness}; -} -} // namespace - void BufferStateLayer::onPostComposition(const DisplayDevice* display, const std::shared_ptr<FenceTime>& glDoneFence, const std::shared_ptr<FenceTime>& presentFence, @@ -1413,8 +1285,10 @@ void BufferStateLayer::onPostComposition(const DisplayDevice* display, // composition. if (!mBufferInfo.mFrameLatencyNeeded) return; - // Update mFrameEventHistory. - finalizeFrameEventHistory(glDoneFence, compositorTiming); + for (const auto& handle : mDrawingState.callbackHandles) { + handle->gpuCompositionDoneFence = glDoneFence; + handle->compositorTiming = compositorTiming; + } // Update mFrameTracker. nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; @@ -1480,8 +1354,7 @@ void BufferStateLayer::onPostComposition(const DisplayDevice* display, mBufferInfo.mFrameLatencyNeeded = false; } -bool BufferStateLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, - nsecs_t expectedPresentTime) { +bool BufferStateLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(), getDrawingState().frameNumber); @@ -1499,27 +1372,16 @@ bool BufferStateLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchT return false; } - // Capture the old state of the layer for comparisons later - const State& s(getDrawingState()); - const bool oldOpacity = isOpaque(s); - - BufferInfo oldBufferInfo = mBufferInfo; - - status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime); - if (err != NO_ERROR) { - return false; - } - - err = updateActiveBuffer(); - if (err != NO_ERROR) { - return false; - } - - err = updateFrameNumber(); - if (err != NO_ERROR) { + updateTexImage(latchTime); + if (mDrawingState.buffer == nullptr) { return false; } + // Capture the old state of the layer for comparisons later + BufferInfo oldBufferInfo = mBufferInfo; + const bool oldOpacity = isOpaque(mDrawingState); + mPreviousFrameNumber = mCurrentFrameNumber; + mCurrentFrameNumber = mDrawingState.frameNumber; gatherBufferInfo(); if (oldBufferInfo.mBuffer == nullptr) { @@ -1544,7 +1406,7 @@ bool BufferStateLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchT } } - if (oldOpacity != isOpaque(s)) { + if (oldOpacity != isOpaque(mDrawingState)) { recomputeVisibleRegions = true; } @@ -1628,7 +1490,7 @@ bool BufferStateLayer::needsFilteringForScreenshots( void BufferStateLayer::latchAndReleaseBuffer() { if (hasReadyFrame()) { bool ignored = false; - latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); + latchBuffer(ignored, systemTime()); } releasePendingBuffer(systemTime()); } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index df7ae611b8..8bad3d230c 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -40,6 +40,7 @@ #include "DisplayHardware/HWComposer.h" #include "FrameTimeline.h" #include "FrameTracker.h" +#include "HwcSlotGenerator.h" #include "Layer.h" #include "LayerVector.h" #include "SurfaceFlinger.h" @@ -74,10 +75,7 @@ public: // GRALLOC_USAGE_PROTECTED sense. bool isProtected() const override; - // isFixedSize - true if content has a fixed size - bool isFixedSize() const override; - - bool usesSourceCrop() const override; + bool usesSourceCrop() const override { return true; } bool isHdrY410() const override; @@ -89,13 +87,9 @@ 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, - nsecs_t expectedPresentTime) override; + bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; bool hasReadyFrame() const override; - // Returns the current scaling mode - 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. @@ -122,14 +116,6 @@ public: void releasePendingBuffer(nsecs_t dequeueReadyTime) override; - void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& glDoneFence, - const CompositorTiming& compositorTiming) override; - - // Returns true if the next buffer should be presented at the expected present time, - // overridden by BufferStateLayer and BufferQueueLayer for implementation - // specific logic - bool isBufferDue(nsecs_t /*expectedPresentTime*/) const { return true; } - Region getActiveTransparentRegion(const Layer::State& s) const override { return s.transparentRegionHint; } @@ -166,7 +152,6 @@ public: bool updateGeometry() override; bool fenceHasSignaled() const; - bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const; bool onPreComposition(nsecs_t) override; // See mPendingBufferTransactions @@ -174,9 +159,6 @@ public: std::atomic<int32_t>* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } - // Returns true if the next buffer should be presented at the expected present time - bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const override { return true; } - protected: void gatherBufferInfo(); void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame); @@ -268,11 +250,7 @@ private: bool hasFrameUpdate() const; - status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, - nsecs_t expectedPresentTime); - - status_t updateActiveBuffer(); - status_t updateFrameNumber(); + void updateTexImage(nsecs_t latchTime); sp<Layer> createClone() override; @@ -323,45 +301,6 @@ private: // not specify a destination frame. ui::Transform mRequestedTransform; - // TODO(marissaw): support sticky transform for LEGACY camera mode - - class HwcSlotGenerator : public ClientCache::ErasedRecipient { - public: - HwcSlotGenerator() { - for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { - mFreeHwcCacheSlots.push(i); - } - } - - void bufferErased(const client_cache_t& clientCacheId); - - int getHwcCacheSlot(const client_cache_t& clientCacheId); - - private: - friend class SlotGenerationTest; - int addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex); - int getFreeHwcCacheSlot() REQUIRES(mMutex); - void evictLeastRecentlyUsed() REQUIRES(mMutex); - void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex); - - struct CachedBufferHash { - std::size_t operator()(const client_cache_t& clientCacheId) const { - return std::hash<uint64_t>{}(clientCacheId.id); - } - }; - - std::mutex mMutex; - - std::unordered_map<client_cache_t, std::pair<int /*HwcCacheSlot*/, uint64_t /*counter*/>, - CachedBufferHash> - mCachedBuffers GUARDED_BY(mMutex); - std::stack<int /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex); - - // The cache increments this counter value when a slot is updated or used. - // Used to track the least recently-used buffer - uint64_t mCounter = 0; - }; - sp<HwcSlotGenerator> mHwcSlotGenerator; }; diff --git a/services/surfaceflinger/HwcSlotGenerator.cpp b/services/surfaceflinger/HwcSlotGenerator.cpp new file mode 100644 index 0000000000..b7e9607c4b --- /dev/null +++ b/services/surfaceflinger/HwcSlotGenerator.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2022 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 "HwcSlotGenerator" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include <gui/BufferQueue.h> + +#include "HwcSlotGenerator.h" + +namespace android { + +HwcSlotGenerator::HwcSlotGenerator() { + for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { + mFreeHwcCacheSlots.push(i); + } +} + +void HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { + std::lock_guard lock(mMutex); + if (!clientCacheId.isValid()) { + ALOGE("invalid process, failed to erase buffer"); + return; + } + eraseBufferLocked(clientCacheId); +} + +int HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) { + std::lock_guard<std::mutex> lock(mMutex); + auto itr = mCachedBuffers.find(clientCacheId); + if (itr == mCachedBuffers.end()) { + return addCachedBuffer(clientCacheId); + } + auto& [hwcCacheSlot, counter] = itr->second; + counter = mCounter++; + return hwcCacheSlot; +} + +int HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex) { + if (!clientCacheId.isValid()) { + ALOGE("invalid process, returning invalid slot"); + return BufferQueue::INVALID_BUFFER_SLOT; + } + + ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this)); + + int hwcCacheSlot = getFreeHwcCacheSlot(); + mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++}; + return hwcCacheSlot; +} + +int HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) { + if (mFreeHwcCacheSlots.empty()) { + evictLeastRecentlyUsed(); + } + + int hwcCacheSlot = mFreeHwcCacheSlots.top(); + mFreeHwcCacheSlots.pop(); + return hwcCacheSlot; +} + +void HwcSlotGenerator::evictLeastRecentlyUsed() REQUIRES(mMutex) { + uint64_t minCounter = UINT_MAX; + client_cache_t minClientCacheId = {}; + for (const auto& [clientCacheId, slotCounter] : mCachedBuffers) { + const auto& [hwcCacheSlot, counter] = slotCounter; + if (counter < minCounter) { + minCounter = counter; + minClientCacheId = clientCacheId; + } + } + eraseBufferLocked(minClientCacheId); + + ClientCache::getInstance().unregisterErasedRecipient(minClientCacheId, this); +} + +void HwcSlotGenerator::eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex) { + auto itr = mCachedBuffers.find(clientCacheId); + if (itr == mCachedBuffers.end()) { + return; + } + auto& [hwcCacheSlot, counter] = itr->second; + + // TODO send to hwc cache and resources + + mFreeHwcCacheSlots.push(hwcCacheSlot); + mCachedBuffers.erase(clientCacheId); +} + +} // namespace android diff --git a/services/surfaceflinger/HwcSlotGenerator.h b/services/surfaceflinger/HwcSlotGenerator.h new file mode 100644 index 0000000000..5a1b6d7d9d --- /dev/null +++ b/services/surfaceflinger/HwcSlotGenerator.h @@ -0,0 +1,58 @@ +/* + * Copyright 2022 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 <functional> +#include <mutex> +#include <stack> +#include <unordered_map> + +#include "ClientCache.h" + +namespace android { + +class HwcSlotGenerator : public ClientCache::ErasedRecipient { +public: + HwcSlotGenerator(); + void bufferErased(const client_cache_t& clientCacheId); + int getHwcCacheSlot(const client_cache_t& clientCacheId); + +private: + friend class SlotGenerationTest; + int addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex); + int getFreeHwcCacheSlot() REQUIRES(mMutex); + void evictLeastRecentlyUsed() REQUIRES(mMutex); + void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex); + + struct CachedBufferHash { + std::size_t operator()(const client_cache_t& clientCacheId) const { + return std::hash<uint64_t>{}(clientCacheId.id); + } + }; + + std::mutex mMutex; + + std::unordered_map<client_cache_t, std::pair<int /*HwcCacheSlot*/, uint64_t /*counter*/>, + CachedBufferHash> + mCachedBuffers GUARDED_BY(mMutex); + std::stack<int /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex); + + // The cache increments this counter value when a slot is updated or used. + // Used to track the least recently-used buffer + uint64_t mCounter = 0; +}; +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba3cb51f39..fe12a0bc2f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2112,8 +2112,6 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo) { layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(getDataSpace()))); layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_curr_frame(mCurrentFrameNumber); - layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); - layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius); layerInfo->set_corner_radius( (getRoundedCornerState().radius.x + getRoundedCornerState().radius.y) / 2.0); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b809c8a192..67e4e8f4b9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -528,8 +528,6 @@ public: virtual bool isHdrY410() const { return false; } - virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } - /* * called after composition. * returns true if the layer latched a new buffer this frame. @@ -542,17 +540,13 @@ public: // If a buffer was replaced this frame, release the former buffer virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { } - virtual void finalizeFrameEventHistory(const std::shared_ptr<FenceTime>& /*glDoneFence*/, - const CompositorTiming& /*compositorTiming*/) {} - /* * latchBuffer - called each time the screen is redrawn and returns whether * 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. */ - virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/, - nsecs_t /*expectedPresentTime*/) { + virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) { return false; } @@ -926,11 +920,6 @@ protected: virtual void commitTransaction(State& stateToCommit); virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {} - // Returns mCurrentScaling mode (originating from the - // Client) or mOverrideScalingMode mode (originating from - // the Surface Controller) if set. - virtual uint32_t getEffectiveScalingMode() const { return 0; } - sp<compositionengine::LayerFE> asLayerFE() const; sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } bool isClone() { return mClonedFrom != nullptr; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9ef8e7b5f3..e880bd42b8 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3540,8 +3540,6 @@ bool SurfaceFlinger::latchBuffers() { 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: @@ -3561,12 +3559,7 @@ bool SurfaceFlinger::latchBuffers() { if (layer->hasReadyFrame()) { frameQueued = true; - if (layer->shouldPresentNow(expectedPresentTime)) { - mLayersWithQueuedFrames.emplace(layer); - } else { - ATRACE_NAME("!layer->shouldPresentNow()"); - layer->useEmptyDamage(); - } + mLayersWithQueuedFrames.emplace(layer); } else { layer->useEmptyDamage(); } @@ -3587,7 +3580,7 @@ bool SurfaceFlinger::latchBuffers() { Mutex::Autolock lock(mStateLock); for (const auto& layer : mLayersWithQueuedFrames) { - if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) { + if (layer->latchBuffer(visibleRegions, latchTime)) { mLayersPendingRefresh.push_back(layer); newDataLatched = true; } diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 4d90b1e56e..ed94e76fd0 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -125,9 +125,7 @@ void LayerFuzzer::invokeBufferStateLayer() { ftl::yield<FenceResult>(base::unexpected(mFdp.ConsumeIntegral<status_t>())).share()); layer->releasePendingBuffer(mFdp.ConsumeIntegral<int64_t>()); - layer->finalizeFrameEventHistory(fenceTime, compositorTiming); layer->onPostComposition(nullptr, fenceTime, fenceTime, compositorTiming); - layer->isBufferDue(mFdp.ConsumeIntegral<int64_t>()); layer->setTransform(mFdp.ConsumeIntegral<uint32_t>()); layer->setTransformToDisplayInverse(mFdp.ConsumeBool()); @@ -151,7 +149,6 @@ void LayerFuzzer::invokeBufferStateLayer() { layer->computeSourceBounds(getFuzzedFloatRect(&mFdp)); layer->fenceHasSignaled(); - layer->framePresentTimeIsCurrent(mFdp.ConsumeIntegral<int64_t>()); layer->onPreComposition(mFdp.ConsumeIntegral<int64_t>()); const std::vector<sp<CallbackHandle>> callbacks; layer->setTransactionCompletedListeners(callbacks); diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp index 6f85498670..7f203ce943 100644 --- a/services/surfaceflinger/tests/unittests/CachingTest.cpp +++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp @@ -26,8 +26,7 @@ namespace android { class SlotGenerationTest : public testing::Test { protected: - sp<BufferStateLayer::HwcSlotGenerator> mHwcSlotGenerator = - sp<BufferStateLayer::HwcSlotGenerator>::make(); + sp<HwcSlotGenerator> mHwcSlotGenerator = sp<HwcSlotGenerator>::make(); sp<GraphicBuffer> mBuffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; sp<GraphicBuffer> mBuffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; sp<GraphicBuffer> mBuffer3{new GraphicBuffer(10, 10, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index f6ebfe5af1..9c16e4cba8 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -511,7 +511,7 @@ struct BaseLayerProperties { Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH))); bool ignoredRecomputeVisibleRegions; - layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0); + layer->latchBuffer(ignoredRecomputeVisibleRegions, 0); Mock::VerifyAndClear(test->mRenderEngine); } diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 5364630400..28bf8bf0f9 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -127,7 +127,6 @@ public: dequeueTime, FrameTimelineInfo{}); commitTransaction(layer.get()); - bool computeVisisbleRegions; nsecs_t latchTime = 25; EXPECT_CALL(*mFlinger.getFrameTracer(), traceFence(layerId, bufferId, frameNumber, _, @@ -135,7 +134,7 @@ public: EXPECT_CALL(*mFlinger.getFrameTracer(), traceTimestamp(layerId, bufferId, frameNumber, latchTime, FrameTracer::FrameEvent::LATCH, /*duration*/ 0)); - layer->updateTexImage(computeVisisbleRegions, latchTime, /*expectedPresentTime*/ 0); + layer->updateTexImage(latchTime); auto glDoneFence = fenceFactory.createFenceTimeForTest(fence); auto presentFence = fenceFactory.createFenceTimeForTest(fence); diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 6d583036fa..e943644834 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -140,8 +140,7 @@ public: // Buffers are presented only at latch time. EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); EXPECT_EQ(1, surfaceFrame->getToken()); EXPECT_EQ(true, surfaceFrame->getIsBuffer()); @@ -192,8 +191,7 @@ public: const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); EXPECT_EQ(1, droppedSurfaceFrame->getToken()); EXPECT_EQ(true, droppedSurfaceFrame->getIsBuffer()); @@ -243,8 +241,7 @@ public: // Buffers are presented only at latch time. EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); } @@ -331,8 +328,7 @@ public: // Buffers are presented only at latch time. EXPECT_EQ(PresentState::Unknown, bufferSurfaceFrameTX->getPresentState()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState()); } @@ -377,8 +373,7 @@ public: auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); // Both the droppedSurfaceFrame and presentedSurfaceFrame should be in // pendingJankClassifications. @@ -458,8 +453,7 @@ public: const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); EXPECT_EQ(1, droppedSurfaceFrame1->getToken()); EXPECT_EQ(true, droppedSurfaceFrame1->getIsBuffer()); @@ -517,8 +511,7 @@ public: } auto presentedBufferSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; - bool computeVisisbleRegions; - layer->updateTexImage(computeVisisbleRegions, 15, 0); + layer->updateTexImage(15); // BufferlessSurfaceFrames are immediately set to presented and added to the DisplayFrame. // Since we don't have access to DisplayFrame here, trigger an onPresent directly. for (auto& surfaceFrame : bufferlessSurfaceFrames) { |