From 29d0da35d9024daf4b14d6b3d3843ae5216ec4e7 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 16 Jul 2020 18:39:33 -0700 Subject: SF: add a spinner to refresh rate overlay Add a spinner to refresh rate overlay to visualize when the display updates. Test: adb shell setprop sf.debug.show_refresh_rate_overlay_spinner 1 and enable refresh rate overlay Change-Id: I089df8437cffb45ef631772fe0179970f21abfa0 --- services/surfaceflinger/RefreshRateOverlay.cpp | 98 ++++++++++++++++++-------- 1 file changed, 70 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index f602412930..d8477e7bc2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -106,41 +106,71 @@ void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, cons drawSegment(Segment::Buttom, left, color, buffer, pixels); } -sp RefreshRateOverlay::SevenSegmentDrawer::drawNumber(int number, - const half4& color) { - if (number < 0 || number > 1000) return nullptr; +std::vector> RefreshRateOverlay::SevenSegmentDrawer::drawNumber( + int number, const half4& color, bool showSpinner) { + if (number < 0 || number > 1000) return {}; const auto hundreds = number / 100; const auto tens = (number / 10) % 10; const auto ones = number % 10; - sp buffer = - new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | - GRALLOC_USAGE_HW_TEXTURE, - "RefreshRateOverlayBuffer"); - uint8_t* pixels; - buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast(&pixels)); - // Clear buffer content - drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); - int left = 0; - if (hundreds != 0) { - drawDigit(hundreds, left, color, buffer, pixels); + std::vector> buffers; + const auto loopCount = showSpinner ? 6 : 1; + for (int i = 0; i < loopCount; i++) { + sp buffer = + new GraphicBuffer(BUFFER_WIDTH, BUFFER_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | + GRALLOC_USAGE_HW_TEXTURE, + "RefreshRateOverlayBuffer"); + uint8_t* pixels; + buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast(&pixels)); + // Clear buffer content + drawRect(Rect(BUFFER_WIDTH, BUFFER_HEIGHT), half4(0), buffer, pixels); + int left = 0; + if (hundreds != 0) { + drawDigit(hundreds, left, color, buffer, pixels); + } left += DIGIT_WIDTH + DIGIT_SPACE; - } - if (tens != 0) { - drawDigit(tens, left, color, buffer, pixels); + if (tens != 0) { + drawDigit(tens, left, color, buffer, pixels); + } left += DIGIT_WIDTH + DIGIT_SPACE; - } - drawDigit(ones, left, color, buffer, pixels); - buffer->unlock(); - return buffer; + drawDigit(ones, left, color, buffer, pixels); + left += DIGIT_WIDTH + DIGIT_SPACE; + + if (showSpinner) { + switch (i) { + case 0: + drawSegment(Segment::Upper, left, color, buffer, pixels); + break; + case 1: + drawSegment(Segment::UpperRight, left, color, buffer, pixels); + break; + case 2: + drawSegment(Segment::LowerRight, left, color, buffer, pixels); + break; + case 3: + drawSegment(Segment::Buttom, left, color, buffer, pixels); + break; + case 4: + drawSegment(Segment::LowerLeft, left, color, buffer, pixels); + break; + case 5: + drawSegment(Segment::UpperLeft, left, color, buffer, pixels); + break; + } + } + + buffer->unlock(); + buffers.emplace_back(buffer); + } + return buffers; } -RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) - : mFlinger(flinger), mClient(new Client(&mFlinger)) { +RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner) + : mFlinger(flinger), mClient(new Client(&mFlinger)), mShowSpinner(showSpinner) { createLayer(); primeCache(); } @@ -176,7 +206,7 @@ void RefreshRateOverlay::primeCache() { if (allRefreshRates.size() == 1) { auto fps = allRefreshRates.begin()->second->getFps(); half4 color = {LOW_FPS_COLOR, ALPHA}; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); return; } @@ -196,12 +226,12 @@ void RefreshRateOverlay::primeCache() { color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color)); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); } } void RefreshRateOverlay::setViewport(ui::Size viewport) { - Rect frame(viewport.width >> 3, viewport.height >> 5); + Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); mLayer->setFrame(frame); @@ -209,7 +239,19 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - auto buffer = mBufferCache[refreshRate.getFps()]; + mCurrentFps = refreshRate.getFps(); + auto buffer = mBufferCache[*mCurrentFps][mFrame]; + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + + mFlinger.mTransactionFlags.fetch_or(eTransactionMask); +} + +void RefreshRateOverlay::onInvalidate() { + if (!mCurrentFps.has_value()) return; + + const auto& buffers = mBufferCache[*mCurrentFps]; + mFrame = (mFrame + 1) % buffers.size(); + auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); -- cgit v1.2.3-59-g8ed1b From 6b7c5c9425496be2166fccf2ab14e061b5a20fa3 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 29 Sep 2020 17:27:05 -0700 Subject: Pass in framenumbers if submitting buffers via BlastBufferQueue The framenumber generated by the graphics producer is forwarded to mimic BufferQueue behaviour. Test: atest SurfaceViewBufferTests Bug: 168504870 Change-Id: Ic652a585d10d7e14c9dd94afaabd0e485e209ede --- libs/gui/BLASTBufferQueue.cpp | 1 + libs/gui/LayerState.cpp | 12 +++++++++--- libs/gui/SurfaceComposerClient.cpp | 18 ++++++++++++++++-- libs/gui/include/gui/LayerState.h | 12 +++++++++--- libs/gui/include/gui/SurfaceComposerClient.h | 2 ++ services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 4 ++-- services/surfaceflinger/BufferStateLayer.h | 3 ++- services/surfaceflinger/Layer.cpp | 14 +++++++------- services/surfaceflinger/Layer.h | 6 ++++-- services/surfaceflinger/RefreshRateOverlay.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.cpp | 13 +++++++++---- services/surfaceflinger/SurfaceInterceptor.cpp | 4 ++-- 13 files changed, 68 insertions(+), 29 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 3b2788a599..ba72f9b45f 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -270,6 +270,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); t->setDesiredPresentTime(bufferItem.mTimestamp); + t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); if (applyTransaction) { t->apply(); diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6ff4a3d4e2..150a36d745 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -45,7 +45,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.write, crop_legacy); SAFE_PARCEL(output.writeStrongBinder, barrierHandle_legacy); SAFE_PARCEL(output.writeStrongBinder, reparentHandle); - SAFE_PARCEL(output.writeUint64, frameNumber_legacy); + SAFE_PARCEL(output.writeUint64, barrierFrameNumber); SAFE_PARCEL(output.writeInt32, overrideScalingMode); SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(barrierGbp_legacy)); SAFE_PARCEL(output.writeStrongBinder, relativeLayerHandle); @@ -108,6 +108,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeFloat, frameRate); SAFE_PARCEL(output.writeByte, frameRateCompatibility); SAFE_PARCEL(output.writeUint32, fixedTransformHint); + SAFE_PARCEL(output.writeUint64, frameNumber); return NO_ERROR; } @@ -134,7 +135,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.read, crop_legacy); SAFE_PARCEL(input.readNullableStrongBinder, &barrierHandle_legacy); SAFE_PARCEL(input.readNullableStrongBinder, &reparentHandle); - SAFE_PARCEL(input.readUint64, &frameNumber_legacy); + SAFE_PARCEL(input.readUint64, &barrierFrameNumber); SAFE_PARCEL(input.readInt32, &overrideScalingMode); sp tmpBinder; @@ -213,6 +214,7 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(input.readByte, &frameRateCompatibility); SAFE_PARCEL(input.readUint32, &tmpUint32); fixedTransformHint = static_cast(tmpUint32); + SAFE_PARCEL(input.readUint64, &frameNumber); return NO_ERROR; } @@ -340,7 +342,7 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eDeferTransaction_legacy; barrierHandle_legacy = other.barrierHandle_legacy; barrierGbp_legacy = other.barrierGbp_legacy; - frameNumber_legacy = other.frameNumber_legacy; + barrierFrameNumber = other.barrierFrameNumber; } if (other.what & eOverrideScalingModeChanged) { what |= eOverrideScalingModeChanged; @@ -456,6 +458,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFixedTransformHintChanged; fixedTransformHint = other.fixedTransformHint; } + if (other.what & eFrameNumberChanged) { + what |= eFrameNumberChanged; + frameNumber = other.frameNumber; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 8d2a7d9abc..f24dfca680 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1000,7 +1000,7 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierHandle_legacy = handle; - s->frameNumber_legacy = frameNumber; + s->barrierFrameNumber = frameNumber; registerSurfaceControlForCallback(sc); return *this; @@ -1017,7 +1017,7 @@ SurfaceComposerClient::Transaction::deferTransactionUntil_legacy(const spwhat |= layer_state_t::eDeferTransaction_legacy; s->barrierGbp_legacy = barrierSurface->getIGraphicBufferProducer(); - s->frameNumber_legacy = frameNumber; + s->barrierFrameNumber = frameNumber; registerSurfaceControlForCallback(sc); return *this; @@ -1307,6 +1307,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyPr return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameNumber( + const sp& sc, uint64_t frameNumber) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eFrameNumberChanged; + s->frameNumber = frameNumber; + + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren( const sp& sc) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 7a9bb120cf..96ff61b67b 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -125,6 +125,7 @@ struct layer_state_t { eBackgroundBlurRadiusChanged = 0x80'00000000, eProducerDisconnect = 0x100'00000000, eFixedTransformHintChanged = 0x200'00000000, + eFrameNumberChanged = 0x400'00000000, }; layer_state_t() @@ -142,7 +143,7 @@ struct layer_state_t { crop_legacy(Rect::INVALID_RECT), cornerRadius(0.0f), backgroundBlurRadius(0), - frameNumber_legacy(0), + barrierFrameNumber(0), overrideScalingMode(-1), transform(0), transformToDisplayInverse(false), @@ -159,7 +160,8 @@ struct layer_state_t { frameRateSelectionPriority(-1), frameRate(0.0f), frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT), - fixedTransformHint(ui::Transform::ROT_INVALID) { + fixedTransformHint(ui::Transform::ROT_INVALID), + frameNumber(0) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -195,7 +197,7 @@ struct layer_state_t { uint32_t backgroundBlurRadius; sp barrierHandle_legacy; sp reparentHandle; - uint64_t frameNumber_legacy; + uint64_t barrierFrameNumber; int32_t overrideScalingMode; sp barrierGbp_legacy; @@ -259,6 +261,10 @@ struct layer_state_t { // a buffer of a different size. -1 means the transform hint is not set, // otherwise the value will be a valid ui::Rotation. ui::Transform::RotationFlags fixedTransformHint; + + // Used by BlastBufferQueue to forward the framenumber generated by the + // graphics producer. + uint64_t frameNumber; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6cac287d77..ed2bf07aa4 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -487,6 +487,8 @@ public: // ONLY FOR BLAST ADAPTER Transaction& notifyProducerDisconnect(const sp& sc); + // Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour. + Transaction& setFrameNumber(const sp& sc, uint64_t frameNumber); // Detaches all child surfaces (and their children recursively) // from their SurfaceControl. diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 4cbfdffd8f..1cd753b65b 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -167,7 +167,7 @@ protected: void updateCloneBufferInfo() override; uint64_t mPreviousFrameNumber = 0; - virtual uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; + uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const override; void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ea1f78c048..9f99feeea1 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -258,12 +258,12 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, - const client_cache_t& clientCacheId) { + const client_cache_t& clientCacheId, uint64_t frameNumber) { if (mCurrentState.buffer) { mReleasePreviousBuffer = true; } - mCurrentState.frameNumber++; + mCurrentState.frameNumber = frameNumber; mCurrentState.buffer = buffer; mCurrentState.clientCacheId = clientCacheId; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 81959ae2f3..c13f5e8252 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -70,7 +70,8 @@ public: bool setCrop(const Rect& crop) override; bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, const client_cache_t& clientCacheId) override; + nsecs_t desiredPresentTime, const client_cache_t& clientCacheId, + uint64_t frameNumber) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 85046a4194..58291d4ca0 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -800,10 +800,10 @@ void Layer::pushPendingState() { // to be applied as per normal (no synchronization). mCurrentState.barrierLayer_legacy = nullptr; } else { - auto syncPoint = std::make_shared(mCurrentState.frameNumber_legacy, this); + auto syncPoint = std::make_shared(mCurrentState.barrierFrameNumber, this); if (barrierLayer->addSyncPoint(syncPoint)) { std::stringstream ss; - ss << "Adding sync point " << mCurrentState.frameNumber_legacy; + ss << "Adding sync point " << mCurrentState.barrierFrameNumber; ATRACE_NAME(ss.str().c_str()); mRemoteSyncPoints.push_back(std::move(syncPoint)); } else { @@ -844,7 +844,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { } if (mRemoteSyncPoints.front()->getFrameNumber() != - mPendingStates[0].frameNumber_legacy) { + mPendingStates[0].barrierFrameNumber) { ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it @@ -1463,13 +1463,13 @@ void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t } mCurrentState.barrierLayer_legacy = barrierLayer; - mCurrentState.frameNumber_legacy = frameNumber; + mCurrentState.barrierFrameNumber = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral // request without any other state updates shouldn't actually induce a delay mCurrentState.modified = true; pushPendingState(); mCurrentState.barrierLayer_legacy = nullptr; - mCurrentState.frameNumber_legacy = 0; + mCurrentState.barrierFrameNumber = 0; mCurrentState.modified = false; } @@ -2234,7 +2234,7 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags, void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, const DisplayDevice* display) { - ui::Transform transform = getTransform(); + const ui::Transform transform = getTransform(); if (traceFlags & SurfaceTracing::TRACE_CRITICAL) { for (const auto& pendingState : mPendingStatesSnapshot) { @@ -2242,7 +2242,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags, if (barrierLayer != nullptr) { BarrierLayerProto* barrierLayerProto = layerInfo->add_barrier_layer(); barrierLayerProto->set_id(barrierLayer->sequence); - barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); + barrierLayerProto->set_frame_number(pendingState.barrierFrameNumber); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 88ece5058b..bdc4f848dc 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -187,7 +187,7 @@ public: // If set, defers this state update until the identified Layer // receives a frame with the given frameNumber wp barrierLayer_legacy; - uint64_t frameNumber_legacy; + uint64_t barrierFrameNumber; // the transparentRegion hint is a bit special, it's latched only // when we receive a buffer -- this is because it's "content" @@ -406,7 +406,7 @@ public: virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - const client_cache_t& /*clientCacheId*/) { + const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; @@ -510,6 +510,8 @@ public: virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; } + virtual uint64_t getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { return 0; } + /* * called after composition. * returns true if the layer latched a new buffer this frame. diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index d8477e7bc2..99d061daa3 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -241,7 +241,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps(); auto buffer = mBufferCache[*mCurrentFps][mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -252,7 +253,8 @@ void RefreshRateOverlay::onInvalidate() { const auto& buffers = mBufferCache[*mCurrentFps]; mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}); + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 8ac459b05a..1aec382eba 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3681,13 +3681,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eDeferTransaction_legacy) { if (s.barrierHandle_legacy != nullptr) { - layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.frameNumber_legacy); + layer->deferTransactionUntil_legacy(s.barrierHandle_legacy, s.barrierFrameNumber); } else if (s.barrierGbp_legacy != nullptr) { const sp& gbp = s.barrierGbp_legacy; if (authenticateSurfaceTextureLocked(gbp)) { const auto& otherLayer = (static_cast(gbp.get()))->getLayer(); - layer->deferTransactionUntil_legacy(otherLayer, s.frameNumber_legacy); + layer->deferTransactionUntil_legacy(otherLayer, s.barrierFrameNumber); } else { ALOGE("Attempt to defer transaction to to an" " unrecognized GraphicBufferProducer"); @@ -3818,8 +3818,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( buffer = s.buffer; } if (buffer) { - if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, - s.cachedBuffer)) { + const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; + const uint64_t frameNumber = frameNumberChanged + ? s.frameNumber + : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; + + if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, s.cachedBuffer, + frameNumber)) { flags |= eTraversalNeeded; } } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 9d705e5999..ae7fcc3be1 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -148,7 +148,7 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, if (layer->mCurrentState.barrierLayer_legacy != nullptr) { addDeferTransactionLocked(transaction, layerId, layer->mCurrentState.barrierLayer_legacy.promote(), - layer->mCurrentState.frameNumber_legacy); + layer->mCurrentState.barrierFrameNumber); } addOverrideScalingModeLocked(transaction, layerId, layer->getEffectiveScalingMode()); addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, @@ -483,7 +483,7 @@ void SurfaceInterceptor::addSurfaceChangesLocked(Transaction* transaction, ALOGE("Attempt to defer transaction to to an unrecognized GraphicBufferProducer"); } } - addDeferTransactionLocked(transaction, layerId, otherLayer, state.frameNumber_legacy); + addDeferTransactionLocked(transaction, layerId, otherLayer, state.barrierFrameNumber); } if (state.what & layer_state_t::eOverrideScalingModeChanged) { addOverrideScalingModeLocked(transaction, layerId, state.overrideScalingMode); -- cgit v1.2.3-59-g8ed1b From 9f0a4008b72138f6279a12f474b60e5e3caa13c3 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 5 Oct 2020 15:47:26 -0700 Subject: SurfaceFLinger: rename outLayerId - Rename outId to outLayerId to reflect what the Id is. - Remove the default value and require it to be non-nullptr Test: SF tests Change-Id: Icdbbab4a84e9bd5982d274ee5bf522e36545855a --- libs/gui/ISurfaceComposerClient.cpp | 14 +++++++------- libs/gui/include/gui/ISurfaceComposerClient.h | 6 +++--- services/surfaceflinger/Client.cpp | 12 ++++++------ services/surfaceflinger/Client.h | 6 +++--- services/surfaceflinger/RefreshRateOverlay.cpp | 3 ++- services/surfaceflinger/SurfaceFlinger.cpp | 12 +++++------- services/surfaceflinger/SurfaceFlinger.h | 7 ++++--- 7 files changed, 30 insertions(+), 30 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index a814362e3c..5e7a7ec67b 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -49,13 +49,13 @@ public: status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, - sp* handle, sp* gbp, int32_t* outId, - uint32_t* outTransformHint) override { + sp* handle, sp* gbp, + int32_t* outLayerId, uint32_t* outTransformHint) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, format, flags, parent, std::move(metadata), - handle, gbp, outId, + handle, gbp, outLayerId, outTransformHint); } @@ -63,14 +63,14 @@ public: PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint) override { return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, name, width, height, format, flags, parent, std::move(metadata), handle, gbp, - outId, outTransformHint); + outLayerId, outTransformHint); } status_t clearLayerFrameStats(const sp& handle) const override { @@ -86,10 +86,10 @@ public: } status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, - int32_t* outId) override { + int32_t* outLayerId) override { return callRemote(Tag::MIRROR_SURFACE, mirrorFromHandle, - outHandle, outId); + outHandle, outLayerId); } }; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index f3fcebecad..4a92f535a2 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -58,7 +58,7 @@ public: virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint) = 0; /* @@ -68,7 +68,7 @@ public: PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint) = 0; /* @@ -82,7 +82,7 @@ public: virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const = 0; virtual status_t mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, - int32_t* outId) = 0; + int32_t* outLayerId) = 0; }; class BnSurfaceComposerClient : public SafeBnInterface { diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 07817b5a7f..aac6c913cf 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -79,18 +79,18 @@ sp Client::getLayerUser(const sp& handle) const status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parentHandle, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint) { // We rely on createLayer to check permissions. return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - parentHandle, nullptr, outId, outTransformHint); + parentHandle, outLayerId, nullptr, outTransformHint); } status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint) { if (mFlinger->authenticateSurfaceTexture(parent) == false) { ALOGE("failed to authenticate surface texture"); @@ -104,12 +104,12 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 } return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, - nullptr, layer, outId, outTransformHint); + nullptr, outLayerId, layer, outTransformHint); } status_t Client::mirrorSurface(const sp& mirrorFromHandle, sp* outHandle, - int32_t* outId) { - return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle, outId); + int32_t* outLayerId) { + return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle, outLayerId); } status_t Client::clearLayerFrameStats(const sp& handle) const { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 9462f1a7a3..15cd763822 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -50,18 +50,18 @@ private: virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint = nullptr); virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, LayerMetadata metadata, sp* handle, - sp* gbp, int32_t* outId, + sp* gbp, int32_t* outLayerId, uint32_t* outTransformHint = nullptr); status_t mirrorSurface(const sp& mirrorFromHandle, sp* handle, - int32_t* outId); + int32_t* outLayerId); virtual status_t clearLayerFrameStats(const sp& handle) const; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 99d061daa3..f676d5b44b 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -176,12 +176,13 @@ RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner } bool RefreshRateOverlay::createLayer() { + int32_t layerId; const status_t ret = mFlinger.createLayer(String8("RefreshRateOverlay"), mClient, SevenSegmentDrawer::getWidth(), SevenSegmentDrawer::getHeight(), PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceBufferState, LayerMetadata(), - &mIBinder, &mGbp, nullptr); + &mIBinder, &mGbp, nullptr, &layerId); if (ret) { ALOGE("failed to create buffer state layer"); return false; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bf33e5edef..498859ba28 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3846,7 +3846,7 @@ uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& input } status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp& mirrorFromHandle, - sp* outHandle, int32_t* outId) { + sp* outHandle, int32_t* outLayerId) { if (!mirrorFromHandle) { return NAME_NOT_FOUND; } @@ -3871,7 +3871,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp mirrorLayer->mClonedChild = mirrorFrom->createClone(); } - *outId = mirrorLayer->sequence; + *outLayerId = mirrorLayer->sequence; return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false, nullptr /* outTransformHint */); } @@ -3880,8 +3880,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie uint32_t h, PixelFormat format, uint32_t flags, LayerMetadata metadata, sp* handle, sp* gbp, - const sp& parentHandle, const sp& parentLayer, - int32_t* outId, uint32_t* outTransformHint) { + const sp& parentHandle, int32_t* outLayerId, + const sp& parentLayer, uint32_t* outTransformHint) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); @@ -3947,9 +3947,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie mInterceptor->saveSurfaceCreation(layer); setTransactionFlags(eTransactionNeeded); - if (outId) { - *outId = layer->sequence; - } + *outLayerId = layer->sequence; return result; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e50ecf0493..99d0232e59 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -752,8 +752,9 @@ private: status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, LayerMetadata metadata, sp* handle, sp* gbp, - const sp& parentHandle, const sp& parentLayer = nullptr, - int32_t* outId = nullptr, uint32_t* outTransformHint = nullptr); + const sp& parentHandle, int32_t* outLayerId, + const sp& parentLayer = nullptr, + uint32_t* outTransformHint = nullptr); status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, @@ -773,7 +774,7 @@ private: sp* outHandle, sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, - sp* outHandle, int32_t* outId); + sp* outHandle, int32_t* outLayerId); std::string getUniqueLayerName(const char* name); -- cgit v1.2.3-59-g8ed1b From e8a663d78f711666d4f1f9792884ebdcbe185a28 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Tue, 24 Nov 2020 17:48:00 +0100 Subject: Add Fps class Add a class to wrap a fps value. This is useful because across the code we - convert between vsyncPeriod and fps - compare with tolerance (this ensures we use consistent tolerance) - consistent toString method Bug: 159590486 Test: presubmit Change-Id: Iebb77a33a2f822056642aa61bd6fac6514aa656d --- services/surfaceflinger/Fps.h | 112 ++++++ services/surfaceflinger/Layer.cpp | 11 +- services/surfaceflinger/Layer.h | 12 +- services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 11 +- services/surfaceflinger/Scheduler/LayerHistory.h | 2 +- services/surfaceflinger/Scheduler/LayerInfo.cpp | 47 +-- services/surfaceflinger/Scheduler/LayerInfo.h | 24 +- .../Scheduler/RefreshRateConfigs.cpp | 85 +++-- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 51 +-- .../surfaceflinger/Scheduler/RefreshRateStats.h | 6 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 18 +- .../Scheduler/VsyncConfiguration.cpp | 34 +- .../surfaceflinger/Scheduler/VsyncConfiguration.h | 28 +- services/surfaceflinger/SurfaceFlinger.cpp | 44 +-- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/FakeVsyncConfiguration.h | 4 +- .../surfaceflinger/tests/unittests/FpsTest.cpp | 98 +++++ .../tests/unittests/LayerHistoryTest.cpp | 91 ++--- .../tests/unittests/RefreshRateConfigsTest.cpp | 419 +++++++++++---------- .../tests/unittests/SetFrameRateTest.cpp | 11 +- .../tests/unittests/VsyncConfigurationTest.cpp | 46 +-- 22 files changed, 699 insertions(+), 464 deletions(-) create mode 100644 services/surfaceflinger/Fps.h create mode 100644 services/surfaceflinger/tests/unittests/FpsTest.cpp (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/Fps.h b/services/surfaceflinger/Fps.h new file mode 100644 index 0000000000..38a9af0149 --- /dev/null +++ b/services/surfaceflinger/Fps.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 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 { + +// Value which represents "frames per second". This class is a wrapper around +// float, providing some useful utilities, such as comparisons with tolerance +// and converting between period duruation and frequency. +class Fps { +public: + static constexpr Fps fromPeriodNsecs(nsecs_t period) { return Fps(1e9f / period, period); } + + Fps() = default; + explicit constexpr Fps(float fps) + : fps(fps), period(fps == 0.0f ? 0 : static_cast(1e9f / fps)) {} + + constexpr float getValue() const { return fps; } + + constexpr nsecs_t getPeriodNsecs() const { return period; } + + bool equalsWithMargin(const Fps& other) const { return std::abs(fps - other.fps) < kMargin; } + + // DO NOT use for std::sort. Instead use comparesLess(). + bool lessThanWithMargin(const Fps& other) const { return fps + kMargin < other.fps; } + + bool greaterThanWithMargin(const Fps& other) const { return fps > other.fps + kMargin; } + + bool lessThanOrEqualWithMargin(const Fps& other) const { return !greaterThanWithMargin(other); } + + bool greaterThanOrEqualWithMargin(const Fps& other) const { return !lessThanWithMargin(other); } + + bool isValid() const { return fps > 0.0f; } + + int getIntValue() const { return static_cast(std::round(fps)); } + + // Use this comparator for sorting. Using a comparator with margins can + // cause std::sort to crash. + inline static bool comparesLess(const Fps& left, const Fps& right) { + return left.fps < right.fps; + } + + // Compares two FPS with margin. + // Transitivity is not guaranteed, i.e. a==b and b==c doesn't imply a==c. + // DO NOT use with hash maps. Instead use EqualsInBuckets. + struct EqualsWithMargin { + bool operator()(const Fps& left, const Fps& right) const { + return left.equalsWithMargin(right); + } + }; + + // Equals comparator which can be used with hash maps. + // It's guaranteed that if two elements are equal, then their hashes are equal. + struct EqualsInBuckets { + bool operator()(const Fps& left, const Fps& right) const { + return left.getBucket() == right.getBucket(); + } + }; + + inline friend std::string to_string(const Fps& fps) { + return base::StringPrintf("%.2ffps", fps.fps); + } + + inline friend std::ostream& operator<<(std::ostream& os, const Fps& fps) { + return os << to_string(fps); + } + +private: + friend std::hash; + + constexpr Fps(float fps, nsecs_t period) : fps(fps), period(period) {} + + float getBucket() const { return std::round(fps / kMargin); } + + static constexpr float kMargin = 0.001f; + float fps = 0; + nsecs_t period = 0; +}; + +static_assert(std::is_trivially_copyable_v); + +} // namespace android + +namespace std { +template <> +struct hash { + std::size_t operator()(const android::Fps& fps) const { + return std::hash()(fps.getBucket()); + } +}; +} // namespace std \ No newline at end of file diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 90396dd322..949227b119 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1425,7 +1425,8 @@ void Layer::updateTreeHasFrameRateVote() { // First traverse the tree and count how many layers has votes int layersWithVote = 0; traverseTree([&layersWithVote](Layer* layer) { - const auto layerVotedWithDefaultCompatibility = layer->mCurrentState.frameRate.rate > 0 && + const auto layerVotedWithDefaultCompatibility = + layer->mCurrentState.frameRate.rate.isValid() && layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; @@ -1486,14 +1487,14 @@ void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, ns Layer::FrameRate Layer::getFrameRateForLayerTree() const { const auto frameRate = getDrawingState().frameRate; - if (frameRate.rate > 0 || frameRate.type == FrameRateCompatibility::NoVote) { + if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) { return frameRate; } // This layer doesn't have a frame rate. If one of its ancestors or successors // have a vote, return a NoVote for ancestors/successors to set the vote if (getDrawingState().treeHasFrameRateVote) { - return {0, FrameRateCompatibility::NoVote}; + return {Fps(0.0f), FrameRateCompatibility::NoVote}; } return frameRate; @@ -1687,9 +1688,9 @@ void Layer::miniDump(std::string& result, const DisplayDevice& display) const { const FloatRect& crop = outputLayerState.sourceCrop; StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, crop.bottom); - if (layerState.frameRate.rate != 0 || + if (layerState.frameRate.rate.isValid() || layerState.frameRate.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "% 6.2ffps %15s seamless=%s", layerState.frameRate.rate, + StringAppendF(&result, "%s %15s seamless=%s", to_string(layerState.frameRate.rate).c_str(), frameRateCompatibilityString(layerState.frameRate.type).c_str(), toString(layerState.frameRate.seamlessness).c_str()); } else { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 75d68a16f2..e9fd550660 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -45,6 +45,7 @@ #include "ClientCache.h" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/HWComposer.h" +#include "Fps.h" #include "FrameTracker.h" #include "LayerVector.h" #include "MonitoredProducer.h" @@ -155,7 +156,7 @@ public: struct FrameRate { using Seamlessness = scheduler::Seamlessness; - float rate; + Fps rate; FrameRateCompatibility type; Seamlessness seamlessness; @@ -163,11 +164,12 @@ public: : rate(0), type(FrameRateCompatibility::Default), seamlessness(Seamlessness::Default) {} - FrameRate(float rate, FrameRateCompatibility type, bool shouldBeSeamless = true) + FrameRate(Fps rate, FrameRateCompatibility type, bool shouldBeSeamless = true) : rate(rate), type(type), seamlessness(getSeamlessness(rate, shouldBeSeamless)) {} bool operator==(const FrameRate& other) const { - return rate == other.rate && type == other.type && seamlessness == other.seamlessness; + return rate.equalsWithMargin(other.rate) && type == other.type && + seamlessness == other.seamlessness; } bool operator!=(const FrameRate& other) const { return !(*this == other); } @@ -177,8 +179,8 @@ public: static FrameRateCompatibility convertCompatibility(int8_t compatibility); private: - static Seamlessness getSeamlessness(float rate, bool shouldBeSeamless) { - if (rate == 0.0f) { + static Seamlessness getSeamlessness(Fps rate, bool shouldBeSeamless) { + if (!rate.isValid()) { // Refresh rate of 0 is a special value which should reset the vote to // its default value. return Seamlessness::Default; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index f676d5b44b..f99d54ac53 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -190,7 +190,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setFrameRate(Layer::FrameRate(0, Layer::FrameRateCompatibility::NoVote)); + mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); @@ -205,7 +205,7 @@ bool RefreshRateOverlay::createLayer() { void RefreshRateOverlay::primeCache() { auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); if (allRefreshRates.size() == 1) { - auto fps = allRefreshRates.begin()->second->getFps(); + int fps = allRefreshRates.begin()->second->getFps().getIntValue(); half4 color = {LOW_FPS_COLOR, ALPHA}; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); return; @@ -214,7 +214,7 @@ void RefreshRateOverlay::primeCache() { std::vector supportedFps; supportedFps.reserve(allRefreshRates.size()); for (auto& [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate->getFps()); + supportedFps.push_back(refreshRate->getFps().getIntValue()); } std::sort(supportedFps.begin(), supportedFps.end()); @@ -240,7 +240,7 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { } void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - mCurrentFps = refreshRate.getFps(); + mCurrentFps = refreshRate.getFps().getIntValue(); auto buffer = mBufferCache[*mCurrentFps][mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index c0d00f3369..499daad031 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -41,7 +41,7 @@ namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { // Layers with an explicit vote are always kept active - if (layer.getFrameRateForLayerTree().rate > 0) { + if (layer.getFrameRateForLayerTree().rate.isValid()) { return true; } @@ -86,9 +86,8 @@ LayerHistory::LayerHistory(const RefreshRateConfigs& refreshRateConfigs) LayerHistory::~LayerHistory() = default; -void LayerHistory::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate, - LayerVoteType type) { - const nsecs_t highRefreshRatePeriod = static_cast(1e9f / highRefreshRate); +void LayerHistory::registerLayer(Layer* layer, Fps highRefreshRate, LayerVoteType type) { + const nsecs_t highRefreshRatePeriod = highRefreshRate.getPeriodNsecs(); auto info = std::make_unique(layer->getName(), highRefreshRatePeriod, type); std::lock_guard lock(mLock); mLayerInfos.emplace_back(layer, std::move(info)); @@ -148,7 +147,7 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { {strong->getName(), vote.type, vote.fps, vote.seamlessness, weight, layerFocused}); if (CC_UNLIKELY(mTraceEnabled)) { - trace(layer, *info, vote.type, static_cast(std::round(vote.fps))); + trace(layer, *info, vote.type, vote.fps.getIntValue()); } } @@ -177,7 +176,7 @@ void LayerHistory::partitionLayers(nsecs_t now) { } }(); - if (frameRate.rate > 0 || voteType == LayerVoteType::NoVote) { + if (frameRate.rate.isValid() || voteType == LayerVoteType::NoVote) { const auto type = layer->isVisible() ? voteType : LayerVoteType::NoVote; info->setLayerVote({type, frameRate.rate, frameRate.seamlessness}); } else { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 507ccc6b11..4214bab8ff 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -46,7 +46,7 @@ public: ~LayerHistory(); // Layers are unregistered when the weak reference expires. - void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, LayerVoteType type); + void registerLayer(Layer*, Fps highRefreshRate, LayerVoteType type); // Sets the display size. Client is responsible for synchronization. void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 66ac98adbf..1c0065c9ad 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -38,7 +38,7 @@ LayerInfo::LayerInfo(const std::string& name, nsecs_t highRefreshRatePeriod, : mName(name), mHighRefreshRatePeriod(highRefreshRatePeriod), mDefaultVote(defaultVote), - mLayerVote({defaultVote, 0.0f}), + mLayerVote({defaultVote, Fps(0.0f)}), mRefreshRateHistory(name) {} void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType, @@ -91,7 +91,8 @@ bool LayerInfo::isFrequent(nsecs_t now) const { // Layer is considered frequent if the average frame rate is higher than the threshold const auto totalTime = mFrameTimes.back().queueTime - it->queueTime; - return (1e9f * (numFrames - 1)) / totalTime >= MIN_FPS_FOR_FREQUENT_LAYER; + return Fps::fromPeriodNsecs(totalTime / (numFrames - 1)) + .greaterThanOrEqualWithMargin(MIN_FPS_FOR_FREQUENT_LAYER); } bool LayerInfo::isAnimating(nsecs_t now) const { @@ -139,7 +140,7 @@ std::optional LayerInfo::calculateAverageFrameTime() const { missingPresentTime = true; // If there are no presentation timestamps and we haven't calculated // one in the past then we can't calculate the refresh rate - if (mLastRefreshRate.reported == 0) { + if (!mLastRefreshRate.reported.isValid()) { return std::nullopt; } continue; @@ -163,7 +164,7 @@ std::optional LayerInfo::calculateAverageFrameTime() const { return static_cast(averageFrameTime); } -std::optional LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { +std::optional LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { static constexpr float MARGIN = 1.0f; // 1Hz if (!hasEnoughDataForHeuristic()) { ALOGV("Not enough data"); @@ -172,7 +173,7 @@ std::optional LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { const auto averageFrameTime = calculateAverageFrameTime(); if (averageFrameTime.has_value()) { - const auto refreshRate = 1e9f / *averageFrameTime; + const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime); const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now); if (refreshRateConsistent) { const auto knownRefreshRate = @@ -180,22 +181,23 @@ std::optional LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) { // To avoid oscillation, use the last calculated refresh rate if it is // close enough - if (std::abs(mLastRefreshRate.calculated - refreshRate) > MARGIN && - mLastRefreshRate.reported != knownRefreshRate) { + if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) > + MARGIN && + !mLastRefreshRate.reported.equalsWithMargin(knownRefreshRate)) { mLastRefreshRate.calculated = refreshRate; mLastRefreshRate.reported = knownRefreshRate; } - ALOGV("%s %.2fHz rounded to nearest known frame rate %.2fHz", mName.c_str(), - refreshRate, mLastRefreshRate.reported); + ALOGV("%s %s rounded to nearest known frame rate %s", mName.c_str(), + to_string(refreshRate).c_str(), to_string(mLastRefreshRate.reported).c_str()); } else { - ALOGV("%s Not stable (%.2fHz) returning last known frame rate %.2fHz", mName.c_str(), - refreshRate, mLastRefreshRate.reported); + ALOGV("%s Not stable (%s) returning last known frame rate %s", mName.c_str(), + to_string(refreshRate).c_str(), to_string(mLastRefreshRate.reported).c_str()); } } - return mLastRefreshRate.reported == 0 ? std::nullopt - : std::make_optional(mLastRefreshRate.reported); + return mLastRefreshRate.reported.isValid() ? std::make_optional(mLastRefreshRate.reported) + : std::nullopt; } LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { @@ -207,13 +209,13 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { if (isAnimating(now)) { ALOGV("%s is animating", mName.c_str()); mLastRefreshRate.animatingOrInfrequent = true; - return {LayerHistory::LayerVoteType::Max, 0}; + return {LayerHistory::LayerVoteType::Max, Fps(0.0f)}; } if (!isFrequent(now)) { ALOGV("%s is infrequent", mName.c_str()); mLastRefreshRate.animatingOrInfrequent = true; - return {LayerHistory::LayerVoteType::Min, 0}; + return {LayerHistory::LayerVoteType::Min, Fps(0.0f)}; } // If the layer was previously tagged as animating or infrequent, we clear @@ -225,12 +227,12 @@ LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) { auto refreshRate = calculateRefreshRateIfPossible(now); if (refreshRate.has_value()) { - ALOGV("%s calculated refresh rate: %.2f", mName.c_str(), refreshRate.value()); + ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str()); return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; } ALOGV("%s Max (can't resolve refresh rate)", mName.c_str()); - return {LayerHistory::LayerVoteType::Max, 0}; + return {LayerHistory::LayerVoteType::Max, Fps(0.0f)}; } const char* LayerInfo::getTraceTag(android::scheduler::LayerHistory::LayerVoteType type) const { @@ -256,7 +258,7 @@ void LayerInfo::RefreshRateHistory::clear() { mRefreshRates.clear(); } -bool LayerInfo::RefreshRateHistory::add(float refreshRate, nsecs_t now) { +bool LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now) { mRefreshRates.push_back({refreshRate, now}); while (mRefreshRates.size() >= HISTORY_SIZE || now - mRefreshRates.front().timestamp > HISTORY_DURATION.count()) { @@ -268,7 +270,7 @@ bool LayerInfo::RefreshRateHistory::add(float refreshRate, nsecs_t now) { mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->average.c_str(), static_cast(refreshRate)); + ATRACE_INT(mHeuristicTraceTagData->average.c_str(), refreshRate.getIntValue()); } return isConsistent(); @@ -279,15 +281,16 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const { const auto max = std::max_element(mRefreshRates.begin(), mRefreshRates.end()); const auto min = std::min_element(mRefreshRates.begin(), mRefreshRates.end()); - const auto consistent = max->refreshRate - min->refreshRate <= MARGIN_FPS; + const auto consistent = + max->refreshRate.getValue() - min->refreshRate.getValue() < MARGIN_CONSISTENT_FPS; if (CC_UNLIKELY(sTraceEnabled)) { if (!mHeuristicTraceTagData.has_value()) { mHeuristicTraceTagData = makeHeuristicTraceTagData(); } - ATRACE_INT(mHeuristicTraceTagData->max.c_str(), static_cast(max->refreshRate)); - ATRACE_INT(mHeuristicTraceTagData->min.c_str(), static_cast(min->refreshRate)); + ATRACE_INT(mHeuristicTraceTagData->max.c_str(), max->refreshRate.getIntValue()); + ATRACE_INT(mHeuristicTraceTagData->min.c_str(), min->refreshRate.getIntValue()); ATRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent); } diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index e43467062f..9304e62765 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -50,9 +50,9 @@ class LayerInfo { // 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 float MIN_FPS_FOR_FREQUENT_LAYER = 10.0f; + static constexpr Fps MIN_FPS_FOR_FREQUENT_LAYER{10.0f}; static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = - std::chrono::nanoseconds(static_cast(1e9f / MIN_FPS_FOR_FREQUENT_LAYER)) + 1ms; + std::chrono::nanoseconds(MIN_FPS_FOR_FREQUENT_LAYER.getPeriodNsecs()) + 1ms; friend class LayerHistoryTest; @@ -60,7 +60,7 @@ public: // Holds information about the layer vote struct LayerVote { LayerHistory::LayerVoteType type = LayerHistory::LayerVoteType::Heuristic; - float fps = 0.0f; + Fps fps{0.0f}; Seamlessness seamlessness = Seamlessness::Default; }; @@ -92,7 +92,7 @@ public: void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } // Resets the layer vote to its default. - void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f, Seamlessness::Default}; } + void resetLayerVote() { mLayerVote = {mDefaultVote, Fps(0.0f), Seamlessness::Default}; } LayerVote getRefreshRateVote(nsecs_t now); @@ -130,9 +130,9 @@ private: // Holds information about the calculated and reported refresh rate struct RefreshRateHeuristicData { // Rate calculated on the layer - float calculated = 0.0f; + Fps calculated{0.0f}; // Last reported rate for LayerInfo::getRefreshRate() - float reported = 0.0f; + Fps reported{0.0f}; // Whether the last reported rate for LayerInfo::getRefreshRate() // was due to animation or infrequent updates bool animatingOrInfrequent = false; @@ -151,18 +151,20 @@ private: void clear(); // Adds a new refresh rate and returns true if it is consistent - bool add(float refreshRate, nsecs_t now); + bool add(Fps refreshRate, nsecs_t now); private: friend class LayerHistoryTest; // Holds the refresh rate when it was calculated struct RefreshRateData { - float refreshRate = 0.0f; + Fps refreshRate{0.0f}; nsecs_t timestamp = 0; bool operator<(const RefreshRateData& other) const { - return refreshRate < other.refreshRate; + // We don't need comparison with margins since we are using + // this to find the min and max refresh rates. + return refreshRate.getValue() < other.refreshRate.getValue(); } }; @@ -180,13 +182,13 @@ private: const std::string mName; mutable std::optional mHeuristicTraceTagData; std::deque mRefreshRates; - static constexpr float MARGIN_FPS = 1.0; + static constexpr float MARGIN_CONSISTENT_FPS = 1.0; }; bool isFrequent(nsecs_t now) const; bool isAnimating(nsecs_t now) const; bool hasEnoughDataForHeuristic() const; - std::optional calculateRefreshRateIfPossible(nsecs_t now); + std::optional calculateRefreshRateIfPossible(nsecs_t now); std::optional calculateAverageFrameTime() const; bool isFrameTimeValid(const FrameTimeData&) const; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 83fa20ef34..4b7251b989 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -29,10 +29,10 @@ namespace android::scheduler { namespace { std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) { - return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %.2fHz", - layer.name.c_str(), + return base::StringPrintf("%s (type=%s, weight=%.2f seamlessness=%s) %s", layer.name.c_str(), RefreshRateConfigs::layerVoteTypeString(layer.vote).c_str(), weight, - toString(layer.seamlessness).c_str(), layer.desiredRefreshRate); + toString(layer.seamlessness).c_str(), + to_string(layer.desiredRefreshRate).c_str()); } } // namespace @@ -41,7 +41,7 @@ using RefreshRate = RefreshRateConfigs::RefreshRate; std::string RefreshRate::toString() const { return base::StringPrintf("{id=%d, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}", - getConfigId().value(), hwcConfig->getId(), getFps(), + getConfigId().value(), hwcConfig->getId(), getFps().getValue(), hwcConfig->getWidth(), hwcConfig->getHeight(), getConfigGroup()); } @@ -64,9 +64,9 @@ std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) { std::string RefreshRateConfigs::Policy::toString() const { return base::StringPrintf("default config ID: %d, allowGroupSwitching = %d" - ", primary range: [%.2f %.2f], app request range: [%.2f %.2f]", - defaultConfig.value(), allowGroupSwitching, primaryRange.min, - primaryRange.max, appRequestRange.min, appRequestRange.max); + ", primary range: %s, app request range: %s", + defaultConfig.value(), allowGroupSwitching, + primaryRange.toString().c_str(), appRequestRange.toString().c_str()); } std::pair RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod, @@ -144,7 +144,8 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( // move out the of range if layers explicitly request a different refresh // rate. const Policy* policy = getCurrentPolicyLocked(); - const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max; + const bool primaryRangeIsSingleRate = + policy->primaryRange.min.equalsWithMargin(policy->primaryRange.max); if (!globalSignals.touch && globalSignals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) { @@ -229,17 +230,18 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( // If the layer wants Max, give higher score to the higher refresh rate if (layer.vote == LayerVoteType::Max) { - const auto ratio = scores[i].first->fps / scores.back().first->fps; + const auto ratio = + scores[i].first->fps.getValue() / scores.back().first->fps.getValue(); // use ratio^2 to get a lower score the more we get further from peak const auto layerScore = ratio * ratio; ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore; continue; } const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod(); - const auto layerPeriod = round(1e9f / layer.desiredRefreshRate); + const auto layerPeriod = layer.desiredRefreshRate.getPeriodNsecs(); if (layer.vote == LayerVoteType::ExplicitDefault) { const auto layerScore = [&]() { // Find the actual rate the layer will render, assuming @@ -256,7 +258,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( }(); ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore; continue; } @@ -297,7 +299,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( constexpr float kSeamedSwitchPenalty = 0.95f; const float seamlessness = isSeamlessSwitch ? 1.0f : kSeamedSwitchPenalty; ALOGV("%s gives %s score of %.2f", formatLayerInfo(layer, weight).c_str(), - scores[i].first->name.c_str(), layerScore); + scores[i].first->getName().c_str(), layerScore); scores[i].second += weight * layerScore * seamlessness; continue; } @@ -331,7 +333,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(); if (globalSignals.touch && explicitDefaultVoteLayers == 0 && - bestRefreshRate->fps < touchRefreshRate.fps) { + bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) { setTouchConsidered(); ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str()); return touchRefreshRate; @@ -347,9 +349,9 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) float max = begin->second; for (auto i = begin; i != end; ++i) { const auto [refreshRate, score] = *i; - ALOGV("%s scores %.2f", refreshRate->name.c_str(), score); + ALOGV("%s scores %.2f", refreshRate->getName().c_str(), score); - ATRACE_INT(refreshRate->name.c_str(), round(score * 100)); + ATRACE_INT(refreshRate->getName().c_str(), round(score * 100)); if (score > max * (1 + EPSILON)) { max = score; @@ -433,10 +435,10 @@ RefreshRateConfigs::RefreshRateConfigs( for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast(configId.value())); - const float fps = 1e9f / config->getVsyncPeriod(); mRefreshRates.emplace(configId, std::make_unique(configId, config, - base::StringPrintf("%.2ffps", fps), fps, + Fps::fromPeriodNsecs( + config->getVsyncPeriod()), RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); @@ -463,8 +465,8 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { ALOGE("Default config is not in the primary range."); return false; } - return policy.appRequestRange.min <= policy.primaryRange.min && - policy.appRequestRange.max >= policy.primaryRange.max; + return policy.appRequestRange.min.lessThanOrEqualWithMargin(policy.primaryRange.min) && + policy.appRequestRange.max.greaterThanOrEqualWithMargin(policy.primaryRange.max); } status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { @@ -550,12 +552,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period const Policy* policy = getCurrentPolicyLocked(); const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig; - ALOGV("constructAvailableRefreshRates: default %d group %d primaryRange=[%.2f %.2f]" - " appRequestRange=[%.2f %.2f]", - policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->primaryRange.min, - policy->primaryRange.max, policy->appRequestRange.min, policy->appRequestRange.max); + ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); - auto filterRefreshRates = [&](float min, float max, const char* listName, + auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, std::vector* outRefreshRates) { getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { @@ -572,12 +571,12 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { outRefreshRates); LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(), - "No matching configs for %s range: min=%.0f max=%.0f", listName, min, - max); + "No matching configs for %s range: min=%s max=%s", listName, + to_string(min).c_str(), to_string(max).c_str()); auto stringifyRefreshRates = [&]() -> std::string { std::string str; for (auto refreshRate : *outRefreshRates) { - base::StringAppendF(&str, "%s ", refreshRate->name.c_str()); + base::StringAppendF(&str, "%s ", refreshRate->getName().c_str()); } return str; }; @@ -590,39 +589,39 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { &mAppRequestRefreshRates); } -std::vector RefreshRateConfigs::constructKnownFrameRates( +std::vector RefreshRateConfigs::constructKnownFrameRates( const std::vector>& configs) { - std::vector knownFrameRates = {24.0f, 30.0f, 45.0f, 60.0f, 72.0f}; + std::vector knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; knownFrameRates.reserve(knownFrameRates.size() + configs.size()); // Add all supported refresh rates to the set for (const auto& config : configs) { - const auto refreshRate = 1e9f / config->getVsyncPeriod(); + const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); knownFrameRates.emplace_back(refreshRate); } // Sort and remove duplicates - const auto frameRatesEqual = [](float a, float b) { return std::abs(a - b) <= 0.01f; }; - std::sort(knownFrameRates.begin(), knownFrameRates.end()); + std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), - frameRatesEqual), + Fps::EqualsWithMargin()), knownFrameRates.end()); return knownFrameRates; } -float RefreshRateConfigs::findClosestKnownFrameRate(float frameRate) const { - if (frameRate <= *mKnownFrameRates.begin()) { +Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { + if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) { return *mKnownFrameRates.begin(); } - if (frameRate >= *std::prev(mKnownFrameRates.end())) { + if (frameRate.greaterThanOrEqualWithMargin(*std::prev(mKnownFrameRates.end()))) { return *std::prev(mKnownFrameRates.end()); } - auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate); + auto lowerBound = std::lower_bound(mKnownFrameRates.begin(), mKnownFrameRates.end(), frameRate, + Fps::comparesLess); - const auto distance1 = std::abs(frameRate - *lowerBound); - const auto distance2 = std::abs(frameRate - *std::prev(lowerBound)); + const auto distance1 = std::abs((frameRate.getValue() - lowerBound->getValue())); + const auto distance2 = std::abs((frameRate.getValue() - std::prev(lowerBound)->getValue())); return distance1 < distance2 ? *lowerBound : *std::prev(lowerBound); } @@ -657,7 +656,7 @@ void RefreshRateConfigs::setPreferredRefreshRateForUid(FrameRateOverride frameRa std::lock_guard lock(mLock); if (frameRateOverride.frameRateHz != 0) { - mPreferredRefreshRateForUid[frameRateOverride.uid] = frameRateOverride.frameRateHz; + mPreferredRefreshRateForUid[frameRateOverride.uid] = Fps(frameRateOverride.frameRateHz); } else { mPreferredRefreshRateForUid.erase(frameRateOverride.uid); } @@ -675,7 +674,7 @@ int RefreshRateConfigs::getRefreshRateDividerForUid(uid_t uid) const { // in DisplayManagerService.getDisplayInfoForFrameRateOverride constexpr float kThreshold = 0.1f; const auto refreshRateHz = iter->second; - const auto numPeriods = mCurrentRefreshRate->getFps() / refreshRateHz; + const auto numPeriods = mCurrentRefreshRate->getFps().getValue() / refreshRateHz.getValue(); const auto numPeriodsRounded = std::round(numPeriods); if (std::abs(numPeriods - numPeriodsRounded) > kThreshold) { return 1; @@ -690,7 +689,7 @@ std::vector RefreshRateConfigs::getFrameRateOverrides() { overrides.reserve(mPreferredRefreshRateForUid.size()); for (const auto [uid, frameRate] : mPreferredRefreshRateForUid) { - overrides.emplace_back(FrameRateOverride{uid, frameRate}); + overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()}); } return overrides; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 6e0c0d3897..ec7ffe5b30 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -25,6 +25,7 @@ #include #include "DisplayHardware/HWComposer.h" +#include "Fps.h" #include "HwcStrongTypes.h" #include "Scheduler/SchedulerUtils.h" #include "Scheduler/Seamlessness.h" @@ -64,29 +65,31 @@ public: public: RefreshRate(HwcConfigIndexType configId, - std::shared_ptr config, std::string name, - float fps, ConstructorTag) - : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {} + std::shared_ptr config, Fps fps, ConstructorTag) + : configId(configId), hwcConfig(config), fps(std::move(fps)) {} RefreshRate(const RefreshRate&) = delete; HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } - const std::string& getName() const { return name; } - float getFps() const { return fps; } + std::string getName() const { return to_string(fps); } + Fps getFps() const { return fps; } // Checks whether the fps of this RefreshRate struct is within a given min and max refresh - // rate passed in. FPS_EPSILON is applied to the boundaries for approximation. - bool inPolicy(float minRefreshRate, float maxRefreshRate) const { - return (fps >= (minRefreshRate - FPS_EPSILON) && fps <= (maxRefreshRate + FPS_EPSILON)); + // rate passed in. Margin of error is applied to the boundaries for approximation. + bool inPolicy(Fps minRefreshRate, Fps maxRefreshRate) const { + return minRefreshRate.lessThanOrEqualWithMargin(fps) && + fps.lessThanOrEqualWithMargin(maxRefreshRate); } bool operator!=(const RefreshRate& other) const { return configId != other.configId || hwcConfig != other.hwcConfig; } - bool operator<(const RefreshRate& other) const { return getFps() < other.getFps(); } + bool operator<(const RefreshRate& other) const { + return getFps().getValue() < other.getFps().getValue(); + } bool operator==(const RefreshRate& other) const { return !(*this != other); } @@ -96,18 +99,13 @@ public: friend RefreshRateConfigs; friend class RefreshRateConfigsTest; - // The tolerance within which we consider FPS approximately equals. - static constexpr float FPS_EPSILON = 0.001f; - // This config ID corresponds to the position of the config in the vector that is stored // on the device. const HwcConfigIndexType configId; // The config itself std::shared_ptr hwcConfig; - // Human readable name of the refresh rate. - const std::string name; // Refresh rate in frames per second - const float fps = 0; + const Fps fps{0.0f}; }; using AllRefreshRatesMapType = @@ -119,14 +117,19 @@ public: public: struct Range { - float min = 0; - float max = std::numeric_limits::max(); + Fps min{0.0f}; + Fps max{std::numeric_limits::max()}; bool operator==(const Range& other) const { - return min == other.min && max == other.max; + return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); } bool operator!=(const Range& other) const { return !(*this == other); } + + std::string toString() const { + return base::StringPrintf("[%s %s]", to_string(min).c_str(), + to_string(max).c_str()); + } }; // The default config, used to ensure we only initiate display config switches within the @@ -221,7 +224,7 @@ public: // Layer vote type. LayerVoteType vote = LayerVoteType::NoVote; // Layer's desired refresh rate, if applicable. - float desiredRefreshRate = 0.0f; + Fps desiredRefreshRate{0.0f}; // If a seamless mode switch is required. Seamlessness seamlessness = Seamlessness::Default; // Layer's weight in the range of [0, 1]. The higher the weight the more impact this layer @@ -232,7 +235,7 @@ public: bool operator==(const LayerRequirement& other) const { return name == other.name && vote == other.vote && - desiredRefreshRate == other.desiredRefreshRate && + desiredRefreshRate.equalsWithMargin(other.desiredRefreshRate) && seamlessness == other.seamlessness && weight == other.weight && focused == other.focused; } @@ -295,7 +298,7 @@ public: static std::string layerVoteTypeString(LayerVoteType vote); // Returns a known frame rate that is the closest to frameRate - float findClosestKnownFrameRate(float frameRate) const; + Fps findClosestKnownFrameRate(Fps frameRate) const; RefreshRateConfigs(const std::vector>& configs, HwcConfigIndexType currentConfigId); @@ -332,7 +335,7 @@ private: friend class RefreshRateConfigsTest; void constructAvailableRefreshRates() REQUIRES(mLock); - static std::vector constructKnownFrameRates( + static std::vector constructKnownFrameRates( const std::vector>& configs); void getSortedRefreshRateList( @@ -387,7 +390,7 @@ private: // A mapping between a UID and a preferred refresh rate that this app would // run at. - std::unordered_map mPreferredRefreshRateForUid GUARDED_BY(mLock); + std::unordered_map mPreferredRefreshRateForUid GUARDED_BY(mLock); // The min and max refresh rates supported by the device. // This will not change at runtime. @@ -398,7 +401,7 @@ private: // A sorted list of known frame rates that a Heuristic layer will choose // from based on the closest value. - const std::vector mKnownFrameRates; + const std::vector mKnownFrameRates; }; } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index d9e7b371ff..ce91a760fb 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -115,8 +115,10 @@ private: mConfigModesTotalTime[mCurrentConfigMode] = 0; } mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs; - fps = static_cast(std::round( - mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).getFps())); + fps = static_cast( + std::round(mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode) + .getFps() + .getValue())); } else { mScreenOffTime += timeElapsedMs; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 52bf483fdd..07411b08d0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -510,25 +510,22 @@ void Scheduler::setIgnorePresentFences(bool ignore) { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps(); if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) { - mLayerHistory->registerLayer(layer, minFps, maxFps, - scheduler::LayerHistory::LayerVoteType::NoVote); + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::NoVote); } else if (!mOptions.useContentDetection) { // If the content detection feature is off, all layers are registered at Max. We still keep // the layer history, since we use it for other features (like Frame Rate API), so layers // still need to be registered. - mLayerHistory->registerLayer(layer, minFps, maxFps, - scheduler::LayerHistory::LayerVoteType::Max); + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Max); } else { if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. - mLayerHistory->registerLayer(layer, minFps, maxFps, + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Min); } else { - mLayerHistory->registerLayer(layer, minFps, maxFps, + mLayerHistory->registerLayer(layer, maxFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } } @@ -618,14 +615,15 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) { // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate // magic number const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); - constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; - if (state == TimerState::Reset && refreshRate.getFps() > FPS_THRESHOLD_FOR_KERNEL_TIMER) { + constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER{65.0f}; + if (state == TimerState::Reset && + refreshRate.getFps().greaterThanWithMargin(FPS_THRESHOLD_FOR_KERNEL_TIMER)) { // If we're not in performance mode then the kernel timer shouldn't do // anything, as the refresh rate during DPU power collapse will be the // same. resyncToHardwareVsync(true /* makeAvailable */, refreshRate.getVsyncPeriod()); } else if (state == TimerState::Expired && - refreshRate.getFps() <= FPS_THRESHOLD_FOR_KERNEL_TIMER) { + refreshRate.getFps().lessThanOrEqualWithMargin(FPS_THRESHOLD_FOR_KERNEL_TIMER)) { // Disable HW VSYNC if the timer expired, as we don't need it enabled if // we're not pushing frames, and if we're in PERFORMANCE mode then we'll // need to update the VsyncController model anyway. diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp index aac2569044..8431323888 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.cpp @@ -31,15 +31,10 @@ std::optional getProperty(const char* name) { return std::nullopt; } -bool fpsEqualsWithMargin(float fpsA, float fpsB) { - static constexpr float MARGIN = 0.01f; - return std::abs(fpsA - fpsB) <= MARGIN; -} - -std::vector getRefreshRatesFromConfigs( +std::vector getRefreshRatesFromConfigs( const android::scheduler::RefreshRateConfigs& refreshRateConfigs) { const auto& allRefreshRates = refreshRateConfigs.getAllRefreshRates(); - std::vector refreshRates; + std::vector refreshRates; refreshRates.reserve(allRefreshRates.size()); for (const auto& [ignored, refreshRate] : allRefreshRates) { @@ -53,12 +48,12 @@ std::vector getRefreshRatesFromConfigs( namespace android::scheduler::impl { -VsyncConfiguration::VsyncConfiguration(float currentFps) : mRefreshRateFps(currentFps) {} +VsyncConfiguration::VsyncConfiguration(Fps currentFps) : mRefreshRateFps(currentFps) {} -PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(float fps) const { +PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(Fps fps) const { const auto iter = std::find_if(mOffsets.begin(), mOffsets.end(), - [&fps](const std::pair& candidateFps) { - return fpsEqualsWithMargin(fps, candidateFps.first); + [&fps](const std::pair& candidateFps) { + return fps.equalsWithMargin(candidateFps.first); }); if (iter != mOffsets.end()) { @@ -67,13 +62,13 @@ PhaseOffsets::VsyncConfigSet VsyncConfiguration::getConfigsForRefreshRate(float // Unknown refresh rate. This might happen if we get a hotplug event for an external display. // In this case just construct the offset. - ALOGW("Can't find offset for %.2f fps", fps); - return constructOffsets(static_cast(1e9f / fps)); + ALOGW("Can't find offset for %s", to_string(fps).c_str()); + return constructOffsets(fps.getPeriodNsecs()); } -void VsyncConfiguration::initializeOffsets(const std::vector& refreshRates) { +void VsyncConfiguration::initializeOffsets(const std::vector& refreshRates) { for (const auto fps : refreshRates) { - mOffsets.emplace(fps, constructOffsets(static_cast(1e9f / fps))); + mOffsets.emplace(fps, constructOffsets(fps.getPeriodNsecs())); } } @@ -127,7 +122,7 @@ PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfi .value_or(std::numeric_limits::max())) {} PhaseOffsets::PhaseOffsets( - const std::vector& refreshRates, float currentFps, nsecs_t vsyncPhaseOffsetNs, + const std::vector& refreshRates, Fps currentFps, nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, std::optional earlySfOffsetNs, std::optional earlyGpuSfOffsetNs, std::optional earlyAppOffsetNs, std::optional earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs, @@ -378,10 +373,9 @@ WorkDuration::WorkDuration(const scheduler::RefreshRateConfigs& refreshRateConfi validateSysprops(); } -WorkDuration::WorkDuration(const std::vector& refreshRates, float currentFps, - nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, - nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, - nsecs_t appEarlyGpuDuration) +WorkDuration::WorkDuration(const std::vector& refreshRates, Fps currentFps, nsecs_t sfDuration, + nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, + nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration) : VsyncConfiguration(currentFps), mSfDuration(sfDuration), mAppDuration(appDuration), diff --git a/services/surfaceflinger/Scheduler/VsyncConfiguration.h b/services/surfaceflinger/Scheduler/VsyncConfiguration.h index c27a25d738..a120e976f0 100644 --- a/services/surfaceflinger/Scheduler/VsyncConfiguration.h +++ b/services/surfaceflinger/Scheduler/VsyncConfiguration.h @@ -18,6 +18,9 @@ #include +#include + +#include "Fps.h" #include "RefreshRateConfigs.h" #include "VsyncModulator.h" @@ -35,9 +38,9 @@ public: virtual ~VsyncConfiguration() = default; virtual VsyncConfigSet getCurrentConfigs() const = 0; - virtual VsyncConfigSet getConfigsForRefreshRate(float fps) const = 0; + virtual VsyncConfigSet getConfigsForRefreshRate(Fps fps) const = 0; - virtual void setRefreshRateFps(float fps) = 0; + virtual void setRefreshRateFps(Fps fps) = 0; virtual void dump(std::string& result) const = 0; }; @@ -51,10 +54,10 @@ namespace impl { */ class VsyncConfiguration : public scheduler::VsyncConfiguration { public: - explicit VsyncConfiguration(float currentFps); + explicit VsyncConfiguration(Fps currentFps); // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate. - VsyncConfigSet getConfigsForRefreshRate(float fps) const override; + VsyncConfigSet getConfigsForRefreshRate(Fps fps) const override; // Returns early, early GL, and late offsets for Apps and SF. VsyncConfigSet getCurrentConfigs() const override { @@ -63,17 +66,17 @@ public: // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. - void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; } + void setRefreshRateFps(Fps fps) override { mRefreshRateFps = fps; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; protected: - void initializeOffsets(const std::vector& refreshRates); + void initializeOffsets(const std::vector& refreshRates); virtual VsyncConfiguration::VsyncConfigSet constructOffsets(nsecs_t vsyncDuration) const = 0; - std::unordered_map mOffsets; - std::atomic mRefreshRateFps; + std::unordered_map, Fps::EqualsInBuckets> mOffsets; + std::atomic mRefreshRateFps; }; /* @@ -86,10 +89,9 @@ public: protected: // Used for unit tests - PhaseOffsets(const std::vector& refreshRates, float currentFps, - nsecs_t vsyncPhaseOffsetNs, nsecs_t sfVSyncPhaseOffsetNs, - std::optional earlySfOffsetNs, std::optional earlyGpuSfOffsetNs, - std::optional earlyAppOffsetNs, + PhaseOffsets(const std::vector& refreshRates, Fps currentFps, nsecs_t vsyncPhaseOffsetNs, + nsecs_t sfVSyncPhaseOffsetNs, std::optional earlySfOffsetNs, + std::optional earlyGpuSfOffsetNs, std::optional earlyAppOffsetNs, std::optional earlyGpuAppOffsetNs, nsecs_t highFpsVsyncPhaseOffsetNs, nsecs_t highFpsSfVSyncPhaseOffsetNs, std::optional highFpsEarlySfOffsetNs, std::optional highFpsEarlyGpuSfOffsetNs, @@ -130,7 +132,7 @@ public: protected: // Used for unit tests - WorkDuration(const std::vector& refreshRates, float currentFps, nsecs_t sfDuration, + WorkDuration(const std::vector& refreshRates, Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, nsecs_t sfEarlyGpuDuration, nsecs_t appEarlyGpuDuration); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 95c99829ca..39f73910b7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -921,10 +921,10 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, } const nsecs_t period = hwConfig->getVsyncPeriod(); - config.refreshRate = 1e9f / period; + config.refreshRate = Fps::fromPeriodNsecs(period).getValue(); const auto vsyncConfigSet = - mVsyncConfiguration->getConfigsForRefreshRate(config.refreshRate); + mVsyncConfiguration->getConfigsForRefreshRate(Fps(config.refreshRate)); config.appVsyncOffset = vsyncConfigSet.late.appOffset; config.sfVsyncOffset = vsyncConfigSet.late.sfOffset; config.configGroup = hwConfig->getConfigGroup(); @@ -1042,7 +1042,7 @@ status_t SurfaceFlinger::setActiveConfig(const sp& displayToken, int mo return INVALID_OPERATION; } else { const HwcConfigIndexType config(mode); - const float fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); + const auto fps = mRefreshRateConfigs->getRefreshRateFromConfigId(config).getFps(); // Keep the old switching type. const auto allowGroupSwitching = mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching; @@ -1080,7 +1080,7 @@ void SurfaceFlinger::setActiveConfigInternal() { mTimeStats->incrementRefreshRateSwitches(); } updatePhaseConfiguration(refreshRate); - ATRACE_INT("ActiveConfigFPS", refreshRate.getFps()); + ATRACE_INT("ActiveConfigFPS", refreshRate.getFps().getValue()); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { const nsecs_t vsyncPeriod = @@ -1138,7 +1138,7 @@ void SurfaceFlinger::performSetActiveConfig() { mUpcomingActiveConfig = *desiredActiveConfig; const auto displayId = display->getPhysicalId(); - ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps()); + ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getFps().getValue()); // TODO(b/142753666) use constrains hal::VsyncPeriodChangeConstraints constraints; @@ -3775,7 +3775,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eFrameRateChanged) { if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility, "SurfaceFlinger::setClientStateLocked") && - layer->setFrameRate(Layer::FrameRate(s.frameRate, + layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate), Layer::FrameRate::convertCompatibility( s.frameRateCompatibility), s.shouldBeSeamless))) { @@ -4708,8 +4708,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co const auto activeConfig = getHwComposer().getActiveConfig(*displayId); std::string fps, xDpi, yDpi; if (activeConfig) { - fps = base::StringPrintf("%.2f Hz", - 1e9f / getHwComposer().getDisplayVsyncPeriod(*displayId)); + const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId); + fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str()); xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX()); yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY()); } else { @@ -5965,11 +5965,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( } scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy(); - ALOGV("Setting desired display config specs: defaultConfig: %d primaryRange: [%.0f %.0f]" - " expandedRange: [%.0f %.0f]", - currentPolicy.defaultConfig.value(), currentPolicy.primaryRange.min, - currentPolicy.primaryRange.max, currentPolicy.appRequestRange.min, - currentPolicy.appRequestRange.max); + ALOGV("Setting desired display config specs: %s", currentPolicy.toString().c_str()); // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might // be depending in this callback. @@ -6025,8 +6021,8 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecs( using Policy = scheduler::RefreshRateConfigs::Policy; const Policy policy{HwcConfigIndexType(defaultConfig), allowGroupSwitching, - {primaryRefreshRateMin, primaryRefreshRateMax}, - {appRequestRefreshRateMin, appRequestRefreshRateMax}}; + {Fps(primaryRefreshRateMin), Fps(primaryRefreshRateMax)}, + {Fps(appRequestRefreshRateMin), Fps(appRequestRefreshRateMax)}}; constexpr bool kOverridePolicy = false; return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy); @@ -6058,10 +6054,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( mRefreshRateConfigs->getDisplayManagerPolicy(); *outDefaultConfig = policy.defaultConfig.value(); *outAllowGroupSwitching = policy.allowGroupSwitching; - *outPrimaryRefreshRateMin = policy.primaryRange.min; - *outPrimaryRefreshRateMax = policy.primaryRange.max; - *outAppRequestRefreshRateMin = policy.appRequestRange.min; - *outAppRequestRefreshRateMax = policy.appRequestRange.max; + *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue(); + *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue(); + *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue(); + *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue(); return NO_ERROR; } else if (display->isVirtual()) { return INVALID_OPERATION; @@ -6070,10 +6066,10 @@ status_t SurfaceFlinger::getDesiredDisplayConfigSpecs( *outDefaultConfig = getHwComposer().getActiveConfigIndex(displayId); *outAllowGroupSwitching = false; auto vsyncPeriod = getHwComposer().getActiveConfig(displayId)->getVsyncPeriod(); - *outPrimaryRefreshRateMin = 1e9f / vsyncPeriod; - *outPrimaryRefreshRateMax = 1e9f / vsyncPeriod; - *outAppRequestRefreshRateMin = 1e9f / vsyncPeriod; - *outAppRequestRefreshRateMax = 1e9f / vsyncPeriod; + *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outPrimaryRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outAppRequestRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); + *outAppRequestRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue(); return NO_ERROR; } } @@ -6169,7 +6165,7 @@ status_t SurfaceFlinger::setFrameRate(const sp& surface, return BAD_VALUE; } if (layer->setFrameRate( - Layer::FrameRate(frameRate, + Layer::FrameRate(Fps{frameRate}, Layer::FrameRate::convertCompatibility(compatibility), shouldBeSeamless))) { setTransactionFlags(eTraversalNeeded); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 871222c8b0..a00e959762 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -44,6 +44,7 @@ cc_test { "DisplayDevice_GetBestColorModeTest.cpp", "DisplayDevice_SetProjectionTest.cpp", "EventThreadTest.cpp", + "FpsTest.cpp", "FrameTimelineTest.cpp", "HWComposerTest.cpp", "OneShotTimerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h index 4cd1e0adf1..36e24d25f7 100644 --- a/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h +++ b/services/surfaceflinger/tests/unittests/FakeVsyncConfiguration.h @@ -26,7 +26,7 @@ struct FakePhaseOffsets : VsyncConfiguration { static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0; static constexpr auto FAKE_DURATION_OFFSET_NS = std::chrono::nanoseconds(0); - VsyncConfigSet getConfigsForRefreshRate(float) const override { return getCurrentConfigs(); } + VsyncConfigSet getConfigsForRefreshRate(Fps) const override { return getCurrentConfigs(); } VsyncConfigSet getCurrentConfigs() const override { return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS, FAKE_DURATION_OFFSET_NS, @@ -37,7 +37,7 @@ struct FakePhaseOffsets : VsyncConfiguration { FAKE_DURATION_OFFSET_NS}}; } - void setRefreshRateFps(float) override {} + void setRefreshRateFps(Fps) override {} void dump(std::string&) const override {} }; diff --git a/services/surfaceflinger/tests/unittests/FpsTest.cpp b/services/surfaceflinger/tests/unittests/FpsTest.cpp new file mode 100644 index 0000000000..db732cfeaf --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FpsTest.cpp @@ -0,0 +1,98 @@ +/* + * Copyright 2020 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 "Fps.h" + +#include +#include + +namespace android { + +TEST(FpsTest, construct) { + Fps fpsDefault; + EXPECT_FALSE(fpsDefault.isValid()); + + Fps fps1(60.0f); + EXPECT_TRUE(fps1.isValid()); + Fps fps2 = Fps::fromPeriodNsecs(static_cast(1e9f / 60.0f)); + EXPECT_TRUE(fps2.isValid()); + EXPECT_TRUE(fps1.equalsWithMargin(fps2)); +} + +TEST(FpsTest, compare) { + constexpr float kEpsilon = 1e-4f; + const Fps::EqualsInBuckets equalsInBuckets; + const Fps::EqualsWithMargin equalsWithMargin; + + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f - kEpsilon))); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(Fps(60.f + kEpsilon))); + + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f))); + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f - kEpsilon))); + EXPECT_TRUE(equalsInBuckets(Fps(60.0f), Fps(60.0f + kEpsilon))); + + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f))); + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f - kEpsilon))); + EXPECT_TRUE(equalsWithMargin(Fps(60.0f), Fps(60.0f + kEpsilon))); + + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f + kEpsilon))); + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).lessThanOrEqualWithMargin(Fps(60.f - kEpsilon))); + + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f + kEpsilon))); + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f))); + EXPECT_TRUE(Fps(60.0f).greaterThanOrEqualWithMargin(Fps(60.f - kEpsilon))); + + // Fps with difference of 1 should be different + EXPECT_FALSE(Fps(60.0f).equalsWithMargin(Fps(61.f))); + EXPECT_TRUE(Fps(60.0f).lessThanWithMargin(Fps(61.f))); + EXPECT_TRUE(Fps(60.0f).greaterThanWithMargin(Fps(59.f))); + + // These are common refresh rates which should be different. + EXPECT_FALSE(Fps(60.0f).equalsWithMargin(Fps(59.94f))); + EXPECT_TRUE(Fps(60.0f).greaterThanWithMargin(Fps(59.94f))); + EXPECT_FALSE(equalsInBuckets(Fps(60.0f), Fps(59.94f))); + EXPECT_FALSE(equalsWithMargin(Fps(60.0f), Fps(59.94f))); + EXPECT_NE(std::hash()(Fps(60.0f)), std::hash()(Fps(59.94f))); + + EXPECT_FALSE(Fps(30.0f).equalsWithMargin(Fps(29.97f))); + EXPECT_TRUE(Fps(30.0f).greaterThanWithMargin(Fps(29.97f))); + EXPECT_FALSE(equalsInBuckets(Fps(30.0f), Fps(29.97f))); + EXPECT_FALSE(equalsWithMargin(Fps(30.0f), Fps(29.97f))); + EXPECT_NE(std::hash()(Fps(30.0f)), std::hash()(Fps(29.97f))); +} + +TEST(FpsTest, getIntValue) { + EXPECT_EQ(30, Fps(30.1f).getIntValue()); + EXPECT_EQ(31, Fps(30.9f).getIntValue()); + EXPECT_EQ(31, Fps(30.5f).getIntValue()); +} + +TEST(FpsTest, equalsInBucketsImpliesEqualHashes) { + constexpr float kStep = 1e-4f; + const Fps::EqualsInBuckets equals; + for (float fps = 30.0f; fps < 31.0f; fps += kStep) { + const Fps left(fps); + const Fps right(fps + kStep); + if (equals(left, right)) { + ASSERT_EQ(std::hash()(left), std::hash()(right)) + << "left= " << left << " right=" << right; + } + } +} + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index fbb46370b9..cbc1e0203a 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -32,7 +32,9 @@ using testing::_; using testing::Return; -namespace android::scheduler { +namespace android { + +namespace scheduler { class LayerHistoryTest : public testing::Test { protected: @@ -43,11 +45,11 @@ protected: static constexpr auto REFRESH_RATE_AVERAGE_HISTORY_DURATION = LayerInfo::RefreshRateHistory::HISTORY_DURATION; - static constexpr float LO_FPS = 30.f; - static constexpr auto LO_FPS_PERIOD = static_cast(1e9f / LO_FPS); + static constexpr Fps LO_FPS{30.f}; + static constexpr auto LO_FPS_PERIOD = LO_FPS.getPeriodNsecs(); - static constexpr float HI_FPS = 90.f; - static constexpr auto HI_FPS_PERIOD = static_cast(1e9f / HI_FPS); + static constexpr Fps HI_FPS{90.f}; + static constexpr auto HI_FPS_PERIOD = HI_FPS.getPeriodNsecs(); LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } @@ -88,20 +90,19 @@ protected: return sp(new mock::MockLayer(mFlinger.flinger(), std::move(name))); } - void recordFramesAndExpect(const sp& layer, nsecs_t& time, float frameRate, - float desiredRefreshRate, int numFrames) { - const nsecs_t framePeriod = static_cast(1e9f / frameRate); + void recordFramesAndExpect(const sp& layer, nsecs_t& time, Fps frameRate, + Fps desiredRefreshRate, int numFrames) { LayerHistory::Summary summary; for (int i = 0; i < numFrames; i++) { history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer); - time += framePeriod; + time += frameRate.getPeriodNsecs(); summary = history().summarize(time); } ASSERT_EQ(1, summary.size()); ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - ASSERT_FLOAT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate) + ASSERT_TRUE(desiredRefreshRate.equalsWithMargin(summary[0].desiredRefreshRate)) << "Frame rate is " << frameRate; } @@ -196,7 +197,7 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } @@ -289,7 +290,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly( - Return(Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::Default))); + Return(Layer::FrameRate(Fps(73.4f), Layer::FrameRateCompatibility::Default))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -302,7 +303,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -311,7 +312,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitVote) { time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } @@ -321,7 +322,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(73.4f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(73.4f), Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -335,7 +336,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -345,7 +346,7 @@ TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); } @@ -397,7 +398,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote); ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(history().summarize(time)[1].desiredRefreshRate)); + EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -411,7 +413,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -430,7 +432,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Max, summary[1].vote); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -440,9 +442,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { summary = history().summarize(time); ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[1].desiredRefreshRate)); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -452,9 +454,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(2, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[1].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[1].desiredRefreshRate)); EXPECT_EQ(2, layerCount()); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -469,7 +471,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(LO_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -490,7 +492,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { ASSERT_EQ(1, summary.size()); EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_FLOAT_EQ(HI_FPS, summary[0].desiredRefreshRate); + EXPECT_TRUE(HI_FPS.equalsWithMargin(summary[0].desiredRefreshRate)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -567,12 +569,12 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(60.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(60.0f), Layer::FrameRateCompatibility::ExactOrMultiple))); EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) .WillRepeatedly(Return( - Layer::FrameRate(90.0f, Layer::FrameRateCompatibility::ExactOrMultiple))); + Layer::FrameRate(Fps(90.0f), Layer::FrameRateCompatibility::ExactOrMultiple))); nsecs_t time = systemTime(); @@ -585,7 +587,7 @@ TEST_F(LayerHistoryTest, invisibleExplicitLayer) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, history().summarize(time)[0].vote); - EXPECT_FLOAT_EQ(60.0f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_TRUE(Fps(60.0f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate)); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); } @@ -643,7 +645,7 @@ TEST_F(LayerHistoryTest, heuristicLayer60Hz) { nsecs_t time = systemTime(); for (float fps = 54.0f; fps < 65.0f; fps += 0.1f) { - recordFramesAndExpect(layer, time, fps, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(fps), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); } } @@ -653,13 +655,13 @@ TEST_F(LayerHistoryTest, heuristicLayer60_30Hz) { EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); nsecs_t time = systemTime(); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60.0f, 60.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(30.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(30.0f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(60.0f), Fps(60.0f), PRESENT_TIME_HISTORY_SIZE); } TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { @@ -669,11 +671,11 @@ TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { nsecs_t time = systemTime(); - recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.90f, 30.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.00f, 24.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.90f, 24.0f, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 27.10f, 30.0f, PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(27.10f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.90f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.00f), Fps(24.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(26.90f), Fps(24.0f), PRESENT_TIME_HISTORY_SIZE); + recordFramesAndExpect(layer, time, Fps(27.10f), Fps(30.0f), PRESENT_TIME_HISTORY_SIZE); } class LayerHistoryTestParameterized : public LayerHistoryTest, @@ -724,7 +726,7 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) { bool max = false; bool min = false; - float heuristic = 0; + Fps heuristic{0.0}; for (const auto& layer : history().summarize(time)) { if (layer.vote == LayerHistory::LayerVoteType::Heuristic) { heuristic = layer.desiredRefreshRate; @@ -736,7 +738,7 @@ TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) { } if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) { - EXPECT_FLOAT_EQ(24.0f, heuristic); + EXPECT_TRUE(Fps(24.0f).equalsWithMargin(heuristic)); EXPECT_FALSE(max); if (history().summarize(time).size() == 2) { EXPECT_TRUE(min); @@ -750,4 +752,5 @@ INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryTestParameterized, ::testing::Values(1s, 2s, 3s, 4s, 5s)); } // namespace -} // namespace android::scheduler +} // namespace scheduler +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index f2b7191500..83ad737526 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -30,6 +30,7 @@ using namespace std::chrono_literals; using testing::_; namespace android { + namespace scheduler { namespace hal = android::hardware::graphics::composer::hal; @@ -43,11 +44,11 @@ protected: RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); - float findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, float frameRate) { + Fps findClosestKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs, Fps frameRate) { return refreshRateConfigs.findClosestKnownFrameRate(frameRate); } - std::vector getKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs) { + std::vector getKnownFrameRate(const RefreshRateConfigs& refreshRateConfigs) { return refreshRateConfigs.mKnownFrameRates; } @@ -62,29 +63,29 @@ protected: // Test configs std::shared_ptr mConfig60 = - createConfig(HWC_CONFIG_ID_60, 0, static_cast(1e9f / 60)); + createConfig(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs()); std::shared_ptr mConfig90 = - createConfig(HWC_CONFIG_ID_90, 0, static_cast(1e9f / 90)); + createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs()); std::shared_ptr mConfig90DifferentGroup = - createConfig(HWC_CONFIG_ID_90, 1, static_cast(1e9f / 90)); + createConfig(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs()); std::shared_ptr mConfig90DifferentResolution = - createConfig(HWC_CONFIG_ID_90, 0, static_cast(1e9f / 90), 111, 222); + createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), 111, 222); std::shared_ptr mConfig72 = - createConfig(HWC_CONFIG_ID_72, 0, static_cast(1e9f / 72)); + createConfig(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs()); std::shared_ptr mConfig72DifferentGroup = - createConfig(HWC_CONFIG_ID_72, 1, static_cast(1e9f / 72)); + createConfig(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs()); std::shared_ptr mConfig120 = - createConfig(HWC_CONFIG_ID_120, 0, static_cast(1e9f / 120)); + createConfig(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs()); std::shared_ptr mConfig120DifferentGroup = - createConfig(HWC_CONFIG_ID_120, 1, static_cast(1e9f / 120)); + createConfig(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs()); std::shared_ptr mConfig30 = - createConfig(HWC_CONFIG_ID_30, 0, static_cast(1e9f / 30)); + createConfig(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs()); std::shared_ptr mConfig30DifferentGroup = - createConfig(HWC_CONFIG_ID_30, 1, static_cast(1e9f / 30)); + createConfig(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs()); std::shared_ptr mConfig25DifferentGroup = - createConfig(HWC_CONFIG_ID_25, 1, static_cast(1e9f / 25)); + createConfig(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs()); std::shared_ptr mConfig50 = - createConfig(HWC_CONFIG_ID_50, 0, static_cast(1e9f / 50)); + createConfig(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs()); // Test device configurations // The positions of the configs in the arrays below MUST match their IDs. For example, @@ -124,23 +125,23 @@ protected: mConfig50}; // Expected RefreshRate objects - RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, "60fps", 60, + RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60), RefreshRate::ConstructorTag(0)}; RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60, - createConfig(HWC_CONFIG_ID_60, 0, 16666665), "60fps", 60, + createConfig(HWC_CONFIG_ID_60, 0, 16666665), Fps(60), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, "90fps", 90, + RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, Fps(90), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup, - "90fps", 90, RefreshRate::ConstructorTag(0)}; + Fps(90), RefreshRate::ConstructorTag(0)}; RefreshRate mExpected90DifferentResolutionConfig = {HWC_CONFIG_ID_90, - mConfig90DifferentResolution, "90fps", 90, + mConfig90DifferentResolution, Fps(90), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, "72fps", 72, + RefreshRate mExpected72Config = {HWC_CONFIG_ID_72, mConfig72, Fps(72.0f), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, "30fps", 30, + RefreshRate mExpected30Config = {HWC_CONFIG_ID_30, mConfig30, Fps(30), RefreshRate::ConstructorTag(0)}; - RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, "120fps", 120, + RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120), RefreshRate::ConstructorTag(0)}; Hwc2::mock::Display mDisplay; @@ -192,8 +193,11 @@ TEST_F(RefreshRateConfigsTest, invalidPolicy) { auto refreshRateConfigs = std::make_unique(m60OnlyConfigDevice, /*currentConfigId=*/HWC_CONFIG_ID_60); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HwcConfigIndexType(10), {60, 60}}), 0); - ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {20, 40}}), 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy( + {HwcConfigIndexType(10), {Fps(60), Fps(60)}}), + 0); + ASSERT_LT(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(20), Fps(40)}}), + 0); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { @@ -227,7 +231,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), + 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -252,7 +257,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}), + 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); @@ -274,7 +280,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_EQ(mExpected60Config, minRate); ASSERT_EQ(mExpected90Config, performanceRate); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); @@ -297,7 +304,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), + 0); { auto& current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); @@ -315,7 +323,8 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -338,34 +347,35 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.name = ""; - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, @@ -375,28 +385,30 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_90, {Fps(90.0f), Fps(90.0f)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected90Config, @@ -406,28 +418,30 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {0, 120}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( + {HWC_CONFIG_ID_60, {Fps(0.0f), Fps(120.0f)}}), + 0); lr.vote = LayerVoteType::Min; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -436,24 +450,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -474,24 +488,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_60_72_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -506,23 +520,23 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90_120) { auto& lr1 = layers[0]; auto& lr2 = layers[1]; - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 48.0f; + lr2.desiredRefreshRate = Fps(48.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 48.0f; + lr2.desiredRefreshRate = Fps(48.0f); lr2.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -538,82 +552,82 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_90_120_DifferentTypes) { auto& lr1 = layers[0]; auto& lr2 = layers[1]; - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "60Hz Heuristic"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "60Hz ExplicitDefault"; EXPECT_EQ(mExpected120Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::Heuristic; lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::Heuristic; lr1.name = "24Hz Heuristic"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; lr1.name = "24Hz ExplicitExactOrMultiple"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitDefault; lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr1.desiredRefreshRate = 24.0f; + lr1.desiredRefreshRate = Fps(24.0f); lr1.vote = LayerVoteType::ExplicitDefault; lr1.name = "24Hz ExplicitDefault"; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; lr2.name = "90Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected90Config, @@ -636,24 +650,24 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60) { EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); EXPECT_EQ(mExpected30Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -676,41 +690,41 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_30_60_72_90) { EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.vote = LayerVoteType::Heuristic; lr.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 45.0f; + lr.desiredRefreshRate = Fps(45.0f); lr.name = "45Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 30.0f; + lr.desiredRefreshRate = Fps(30.0f); lr.name = "30Hz Heuristic"; EXPECT_EQ(mExpected30Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.name = "24Hz Heuristic"; EXPECT_EQ(mExpected72Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); - lr.desiredRefreshRate = 24.0f; + lr.desiredRefreshRate = Fps(24.0f); lr.vote = LayerVoteType::ExplicitExactOrMultiple; lr.name = "24Hz ExplicitExactOrMultiple"; EXPECT_EQ(mExpected72Config, @@ -736,39 +750,39 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_PriorityTest) { lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 24.0f; + lr2.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Min; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 24.0f; + lr2.desiredRefreshRate = Fps(24.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Max; lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 15.0f; + lr1.desiredRefreshRate = Fps(15.0f); lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 45.0f; + lr2.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 45.0f; + lr2.desiredRefreshRate = Fps(45.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } @@ -783,7 +797,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_24FpsVideo) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { - lr.desiredRefreshRate = fps; + lr.desiredRefreshRate = Fps(fps); const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); EXPECT_EQ(mExpected60Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName(); @@ -801,33 +815,33 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getBestRefreshRate_Explicit) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 90.0f; + lr1.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::Heuristic; - lr1.desiredRefreshRate = 90.0f; + lr1.desiredRefreshRate = Fps(90.0f); lr2.vote = LayerVoteType::ExplicitExactOrMultiple; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); } TEST_F(RefreshRateConfigsTest, testInPolicy) { - ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(60.000004f, 60.000004f)); - ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(59.0f, 60.1f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(75.0f, 90.0f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(60.0011f, 90.0f)); - ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(50.0f, 59.998f)); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(Fps(60.000004f), Fps(60.000004f))); + ASSERT_TRUE(mExpectedAlmost60Config.inPolicy(Fps(59.0f), Fps(60.1f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(75.0f), Fps(90.0f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(60.0011f), Fps(90.0f))); + ASSERT_FALSE(mExpectedAlmost60Config.inPolicy(Fps(50.0f), Fps(59.998f))); } TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { @@ -840,7 +854,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_75HzContent) { lr.vote = LayerVoteType::ExplicitExactOrMultiple; for (float fps = 75.0f; fps < 100.0f; fps += 0.1f) { - lr.desiredRefreshRate = fps; + lr.desiredRefreshRate = Fps(fps); const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); EXPECT_EQ(mExpected90Config, refreshRate) << fps << "Hz chooses " << refreshRate.getName(); @@ -858,25 +872,25 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::ExplicitDefault; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz ExplicitDefault"; EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -884,16 +898,16 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_Multiples) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 30.0f; + lr1.desiredRefreshRate = Fps(30.0f); lr1.name = "30Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -912,7 +926,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; @@ -920,7 +934,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::NoVote; lr2.name = "NoVote"; @@ -928,7 +942,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -936,7 +950,7 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false})); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Max; lr2.name = "Max"; @@ -945,10 +959,10 @@ TEST_F(RefreshRateConfigsTest, scrollWhileWatching60fps_60_90) { // The other layer starts to provide buffers lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 90.0f; + lr2.desiredRefreshRate = Fps(90.0f); lr2.name = "90Hz Heuristic"; EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); @@ -972,40 +986,40 @@ TEST_F(RefreshRateConfigsTest, touchConsidered) { auto& lr2 = layers[1]; lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(true, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(false, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitExactOrMultiple; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); EXPECT_EQ(true, consideredSignals.touch); lr1.vote = LayerVoteType::ExplicitDefault; - lr1.desiredRefreshRate = 60.0f; + lr1.desiredRefreshRate = Fps(60.0f); lr1.name = "60Hz ExplicitExactOrMultiple"; lr2.vote = LayerVoteType::Heuristic; - lr2.desiredRefreshRate = 60.0f; + lr2.desiredRefreshRate = Fps(60.0f); lr2.name = "60Hz Heuristic"; refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}, &consideredSignals); @@ -1041,7 +1055,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { for (const auto& test : testCases) { lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = test.first; + lr.desiredRefreshRate = Fps(test.first); std::stringstream ss; ss << "ExplicitDefault " << test.first << " fps"; @@ -1049,7 +1063,7 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitDefault) { const auto& refreshRate = refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}); - EXPECT_FLOAT_EQ(refreshRate.getFps(), test.second) + EXPECT_TRUE(refreshRate.getFps().equalsWithMargin(Fps(test.second))) << "Expecting " << test.first << "fps => " << test.second << "Hz"; } } @@ -1061,7 +1075,7 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_90); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_90, {Fps(90.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; @@ -1069,7 +1083,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateConfigs::GlobalSignals consideredSignals; lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitDefault"; lr.focused = true; EXPECT_EQ(mExpected60Config, @@ -1085,14 +1099,14 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(60.f)}, {Fps(60.f), Fps(90.f)}}), 0); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& lr = layers[0]; lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 90.0f; + lr.desiredRefreshRate = Fps(90.0f); lr.name = "90Hz ExplicitDefault"; lr.focused = true; EXPECT_EQ(mExpected90Config, @@ -1106,7 +1120,7 @@ TEST_F(RefreshRateConfigsTest, /*currentConfigId=*/HWC_CONFIG_ID_90); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_90, {Fps(90.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); RefreshRateConfigs::GlobalSignals consideredSignals; @@ -1119,7 +1133,7 @@ TEST_F(RefreshRateConfigsTest, auto& lr = layers[0]; lr.vote = LayerVoteType::ExplicitExactOrMultiple; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitExactOrMultiple"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1130,7 +1144,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::ExplicitDefault; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz ExplicitDefault"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1141,7 +1155,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Heuristic; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Heuristic"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1152,7 +1166,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Max; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Max"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1163,7 +1177,7 @@ TEST_F(RefreshRateConfigsTest, refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})); lr.vote = LayerVoteType::Min; - lr.desiredRefreshRate = 60.0f; + lr.desiredRefreshRate = Fps(60.0f); lr.name = "60Hz Min"; lr.focused = false; EXPECT_EQ(mExpected90Config, @@ -1182,7 +1196,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& layer = layers[0]; layer.vote = LayerVoteType::ExplicitDefault; - layer.desiredRefreshRate = 90.0f; + layer.desiredRefreshRate = Fps(90.0f); layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "90Hz ExplicitDefault"; layer.focused = true; @@ -1207,7 +1221,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { // Verify that we won't do a seamless switch if we request the same mode as the default refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.name = "60Hz ExplicitDefault"; layer.seamlessness = Seamlessness::OnlySeamless; ASSERT_EQ(HWC_CONFIG_ID_90, @@ -1216,7 +1230,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { // Verify that if the current config is in another group and there are no layers with // seamlessness=SeamedAndSeamless we'll go back to the default group. - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.name = "60Hz ExplicitDefault"; layer.seamlessness = Seamlessness::Default; ASSERT_EQ(HWC_CONFIG_ID_60, @@ -1231,7 +1245,7 @@ TEST_F(RefreshRateConfigsTest, groupSwitching) { layers.push_back(LayerRequirement{.weight = 0.5f}); auto& layer2 = layers[layers.size() - 1]; layer2.vote = LayerVoteType::ExplicitDefault; - layer2.desiredRefreshRate = 90.0f; + layer2.desiredRefreshRate = Fps(90.0f); layer2.name = "90Hz ExplicitDefault"; layer2.seamlessness = Seamlessness::SeamedAndSeamless; layer2.focused = false; @@ -1262,7 +1276,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) { auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; auto& layer = layers[0]; layer.vote = LayerVoteType::ExplicitExactOrMultiple; - layer.desiredRefreshRate = 60.0f; + layer.desiredRefreshRate = Fps(60.0f); layer.seamlessness = Seamlessness::SeamedAndSeamless; layer.name = "60Hz ExplicitExactOrMultiple"; layer.focused = true; @@ -1291,13 +1305,13 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { auto layers = std::vector< LayerRequirement>{LayerRequirement{.name = "60Hz ExplicitDefault", .vote = LayerVoteType::ExplicitDefault, - .desiredRefreshRate = 60.0f, + .desiredRefreshRate = Fps(60.0f), .seamlessness = Seamlessness::SeamedAndSeamless, .weight = 0.5f, .focused = false}, LayerRequirement{.name = "25Hz ExplicitExactOrMultiple", .vote = LayerVoteType::ExplicitExactOrMultiple, - .desiredRefreshRate = 25.0f, + .desiredRefreshRate = Fps(25.0f), .seamlessness = Seamlessness::OnlySeamless, .weight = 1.0f, .focused = true}}; @@ -1307,7 +1321,7 @@ TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) { refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}) .getConfigId()); - seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = 30.0f; + seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = Fps(30.0f); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_30); ASSERT_EQ(HWC_CONFIG_ID_25, @@ -1325,7 +1339,7 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { // Return the config ID from calling getBestRefreshRate() for a single layer with the // given voteType and fps. - auto getFrameRate = [&](LayerVoteType voteType, float fps, bool touchActive = false, + auto getFrameRate = [&](LayerVoteType voteType, Fps fps, bool touchActive = false, bool focused = true) -> HwcConfigIndexType { layers[0].vote = voteType; layers[0].desiredRefreshRate = fps; @@ -1335,43 +1349,44 @@ TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) { }; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {30.f, 60.f}, {30.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(30.f), Fps(60.f)}, {Fps(30.f), Fps(90.f)}}), 0); EXPECT_EQ(HWC_CONFIG_ID_60, refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false}) .getConfigId()); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f))); // Layers not focused are not allowed to override primary config EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/false, + getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f), /*touch=*/false, /*focused=*/false)); EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/false, + getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f), /*touch=*/false, /*focused=*/false)); // Touch boost should be restricted to the primary range. - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f, /*touch=*/true)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f), /*touch=*/true)); // When we're higher than the primary range max due to a layer frame rate setting, touch boost // shouldn't drag us back down to the primary range max. - EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f, /*touch=*/true)); + EXPECT_EQ(HWC_CONFIG_ID_90, + getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f), /*touch=*/true)); EXPECT_EQ(HWC_CONFIG_ID_60, - getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f, /*touch=*/true)); + getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f), /*touch=*/true)); ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 60.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(60.f)}, {Fps(60.f), Fps(60.f)}}), 0); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, 90.f)); - EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, 90.f)); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitDefault, Fps(90.f))); + EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::ExplicitExactOrMultiple, Fps(90.f))); } TEST_F(RefreshRateConfigsTest, idle) { @@ -1385,7 +1400,7 @@ TEST_F(RefreshRateConfigsTest, idle) { const auto getIdleFrameRate = [&](LayerVoteType voteType, bool touchActive) -> HwcConfigIndexType { layers[0].vote = voteType; - layers[0].desiredRefreshRate = 90.f; + layers[0].desiredRefreshRate = Fps(90.f); RefreshRateConfigs::GlobalSignals consideredSignals; const auto configId = refreshRateConfigs @@ -1398,7 +1413,7 @@ TEST_F(RefreshRateConfigsTest, idle) { }; ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy( - {HWC_CONFIG_ID_60, {60.f, 90.f}, {60.f, 90.f}}), + {HWC_CONFIG_ID_60, {Fps(60.f), Fps(90.f)}, {Fps(60.f), Fps(90.f)}}), 0); // Idle should be lower priority than touch boost. @@ -1439,22 +1454,22 @@ TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) { /*currentConfigId=*/HWC_CONFIG_ID_60); for (float fps = 1.0f; fps <= 120.0f; fps += 0.1f) { - const auto knownFrameRate = findClosestKnownFrameRate(*refreshRateConfigs, fps); - float expectedFrameRate; + const auto knownFrameRate = findClosestKnownFrameRate(*refreshRateConfigs, Fps(fps)); + Fps expectedFrameRate; if (fps < 26.91f) { - expectedFrameRate = 24.0f; + expectedFrameRate = Fps(24.0f); } else if (fps < 37.51f) { - expectedFrameRate = 30.0f; + expectedFrameRate = Fps(30.0f); } else if (fps < 52.51f) { - expectedFrameRate = 45.0f; + expectedFrameRate = Fps(45.0f); } else if (fps < 66.01f) { - expectedFrameRate = 60.0f; + expectedFrameRate = Fps(60.0f); } else if (fps < 81.01f) { - expectedFrameRate = 72.0f; + expectedFrameRate = Fps(72.0f); } else { - expectedFrameRate = 90.0f; + expectedFrameRate = Fps(90.0f); } - EXPECT_FLOAT_EQ(expectedFrameRate, knownFrameRate) + EXPECT_TRUE(expectedFrameRate.equalsWithMargin(knownFrameRate)) << "findClosestKnownFrameRate(" << fps << ") = " << knownFrameRate; } } @@ -1465,26 +1480,27 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_KnownFrameRate) { /*currentConfigId=*/HWC_CONFIG_ID_60); struct ExpectedRate { - float rate; + Fps rate; const RefreshRate& expected; }; /* clang-format off */ std::vector knownFrameRatesExpectations = { - {24.0f, mExpected60Config}, - {30.0f, mExpected60Config}, - {45.0f, mExpected90Config}, - {60.0f, mExpected60Config}, - {72.0f, mExpected90Config}, - {90.0f, mExpected90Config}, + {Fps(24.0f), mExpected60Config}, + {Fps(30.0f), mExpected60Config}, + {Fps(45.0f), mExpected90Config}, + {Fps(60.0f), mExpected60Config}, + {Fps(72.0f), mExpected90Config}, + {Fps(90.0f), mExpected90Config}, }; /* clang-format on */ // Make sure the test tests all the known frame rate const auto knownFrameRateList = getKnownFrameRate(*refreshRateConfigs); - const auto equal = std::equal(knownFrameRateList.begin(), knownFrameRateList.end(), - knownFrameRatesExpectations.begin(), - [](float a, const ExpectedRate& b) { return a == b.rate; }); + const auto equal = + std::equal(knownFrameRateList.begin(), knownFrameRateList.end(), + knownFrameRatesExpectations.begin(), + [](Fps a, const ExpectedRate& b) { return a.equalsWithMargin(b.rate); }); EXPECT_TRUE(equal); auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; @@ -1514,15 +1530,18 @@ TEST_F(RefreshRateConfigsTest, testKernelIdleTimerAction) { EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(60, 90), current 60Hz => TurnOn. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(90)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::TurnOn, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(60, 60), current 60Hz => NoChange, avoid extra calls. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::NoChange, refreshRateConfigs->getIdleTimerAction()); // SetPolicy(90, 90), current 90Hz => TurnOff. - ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {90, 90}}), 0); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), + 0); EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction()); } @@ -1554,7 +1573,7 @@ TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) { EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5}); + refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.5f}); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); refreshRateConfigs->setPreferredRefreshRateForUid({uid, 22.6f}); EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDividerForUid(uid)); diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 5278641e5b..c47b141823 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -108,11 +108,12 @@ std::string PrintToStringParamName( */ class SetFrameRateTest : public ::testing::TestWithParam> { protected: - const FrameRate FRAME_RATE_VOTE1 = FrameRate(67.f, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_VOTE2 = FrameRate(14.f, FrameRateCompatibility::ExactOrMultiple); - const FrameRate FRAME_RATE_VOTE3 = FrameRate(99.f, FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_TREE = FrameRate(0, FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_NO_VOTE = FrameRate(0, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE1 = FrameRate(Fps(67.f), FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE2 = + FrameRate(Fps(14.f), FrameRateCompatibility::ExactOrMultiple); + const FrameRate FRAME_RATE_VOTE3 = FrameRate(Fps(99.f), FrameRateCompatibility::NoVote); + const FrameRate FRAME_RATE_TREE = FrameRate(Fps(0.f), FrameRateCompatibility::NoVote); + const FrameRate FRAME_RATE_NO_VOTE = FrameRate(Fps(0.f), FrameRateCompatibility::Default); SetFrameRateTest(); diff --git a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp index 72ee6db737..2a35f69560 100644 --- a/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp +++ b/services/surfaceflinger/tests/unittests/VsyncConfigurationTest.cpp @@ -29,17 +29,18 @@ namespace android::scheduler { class TestableWorkDuration : public impl::WorkDuration { public: - TestableWorkDuration(float currentFps, nsecs_t sfDuration, nsecs_t appDuration, + TestableWorkDuration(Fps currentFps, nsecs_t sfDuration, nsecs_t appDuration, nsecs_t sfEarlyDuration, nsecs_t appEarlyDuration, nsecs_t sfEarlyGlDuration, nsecs_t appEarlyGlDuration) - : impl::WorkDuration({60.0f, 90.0f}, currentFps, sfDuration, appDuration, sfEarlyDuration, - appEarlyDuration, sfEarlyGlDuration, appEarlyGlDuration) {} + : impl::WorkDuration({Fps(60.0f), Fps(90.0f)}, currentFps, sfDuration, appDuration, + sfEarlyDuration, appEarlyDuration, sfEarlyGlDuration, + appEarlyGlDuration) {} }; class WorkDurationTest : public testing::Test { protected: WorkDurationTest() - : mWorkDuration(60.0f, 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000, + : mWorkDuration(Fps(60.0f), 10'500'000, 20'500'000, 16'000'000, 16'500'000, 13'500'000, 21'000'000) {} ~WorkDurationTest() = default; @@ -51,9 +52,9 @@ protected: * Test cases */ TEST_F(WorkDurationTest, getConfigsForRefreshRate_60Hz) { - mWorkDuration.setRefreshRateFps(60.0f); + mWorkDuration.setRefreshRateFps(Fps(60.0f)); auto currentOffsets = mWorkDuration.getCurrentConfigs(); - auto offsets = mWorkDuration.getConfigsForRefreshRate(60.0f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(currentOffsets, offsets); EXPECT_EQ(offsets.late.sfOffset, 6'166'667); @@ -76,9 +77,9 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_60Hz) { } TEST_F(WorkDurationTest, getConfigsForRefreshRate_90Hz) { - mWorkDuration.setRefreshRateFps(90.0f); + mWorkDuration.setRefreshRateFps(Fps(90.0f)); auto currentOffsets = mWorkDuration.getCurrentConfigs(); - auto offsets = mWorkDuration.getConfigsForRefreshRate(90.0f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(currentOffsets, offsets); EXPECT_EQ(offsets.late.sfOffset, 611'111); @@ -101,7 +102,7 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_90Hz) { } TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) { - TestableWorkDuration phaseOffsetsWithDefaultValues(60.0f, -1, -1, -1, -1, -1, -1); + TestableWorkDuration phaseOffsetsWithDefaultValues(Fps(60.0f), -1, -1, -1, -1, -1, -1); auto validateOffsets = [](const auto& offsets, std::chrono::nanoseconds vsyncPeriod) { EXPECT_EQ(offsets.late.sfOffset, 1'000'000); @@ -123,21 +124,20 @@ TEST_F(WorkDurationTest, getConfigsForRefreshRate_DefaultOffsets) { EXPECT_EQ(offsets.earlyGpu.appWorkDuration, vsyncPeriod); }; - const auto testForRefreshRate = [&](float refreshRate) { + const auto testForRefreshRate = [&](Fps refreshRate) { phaseOffsetsWithDefaultValues.setRefreshRateFps(refreshRate); auto currentOffsets = phaseOffsetsWithDefaultValues.getCurrentConfigs(); auto offsets = phaseOffsetsWithDefaultValues.getConfigsForRefreshRate(refreshRate); EXPECT_EQ(currentOffsets, offsets); - validateOffsets(offsets, - std::chrono::nanoseconds(static_cast(1e9f / refreshRate))); + validateOffsets(offsets, std::chrono::nanoseconds(refreshRate.getPeriodNsecs())); }; - testForRefreshRate(90.0f); - testForRefreshRate(60.0f); + testForRefreshRate(Fps(90.0f)); + testForRefreshRate(Fps(60.0f)); } TEST_F(WorkDurationTest, getConfigsForRefreshRate_unknownRefreshRate) { - auto offsets = mWorkDuration.getConfigsForRefreshRate(14.7f); + auto offsets = mWorkDuration.getConfigsForRefreshRate(Fps(14.7f)); EXPECT_EQ(offsets.late.sfOffset, 57'527'208); EXPECT_EQ(offsets.late.appOffset, 37'027'208); @@ -171,9 +171,9 @@ public: std::optional highFpsEarlyAppOffsetNs, std::optional highFpsEarlyGpuAppOffsetNs, nsecs_t thresholdForNextVsync) - : impl::PhaseOffsets({60.0f, 90.0f}, 60.0f, vsyncPhaseOffsetNs, sfVSyncPhaseOffsetNs, - earlySfOffsetNs, earlyGpuSfOffsetNs, earlyAppOffsetNs, - earlyGpuAppOffsetNs, highFpsVsyncPhaseOffsetNs, + : impl::PhaseOffsets({Fps(60.0f), Fps(90.0f)}, Fps(60.0f), vsyncPhaseOffsetNs, + sfVSyncPhaseOffsetNs, earlySfOffsetNs, earlyGpuSfOffsetNs, + earlyAppOffsetNs, earlyGpuAppOffsetNs, highFpsVsyncPhaseOffsetNs, highFpsSfVSyncPhaseOffsetNs, highFpsEarlySfOffsetNs, highFpsEarlyGpuSfOffsetNs, highFpsEarlyAppOffsetNs, highFpsEarlyGpuAppOffsetNs, thresholdForNextVsync) {} @@ -190,7 +190,7 @@ protected: }; TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(14.7f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(14.7f)); EXPECT_EQ(offsets.late.sfOffset, 6'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -212,7 +212,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_unknownRefreshRate) { } TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_60Hz) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(60.0f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(offsets.late.sfOffset, 6'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -234,7 +234,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_60Hz) { } TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_90Hz) { - auto offsets = mPhaseOffsets.getConfigsForRefreshRate(90.0f); + auto offsets = mPhaseOffsets.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); @@ -258,7 +258,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_90Hz) { TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) { TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, 1'000'000, {}, {}, {}, {}, 10'000'000}; - auto offsets = phaseOffsets.getConfigsForRefreshRate(60.0f); + auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(60.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 1'000'000); @@ -282,7 +282,7 @@ TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_60Hz) { TEST_F(PhaseOffsetsTest, getConfigsForRefreshRate_DefaultValues_90Hz) { TestablePhaseOffsets phaseOffsets{1'000'000, 1'000'000, {}, {}, {}, {}, 2'000'000, 1'000'000, {}, {}, {}, {}, 10'000'000}; - auto offsets = phaseOffsets.getConfigsForRefreshRate(90.0f); + auto offsets = phaseOffsets.getConfigsForRefreshRate(Fps(90.0f)); EXPECT_EQ(offsets.late.sfOffset, 1'000'000); EXPECT_EQ(offsets.late.appOffset, 2'000'000); -- cgit v1.2.3-59-g8ed1b From f7f6b3c7cdb7f331f16021aeda903fc68ab1f672 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Wed, 9 Dec 2020 13:19:38 +0100 Subject: SF: RefreshRateOverlay: Create buffers on demand Currently RefreshRateOverlay precomputes the buffers for all available refresh rates on startup. Since the refresh rates can change (e.g. on AndroidTV) it's better to create the buffers on demand. Bug: 159590486 Test: adb shell service call SurfaceFlinger 1034 i32 1 Change-Id: I49732f4b62b41750c5a3cf4020b2dc23b8f3730b --- services/surfaceflinger/RefreshRateOverlay.cpp | 45 +++++++++++++------------- services/surfaceflinger/RefreshRateOverlay.h | 7 +++- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++ 3 files changed, 33 insertions(+), 24 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index f99d54ac53..a959b9a97f 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -18,6 +18,8 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#include + #include "RefreshRateOverlay.h" #include "Client.h" #include "Layer.h" @@ -172,7 +174,7 @@ std::vector> RefreshRateOverlay::SevenSegmentDrawer::drawNumbe RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, bool showSpinner) : mFlinger(flinger), mClient(new Client(&mFlinger)), mShowSpinner(showSpinner) { createLayer(); - primeCache(); + reset(); } bool RefreshRateOverlay::createLayer() { @@ -202,26 +204,15 @@ bool RefreshRateOverlay::createLayer() { return true; } -void RefreshRateOverlay::primeCache() { - auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates(); - if (allRefreshRates.size() == 1) { - int fps = allRefreshRates.begin()->second->getFps().getIntValue(); - half4 color = {LOW_FPS_COLOR, ALPHA}; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); - return; - } - - std::vector supportedFps; - supportedFps.reserve(allRefreshRates.size()); - for (auto& [ignored, refreshRate] : allRefreshRates) { - supportedFps.push_back(refreshRate->getFps().getIntValue()); - } - - std::sort(supportedFps.begin(), supportedFps.end()); - const auto mLowFps = supportedFps[0]; - const auto mHighFps = supportedFps[supportedFps.size() - 1]; - for (auto fps : supportedFps) { - const auto fpsScale = float(fps - mLowFps) / (mHighFps - mLowFps); +const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { + if (mBufferCache.find(fps) == mBufferCache.end()) { + // Ensure the range is > 0, so we don't divide by 0. + const auto rangeLength = std::max(1u, mHighFps - mLowFps); + // Clip values outside the range [mLowFps, mHighFps]. The current fps may be outside + // of this range if the display has changed its set of supported refresh rates. + fps = std::max(fps, mLowFps); + fps = std::min(fps, mHighFps); + const auto fpsScale = static_cast(fps - mLowFps) / rangeLength; half4 color; color.r = HIGH_FPS_COLOR.r * fpsScale + LOW_FPS_COLOR.r * (1 - fpsScale); color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); @@ -229,6 +220,8 @@ void RefreshRateOverlay::primeCache() { color.a = ALPHA; mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); } + + return mBufferCache[fps]; } void RefreshRateOverlay::setViewport(ui::Size viewport) { @@ -241,7 +234,7 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); - auto buffer = mBufferCache[*mCurrentFps][mFrame]; + auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); @@ -251,7 +244,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { void RefreshRateOverlay::onInvalidate() { if (!mCurrentFps.has_value()) return; - const auto& buffers = mBufferCache[*mCurrentFps]; + const auto& buffers = getOrCreateBuffers(*mCurrentFps); mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, @@ -260,6 +253,12 @@ void RefreshRateOverlay::onInvalidate() { mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } +void RefreshRateOverlay::reset() { + mBufferCache.clear(); + mLowFps = mFlinger.mRefreshRateConfigs->getMinRefreshRate().getFps().getIntValue(); + mHighFps = mFlinger.mRefreshRateConfigs->getMaxRefreshRate().getFps().getIntValue(); +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 1a8938fbd4..4ca1337c67 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -43,6 +43,7 @@ public: void setViewport(ui::Size); void changeRefreshRate(const RefreshRate&); void onInvalidate(); + void reset(); private: class SevenSegmentDrawer { @@ -71,7 +72,7 @@ private: }; bool createLayer(); - void primeCache(); + const std::vector>& getOrCreateBuffers(uint32_t fps); SurfaceFlinger& mFlinger; const sp mClient; @@ -87,6 +88,10 @@ private: const half3 HIGH_FPS_COLOR = half3(0.0f, 1.0f, 0.0f); const bool mShowSpinner; + + // Interpolate the colors between these values. + uint32_t mLowFps; + uint32_t mHighFps; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6c8a1c1907..5d6505f19d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2591,6 +2591,11 @@ void SurfaceFlinger::processDisplayChanged(const wp& displayToken, if (currentState.physical) { const auto display = getDisplayDeviceLocked(displayToken); setPowerModeInternal(display, hal::PowerMode::ON); + + // TODO(b/175678251) Call a listener instead. + if (mRefreshRateOverlay) { + mRefreshRateOverlay->reset(); + } } return; } -- cgit v1.2.3-59-g8ed1b From f0c5649f2ed8ca5fba07389908b2491007d50b08 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 17 Dec 2020 18:04:15 -0800 Subject: SurfaceFlinger: correctly pass desired present time for BLAST Pass whether a desired present time is automatically populated or not to match BufferStateLayer behavior to the one we have for BufferQueueLayer. Bug: 169901895 Test: expand notification shade and observe systrace Change-Id: Ia02c5633d46dde67d2c3be33b084d63c40c2afb0 --- libs/gui/BLASTBufferQueue.cpp | 4 +- libs/gui/ISurfaceComposer.cpp | 9 ++-- libs/gui/SurfaceComposerClient.cpp | 18 ++++++-- libs/gui/include/gui/ISurfaceComposer.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 ++- libs/gui/tests/Surface_test.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 10 ++--- services/surfaceflinger/BufferStateLayer.h | 4 +- services/surfaceflinger/Layer.h | 6 ++- services/surfaceflinger/RefreshRateOverlay.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 45 +++++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 15 ++++--- .../tests/unittests/TestableSurfaceFlinger.h | 8 ++-- .../tests/unittests/TransactionApplicationTest.cpp | 49 +++++++++++++--------- 14 files changed, 111 insertions(+), 71 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 83283224e8..9fc5495938 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -311,7 +311,9 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); - t->setDesiredPresentTime(bufferItem.mTimestamp); + if (!bufferItem.mIsAutoTimestamp) { + t->setDesiredPresentTime(bufferItem.mTimestamp); + } t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber); if (!mNextFrameTimelineVsyncIdQueue.empty()) { diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 405658bf6d..a8d6832275 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -71,7 +71,7 @@ public: virtual status_t setTransactionState( int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, - const InputWindowCommands& commands, int64_t desiredPresentTime, + const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) { Parcel data, reply; @@ -92,6 +92,7 @@ public: SAFE_PARCEL(data.writeStrongBinder, applyToken); SAFE_PARCEL(commands.write, data); SAFE_PARCEL(data.writeInt64, desiredPresentTime); + SAFE_PARCEL(data.writeBool, isAutoTimestamp); SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote()); SAFE_PARCEL(data.writeUint64, uncacheBuffer.id); SAFE_PARCEL(data.writeBool, hasListenerCallbacks); @@ -1297,7 +1298,9 @@ status_t BnSurfaceComposer::onTransact( SAFE_PARCEL(inputWindowCommands.read, data); int64_t desiredPresentTime = 0; + bool isAutoTimestamp = true; SAFE_PARCEL(data.readInt64, &desiredPresentTime); + SAFE_PARCEL(data.readBool, &isAutoTimestamp); client_cache_t uncachedBuffer; sp tmpBinder; @@ -1323,8 +1326,8 @@ status_t BnSurfaceComposer::onTransact( return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags, applyToken, inputWindowCommands, desiredPresentTime, - uncachedBuffer, hasListenerCallbacks, listenerCallbacks, - transactionId); + isAutoTimestamp, uncachedBuffer, hasListenerCallbacks, + listenerCallbacks, transactionId); } case BOOT_FINISHED: { CHECK_INTERFACE(ISurfaceComposer, data, reply); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0d370d3aea..5570d99d61 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -395,6 +395,7 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mExplicitEarlyWakeupEnd(other.mExplicitEarlyWakeupEnd), mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime), + mIsAutoTimestamp(other.mIsAutoTimestamp), mFrameTimelineVsyncId(other.mFrameTimelineVsyncId) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; @@ -424,6 +425,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel const bool explicitEarlyWakeupEnd = parcel->readBool(); const bool containsBuffer = parcel->readBool(); const int64_t desiredPresentTime = parcel->readInt64(); + const bool isAutoTimestamp = parcel->readBool(); const int64_t frameTimelineVsyncId = parcel->readInt64(); size_t count = static_cast(parcel->readUint32()); @@ -497,6 +499,7 @@ status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel mExplicitEarlyWakeupEnd = explicitEarlyWakeupEnd; mContainsBuffer = containsBuffer; mDesiredPresentTime = desiredPresentTime; + mIsAutoTimestamp = isAutoTimestamp; mFrameTimelineVsyncId = frameTimelineVsyncId; mDisplayStates = displayStates; mListenerCallbacks = listenerCallbacks; @@ -527,6 +530,7 @@ status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const parcel->writeBool(mExplicitEarlyWakeupEnd); parcel->writeBool(mContainsBuffer); parcel->writeInt64(mDesiredPresentTime); + parcel->writeBool(mIsAutoTimestamp); parcel->writeInt64(mFrameTimelineVsyncId); parcel->writeUint32(static_cast(mDisplayStates.size())); for (auto const& displayState : mDisplayStates) { @@ -628,7 +632,8 @@ void SurfaceComposerClient::Transaction::clear() { mEarlyWakeup = false; mExplicitEarlyWakeupStart = false; mExplicitEarlyWakeupEnd = false; - mDesiredPresentTime = -1; + mDesiredPresentTime = 0; + mIsAutoTimestamp = true; mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; } @@ -640,8 +645,9 @@ void SurfaceComposerClient::doUncacheBufferTransaction(uint64_t cacheId) { uncacheBuffer.id = cacheId; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); - sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, -1, - uncacheBuffer, false, {}, 0 /* Undefined transactionId */); + sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, + systemTime(), true, uncacheBuffer, false, {}, + 0 /* Undefined transactionId */); } void SurfaceComposerClient::Transaction::cacheBuffers() { @@ -759,7 +765,7 @@ status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken, - mInputWindowCommands, mDesiredPresentTime, + mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp, {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/, hasListenerCallbacks, listenerCallbacks, mId); mId = generateId(); @@ -1201,6 +1207,9 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe } s->what |= layer_state_t::eBufferChanged; s->buffer = buffer; + if (mIsAutoTimestamp) { + mDesiredPresentTime = systemTime(); + } registerSurfaceControlForCallback(sc); @@ -1295,6 +1304,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setSideb SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime( nsecs_t desiredPresentTime) { mDesiredPresentTime = desiredPresentTime; + mIsAutoTimestamp = false; return *this; } diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 7d25d61431..40316dbeea 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -166,7 +166,7 @@ public: int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) = 0; /* signal that we're done booting. diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 3ee4a39392..0abe72c5b7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -373,13 +373,17 @@ public: // to be presented. When it is not possible to present at exactly that time, it will be // presented after the time has passed. // + // If the client didn't pass a desired presentation time, mDesiredPresentTime will be + // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true. + // // Desired present times that are more than 1 second in the future may be ignored. // When a desired present time has already passed, the transaction will be presented as soon // as possible. // // Transactions from the same process are presented in the same order that they are applied. // The desired present time does not affect this ordering. - int64_t mDesiredPresentTime = -1; + int64_t mDesiredPresentTime = 0; + bool mIsAutoTimestamp = true; // The vsync Id provided by Choreographer.getVsyncId int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 7761db8815..fa98cd4c3c 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -700,7 +700,7 @@ public: const Vector& /*displays*/, uint32_t /*flags*/, const sp& /*applyToken*/, const InputWindowCommands& /*inputWindowCommands*/, - int64_t /*desiredPresentTime*/, + int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*cachedBuffer*/, bool /*hasListenerCallbacks*/, const std::vector& /*listenerCallbacks*/, diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 0b9cabae3d..df1472d0d4 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -341,7 +341,7 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post } bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, - nsecs_t postTime, nsecs_t desiredPresentTime, + nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber) { ATRACE_CALL(); @@ -365,13 +365,13 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(), mOwnerUid, postTime); - desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime; mCurrentState.desiredPresentTime = desiredPresentTime; + mCurrentState.isAutoTimestamp = isAutoTimestamp; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, + mFlinger->mScheduler->recordLayerHistory(this, isAutoTimestamp ? 0 : desiredPresentTime, LayerHistory::LayerUpdateType::Buffer); - addFrameEvent(acquireFence, postTime, desiredPresentTime); + addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime); return true; } @@ -533,7 +533,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return true; } - return mCurrentState.desiredPresentTime <= expectedPresentTime; + return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime; } bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ad00c65651..734f647b01 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -70,8 +70,8 @@ public: bool setCrop(const Rect& crop) override; bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, const client_cache_t& clientCacheId, - uint64_t frameNumber) override; + nsecs_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& clientCacheId, uint64_t frameNumber) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c9e97daf8b..d6023b66ac 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -275,7 +275,8 @@ public: // recent callback handle. std::deque> callbackHandles; bool colorSpaceAgnostic; - nsecs_t desiredPresentTime = -1; + nsecs_t desiredPresentTime = 0; + bool isAutoTimestamp = true; // Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will // be rendered around the layer. @@ -444,7 +445,8 @@ public: virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */) { + bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, + uint64_t /* frameNumber */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index a959b9a97f..c291b7f2e0 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -235,7 +235,7 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); @@ -247,7 +247,7 @@ void RefreshRateOverlay::onInvalidate() { const auto& buffers = getOrCreateBuffers(*mCurrentFps); mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; - mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {}, + mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 14536b3143..68d2a68322 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3262,8 +3262,9 @@ bool SurfaceFlinger::flushTransactionQueues() { applyTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, mPendingInputWindowCommands, transaction.desiredPresentTime, - transaction.buffer, transaction.postTime, - transaction.privileged, transaction.hasListenerCallbacks, + transaction.isAutoTimestamp, transaction.buffer, + transaction.postTime, transaction.privileged, + transaction.hasListenerCallbacks, transaction.listenerCallbacks, transaction.originPid, transaction.originUid, transaction.id, /*isMainThread*/ true); transactionQueue.pop(); @@ -3294,7 +3295,7 @@ bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, bool ready = true; // 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 && + if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime && desiredPresentTime < expectedPresentTime + s2ns(1)) { ready = false; } @@ -3331,7 +3332,7 @@ status_t SurfaceFlinger::setTransactionState( int64_t frameTimelineVsyncId, const Vector& states, const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) { ATRACE_CALL(); @@ -3372,17 +3373,19 @@ status_t SurfaceFlinger::setTransactionState( const int originPid = ipc->getCallingPid(); const int originUid = ipc->getCallingUid(); - if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states, true)) { + if (pendingTransactions || + !transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true)) { mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags, - desiredPresentTime, uncacheBuffer, postTime, - privileged, hasListenerCallbacks, listenerCallbacks, - originPid, originUid, transactionId); + desiredPresentTime, isAutoTimestamp, uncacheBuffer, + postTime, privileged, hasListenerCallbacks, + listenerCallbacks, originPid, originUid, + transactionId); setTransactionFlags(eTransactionFlushNeeded); return NO_ERROR; } applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands, - desiredPresentTime, uncacheBuffer, postTime, privileged, + desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged, hasListenerCallbacks, listenerCallbacks, originPid, originUid, transactionId, /*isMainThread*/ false); return NO_ERROR; @@ -3392,9 +3395,10 @@ void SurfaceFlinger::applyTransactionState( int64_t frameTimelineVsyncId, const Vector& states, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime, - const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, - bool hasListenerCallbacks, const std::vector& listenerCallbacks, - int originPid, int originUid, uint64_t transactionId, bool isMainThread) { + bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, + bool privileged, bool hasListenerCallbacks, + const std::vector& listenerCallbacks, int originPid, int originUid, + uint64_t transactionId, bool isMainThread) { uint32_t transactionFlags = 0; if (flags & eAnimation) { @@ -3428,12 +3432,13 @@ void SurfaceFlinger::applyTransactionState( std::unordered_set listenerCallbacksWithSurfaces; uint32_t clientStateFlags = 0; for (const ComposerState& state : states) { - clientStateFlags |= - setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, postTime, - privileged, listenerCallbacksWithSurfaces); + clientStateFlags |= setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, + isAutoTimestamp, postTime, privileged, + listenerCallbacksWithSurfaces); if ((flags & eAnimation) && state.state.surface) { if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) { - mScheduler->recordLayerHistory(layer.get(), desiredPresentTime, + mScheduler->recordLayerHistory(layer.get(), + isAutoTimestamp ? 0 : desiredPresentTime, LayerHistory::LayerUpdateType::AnimationTX); } } @@ -3608,7 +3613,7 @@ bool SurfaceFlinger::callingThreadHasUnscopedSurfaceFlingerAccess(bool usePermis uint32_t SurfaceFlinger::setClientStateLocked( int64_t frameTimelineVsyncId, const ComposerState& composerState, - int64_t desiredPresentTime, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) { const layer_state_t& s = composerState.state; @@ -3919,8 +3924,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( ? s.frameNumber : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; - if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, s.cachedBuffer, - frameNumber)) { + if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, + s.cachedBuffer, frameNumber)) { flags |= eTraversalNeeded; } } @@ -4198,7 +4203,7 @@ void SurfaceFlinger::onInitializeDisplays() { d.height = 0; displays.add(d); setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr, - mPendingInputWindowCommands, -1, {}, false, {}, + mPendingInputWindowCommands, systemTime(), true, {}, false, {}, 0 /* Undefined transactionId */); setPowerModeInternal(display, hal::PowerMode::ON); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e3e9c4f229..db75312cd3 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -341,7 +341,7 @@ protected: virtual uint32_t setClientStateLocked( int64_t frameTimelineVsyncId, const ComposerState& composerState, - int64_t desiredPresentTime, int64_t postTime, bool privileged, + int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged, std::unordered_set& listenerCallbacks) REQUIRES(mStateLock); virtual void commitTransactionLocked(); @@ -434,8 +434,9 @@ private: struct TransactionState { TransactionState(int64_t frameTimelineVsyncId, const Vector& composerStates, const Vector& displayStates, uint32_t transactionFlags, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - int64_t postTime, bool privileged, bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged, + bool hasListenerCallbacks, std::vector listenerCallbacks, int originPid, int originUid, uint64_t transactionId) : frameTimelineVsyncId(frameTimelineVsyncId), @@ -443,6 +444,7 @@ private: displays(displayStates), flags(transactionFlags), desiredPresentTime(desiredPresentTime), + isAutoTimestamp(isAutoTimestamp), buffer(uncacheBuffer), postTime(postTime), privileged(privileged), @@ -457,6 +459,7 @@ private: Vector displays; uint32_t flags; const int64_t desiredPresentTime; + const bool isAutoTimestamp; client_cache_t buffer; const int64_t postTime; bool privileged; @@ -520,8 +523,8 @@ private: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, const std::vector& listenerCallbacks, uint64_t transactionId) override; void bootFinished() override; @@ -723,7 +726,7 @@ private: void applyTransactionState(int64_t frameTimelineVsyncId, const Vector& state, const Vector& displays, uint32_t flags, const InputWindowCommands& inputWindowCommands, - const int64_t desiredPresentTime, + const int64_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged, bool hasListenerCallbacks, const std::vector& listenerCallbacks, diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c98004a8ab..25aaa14bb1 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -371,14 +371,14 @@ public: const Vector& displays, uint32_t flags, const sp& applyToken, const InputWindowCommands& inputWindowCommands, - int64_t desiredPresentTime, const client_cache_t& uncacheBuffer, - bool hasListenerCallbacks, + int64_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& uncacheBuffer, bool hasListenerCallbacks, std::vector& listenerCallbacks, uint64_t transactionId) { return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags, applyToken, inputWindowCommands, desiredPresentTime, - uncacheBuffer, hasListenerCallbacks, listenerCallbacks, - transactionId); + isAutoTimestamp, uncacheBuffer, hasListenerCallbacks, + listenerCallbacks, transactionId); } auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); }; diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index c36d9947b7..fa6ff301af 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -97,7 +97,8 @@ public: uint32_t flags = 0; sp applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance()); InputWindowCommands inputWindowCommands; - int64_t desiredPresentTime = -1; + int64_t desiredPresentTime = 0; + bool isAutoTimestamp = true; int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID; client_cache_t uncacheBuffer; int64_t id = -1; @@ -114,11 +115,13 @@ public: } void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows, - int64_t desiredPresentTime, int64_t frameTimelineVsyncId) { + int64_t desiredPresentTime, bool isAutoTimestamp, + int64_t frameTimelineVsyncId) { mTransactionNumber++; transaction.flags |= flags; // ISurfaceComposer::eSynchronous; transaction.inputWindowCommands.syncInputWindows = syncInputWindows; transaction.desiredPresentTime = desiredPresentTime; + transaction.isAutoTimestamp = isAutoTimestamp; transaction.frameTimelineVsyncId = frameTimelineVsyncId; } @@ -129,13 +132,15 @@ public: EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime())); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationTime = systemTime(); mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transaction.id); + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); // This transaction should not have been placed on the transaction queue. // If transaction is synchronous or syncs input windows, SF @@ -164,13 +169,15 @@ public: .WillOnce(Return(time + nsecs_t(5 * 1e8))); TransactionInfo transaction; setupSingle(transaction, flags, syncInputWindows, - /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states, transaction.displays, transaction.flags, transaction.applyToken, transaction.inputWindowCommands, - transaction.desiredPresentTime, transaction.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transaction.id); + transaction.desiredPresentTime, transaction.isAutoTimestamp, + transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transaction.id); nsecs_t returnedTime = systemTime(); EXPECT_LE(returnedTime, applicationSentTime + s2ns(5)); @@ -189,20 +196,23 @@ public: // transaction that should go on the pending thread TransactionInfo transactionA; setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ time + s2ns(1), false, + ISurfaceComposer::INVALID_VSYNC_ID); // transaction that would not have gone on the pending thread if not // blocked TransactionInfo transactionB; setupSingle(transactionB, flags, syncInputWindows, - /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true, + ISurfaceComposer::INVALID_VSYNC_ID); nsecs_t applicationSentTime = systemTime(); mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, - transactionA.desiredPresentTime, transactionA.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transactionA.id); + transactionA.desiredPresentTime, transactionA.isAutoTimestamp, + transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionA.id); // This thread should not have been blocked by the above transaction // (5s is the timeout period that applyTransactionState waits for SF to @@ -213,8 +223,9 @@ public: mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states, transactionB.displays, transactionB.flags, transactionB.applyToken, transactionB.inputWindowCommands, - transactionB.desiredPresentTime, transactionB.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, transactionB.id); + transactionB.desiredPresentTime, transactionB.isAutoTimestamp, + transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks, + transactionB.id); // this thread should have been blocked by the above transaction // if this is an animation, this thread should be blocked for 5s @@ -256,12 +267,12 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { .WillOnce(Return(s2ns(2))); TransactionInfo transactionA; // transaction to go on pending queue setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false, - /*desiredPresentTime*/ s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID); + /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID); mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states, transactionA.displays, transactionA.flags, transactionA.applyToken, transactionA.inputWindowCommands, transactionA.desiredPresentTime, - transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks, - transactionA.id); + transactionA.isAutoTimestamp, transactionA.uncacheBuffer, + mHasListenerCallbacks, mCallbacks, transactionA.id); auto& transactionQueue = mFlinger.getTransactionQueue(); ASSERT_EQ(1, transactionQueue.size()); @@ -279,8 +290,8 @@ TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) { empty.applyToken = sp(); mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays, empty.flags, empty.applyToken, empty.inputWindowCommands, - empty.desiredPresentTime, empty.uncacheBuffer, - mHasListenerCallbacks, mCallbacks, empty.id); + empty.desiredPresentTime, empty.isAutoTimestamp, + empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id); // flush transaction queue should flush as desiredPresentTime has // passed -- cgit v1.2.3-59-g8ed1b From bed7fd3566605ea21f55d99f0d0708a0f584d885 Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Mon, 21 Dec 2020 20:02:20 +0100 Subject: SF: Compile with -Wextra Compile with -Wextra for additional conversion checks. In each file which produces compile errors -Wextra is ignored. Bug: 175126758 Test: m surfaceflinger && m libsurfaceflinger_unittest Change-Id: Iec6bcc699715a99c8c65d891ab3c0481e884c728 --- libs/renderengine/tests/RenderEngineTest.cpp | 3 ++- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferQueueLayer.cpp | 3 ++- services/surfaceflinger/BufferStateLayer.cpp | 3 ++- .../include/compositionengine/DisplayColorProfile.h | 3 ++- .../include/compositionengine/DisplayColorProfileCreationArgs.h | 3 ++- .../CompositionEngine/include/compositionengine/LayerFE.h | 3 ++- .../include/compositionengine/LayerFECompositionState.h | 3 ++- .../CompositionEngine/include/compositionengine/OutputLayer.h | 3 ++- .../include/compositionengine/impl/HwcBufferCache.h | 3 ++- .../include/compositionengine/impl/OutputCompositionState.h | 3 ++- .../include/compositionengine/impl/OutputLayerCompositionState.h | 3 ++- services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp | 7 +++++++ services/surfaceflinger/CompositionEngine/tests/MockHWC2.h | 3 ++- services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h | 3 ++- .../surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp | 7 +++++++ services/surfaceflinger/DisplayHardware/ComposerHal.h | 3 ++- services/surfaceflinger/DisplayHardware/HWComposer.h | 3 ++- services/surfaceflinger/LayerProtoHelper.cpp | 3 ++- services/surfaceflinger/RefreshRateOverlay.cpp | 3 ++- services/surfaceflinger/RegionSamplingThread.cpp | 3 ++- services/surfaceflinger/Scheduler/LayerInfo.cpp | 7 +++++++ services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp | 7 +++++++ services/surfaceflinger/Scheduler/Scheduler.h | 3 ++- services/surfaceflinger/Scheduler/VSyncPredictor.cpp | 6 ++++++ services/surfaceflinger/SurfaceFlinger.cpp | 3 ++- services/surfaceflinger/TimeStats/TimeStats.h | 3 ++- services/surfaceflinger/tests/DetachChildren_test.cpp | 5 ++++- services/surfaceflinger/tests/DisplayConfigs_test.cpp | 7 +++++++ services/surfaceflinger/tests/InvalidHandles_test.cpp | 3 +++ services/surfaceflinger/tests/LayerTransactionTest.h | 3 ++- services/surfaceflinger/tests/ScreenCapture_test.cpp | 3 +++ services/surfaceflinger/tests/SurfaceInterceptor_test.cpp | 3 ++- services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp | 3 ++- services/surfaceflinger/tests/unittests/CachingTest.cpp | 3 ++- services/surfaceflinger/tests/unittests/CompositionTest.cpp | 3 ++- services/surfaceflinger/tests/unittests/DisplayIdGeneratorTest.cpp | 7 +++++++ .../surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp | 7 +++++++ .../surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h | 3 ++- services/surfaceflinger/tests/unittests/EventThreadTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/FrameTracerTest.cpp | 3 ++- services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp | 7 +++++++ services/surfaceflinger/tests/unittests/TimeStatsTest.cpp | 3 ++- .../surfaceflinger/tests/unittests/TransactionApplicationTest.cpp | 3 ++- .../surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp | 3 ++- services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp | 3 ++- services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp | 7 +++++++ services/surfaceflinger/tests/utils/TransactionUtils.h | 3 ++- 52 files changed, 181 insertions(+), 34 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index d9dfd8cc8d..47b8cad12d 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -20,6 +20,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include @@ -1844,4 +1845,4 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index fdb8aaf483..a7cd2582b7 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -3,6 +3,7 @@ cc_defaults { cflags: [ "-Wall", "-Werror", + "-Wextra", "-Wformat", "-Wthread-safety", "-Wunused", diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e8e31db236..04cec4fafe 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" @@ -661,4 +662,4 @@ void BufferQueueLayer::ContentsChangedListener::abandon() { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 7ec7f36548..bca1c69c0f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" //#define LOG_NDEBUG 0 #undef LOG_TAG @@ -870,4 +871,4 @@ uint32_t BufferStateLayer::doTransaction(uint32_t flags) { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h index 67e6deb506..df44e75625 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfile.h @@ -22,11 +22,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfileCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfileCreationArgs.h index 7eb8eb136d..1136e3d513 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfileCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayColorProfileCreationArgs.h @@ -23,11 +23,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 26f7f68dfb..018a6875bd 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -23,11 +23,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include #include diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 5a3b9ac817..c445d5b615 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -29,6 +29,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include @@ -37,7 +38,7 @@ #include "DisplayHardware/Hal.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android::compositionengine { diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index aa70ef836d..fb19216cc9 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -25,12 +25,13 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include "DisplayHardware/ComposerHal.h" #include "DisplayHardware/DisplayIdentification.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h index 2864c10fd8..aa049a8f83 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h @@ -22,11 +22,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index 06e6a6f46d..8f767d37f6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -23,11 +23,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include #include diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index d2b38d1815..9a118d3f3a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -30,11 +30,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include "DisplayHardware/ComposerHal.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index 1befbf8306..348ec398ae 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include #include @@ -1043,3 +1047,6 @@ TEST_F(DisplayFunctionalTest, postFramebufferCriticalCallsAreOrdered) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h index 87911ccacf..95186599fc 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h @@ -27,12 +27,13 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include "DisplayHardware/HWC2.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { namespace HWC2 { diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h index 84c027bfd3..e64a9f1855 100644 --- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h +++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h @@ -22,11 +22,12 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include "DisplayHardware/HWComposer.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { namespace mock { diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 6ce8a6b2ea..cd39733839 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include #include @@ -359,3 +363,6 @@ TEST_F(RenderSurfaceTest, flipForwardsSignal) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 5b66809d53..c756d658a4 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -26,6 +26,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include @@ -38,7 +39,7 @@ #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" namespace android { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index d8af5bf449..50c98530aa 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -32,8 +32,9 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include -#pragma clang diagnostic pop +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include #include diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index 59fad9bf0f..b1db6d34a3 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include "LayerProtoHelper.h" @@ -173,4 +174,4 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index c291b7f2e0..6a511a85a0 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include @@ -262,4 +263,4 @@ void RefreshRateOverlay::reset() { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index ad4877bdeb..f450ea5f2f 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -501,4 +502,4 @@ void RegionSamplingThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 1c0065c9ad..b0dffd1846 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + // #define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -298,3 +302,6 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index cd03c180c0..200701209b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -17,6 +17,10 @@ // #define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include "RefreshRateConfigs.h" #include #include @@ -791,3 +795,6 @@ void RefreshRateConfigs::dump(std::string& result) const { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 052c425e76..5a09b1f114 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -26,8 +26,9 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include -#pragma clang diagnostic pop +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include "EventThread.h" #include "LayerHistory.h" diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index a6f9372a5c..7cca206357 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 #include "VSyncPredictor.h" @@ -339,3 +343,5 @@ void VSyncPredictor::dump(std::string& result) const { } // namespace android::scheduler +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 68d2a68322..57e02f183c 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -6394,4 +6395,4 @@ int SurfaceFlinger::getGPUContextPriority() { #endif // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index a83b2bfae6..8fac8e9102 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -20,11 +20,12 @@ #include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" #include #include diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp index 9c7b1fcc04..abf8b1a2b9 100644 --- a/services/surfaceflinger/tests/DetachChildren_test.cpp +++ b/services/surfaceflinger/tests/DetachChildren_test.cpp @@ -371,4 +371,7 @@ TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) { } } -} // namespace android \ No newline at end of file +} // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index 3a8b40fd67..55b317382e 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include #include #include @@ -143,3 +147,6 @@ TEST_F(RefreshRateRangeTest, setAllowGroupSwitching) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp index 152d2d26f4..58b039e5d5 100644 --- a/services/surfaceflinger/tests/InvalidHandles_test.cpp +++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp @@ -70,3 +70,6 @@ TEST_F(InvalidHandleTest, captureLayersInvalidHandle) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index b87c734e27..67585185f9 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -19,6 +19,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include @@ -306,4 +307,4 @@ private: } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 7df3711183..214a0cd276 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -837,3 +837,6 @@ TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 81e648aaef..8dc9a1212f 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include @@ -1043,4 +1044,4 @@ TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { } // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index a24aeba6f0..bd49728215 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -2017,4 +2018,4 @@ int main(int argc, char** argv) { } // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp index 1b8c76d1b9..6bc23188a2 100644 --- a/services/surfaceflinger/tests/unittests/CachingTest.cpp +++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "CachingTest" @@ -97,4 +98,4 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index be9d336137..83e3ba414e 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -1533,4 +1534,4 @@ TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirt } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/DisplayIdGeneratorTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdGeneratorTest.cpp index be7609a1a0..77a3e1449f 100644 --- a/services/surfaceflinger/tests/unittests/DisplayIdGeneratorTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayIdGeneratorTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include #include @@ -80,3 +84,6 @@ TEST(DisplayIdGeneratorTest, maxIdsCount) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp index 02ce07904e..dc04b6d91d 100644 --- a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include #include @@ -409,3 +413,6 @@ TEST(DisplayIdentificationTest, getVirtualDisplayId) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h index 01cdb2896f..06c0f8ed30 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h @@ -19,6 +19,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include #include "DisplayIdentificationTest.h" @@ -753,4 +754,4 @@ using HwcVirtualDisplayCase = } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index ee56178169..0cd50cee3b 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -623,3 +627,6 @@ TEST_F(EventThreadTest, requestNextVsyncWithThrottleVsyncDoesntPostVSync) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp index 4b897fa17c..169698ba70 100644 --- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #include "gmock/gmock-spec-builders.h" #include "mock/MockTimeStats.h" #undef LOG_TAG @@ -1333,3 +1337,6 @@ TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadli JankType::AppDeadlineMissed | JankType::BufferStuffing); } } // namespace android::frametimeline + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index a119e27d41..2c71a2e45a 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -381,4 +382,4 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index cbc1e0203a..2ee9c64478 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "LayerHistoryTest" @@ -754,3 +758,6 @@ INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryTestParameterized, } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp index 75a061bf77..373fd74020 100644 --- a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -107,3 +111,6 @@ TEST_F(LayerMetadataTest, merge) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 29be5aba47..45f0ee6d38 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -1656,3 +1660,6 @@ TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index e93d0d0805..218840230b 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -216,3 +220,6 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index ace370f283..fb9afd4045 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -1320,4 +1321,4 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index fa6ff301af..06275c6b5b 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -344,4 +345,4 @@ TEST_F(TransactionApplicationTest, FromHandle) { } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index 72b5396047..00cf574cb2 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -1152,4 +1153,4 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, runCallbackWithReadyDuration) { } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index a1420225ca..a4ddbf46d8 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -17,6 +17,7 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -492,4 +493,4 @@ TEST_F(VSyncPredictorTest, InconsistentVsyncValueIsFlushedEventually) { } // namespace android::scheduler // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp index a7568e4293..b9651ea672 100644 --- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wextra" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 @@ -491,3 +495,6 @@ TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wextra" \ No newline at end of file diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 5c5b18ec1c..3cbfed98f5 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -18,6 +18,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" +#pragma clang diagnostic ignored "-Wextra" #include @@ -186,4 +187,4 @@ public: } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file +#pragma clang diagnostic pop // ignored "-Wconversion -Wextra" \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From eadf2e71ec770dceb781f393a2ce813bc0912aac Mon Sep 17 00:00:00 2001 From: Marin Shalamanov Date: Thu, 10 Dec 2020 15:35:28 +0100 Subject: SF: Mutable RefreshRateConfigs Modify the list of supported refresh rates in RefreshRateConfigs on hotplug. In order to support this the RefreshRateConfigs class is refactored to not return references to its internal members, but instead return copies. This won't be expensive because the RefreshRate objects which are returned are small. Bug: 159590486 Test: 1. boot w/o display 2. connect a display which supports multiple refresh rates 3. request a mode switch from an app 4. verify that the switch works Test: atest libsurfaceflinger_unittest Test: toggle refresh rate overlay adb shell service call SurfaceFlinger 1034 i32 1/0 Change-Id: I1588bf004a0a0319a94931adbfb822836703849a --- services/surfaceflinger/RefreshRateOverlay.cpp | 9 +- services/surfaceflinger/RefreshRateOverlay.h | 6 +- .../Scheduler/RefreshRateConfigs.cpp | 98 +++++++++++-------- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 106 +++++++++++---------- services/surfaceflinger/Scheduler/Scheduler.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 36 +++---- .../tests/unittests/RefreshRateConfigsTest.cpp | 51 ++++++---- 7 files changed, 175 insertions(+), 135 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 6a511a85a0..a0f91c26b2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -233,8 +233,8 @@ void RefreshRateOverlay::setViewport(ui::Size viewport) { mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } -void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { - mCurrentFps = refreshRate.getFps().getIntValue(); +void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { + mCurrentFps = fps.getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); @@ -256,8 +256,9 @@ void RefreshRateOverlay::onInvalidate() { void RefreshRateOverlay::reset() { mBufferCache.clear(); - mLowFps = mFlinger.mRefreshRateConfigs->getMinRefreshRate().getFps().getIntValue(); - mHighFps = mFlinger.mRefreshRateConfigs->getMaxRefreshRate().getFps().getIntValue(); + const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange(); + mLowFps = range.min.getIntValue(); + mHighFps = range.max.getIntValue(); } } // namespace android diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index 4ca1337c67..c16cfa07a4 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -23,7 +23,7 @@ #include #include -#include "Scheduler/RefreshRateConfigs.h" +#include "Fps.h" namespace android { @@ -34,14 +34,12 @@ class IGraphicBufferProducer; class Layer; class SurfaceFlinger; -using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; - class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger&, bool showSpinner); void setViewport(ui::Size); - void changeRefreshRate(const RefreshRate&); + void changeRefreshRate(const Fps&); void onInvalidate(); void reset(); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 35b382ed05..4677db9981 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -38,6 +38,26 @@ std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, f toString(layer.seamlessness).c_str(), to_string(layer.desiredRefreshRate).c_str()); } + +std::vector constructKnownFrameRates( + const std::vector>& configs) { + std::vector knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; + knownFrameRates.reserve(knownFrameRates.size() + configs.size()); + + // Add all supported refresh rates to the set + for (const auto& config : configs) { + const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); + knownFrameRates.emplace_back(refreshRate); + } + + // Sort and remove duplicates + std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); + knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), + Fps::EqualsWithMargin()), + knownFrameRates.end()); + return knownFrameRates; +} + } // namespace using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; @@ -153,9 +173,9 @@ struct RefreshRateScore { float score; }; -const RefreshRate& RefreshRateConfigs::getBestRefreshRate( - const std::vector& layers, const GlobalSignals& globalSignals, - GlobalSignals* outSignalsConsidered) const { +RefreshRate RefreshRateConfigs::getBestRefreshRate(const std::vector& layers, + const GlobalSignals& globalSignals, + GlobalSignals* outSignalsConsidered) const { ATRACE_CALL(); ALOGV("getBestRefreshRate %zu layers", layers.size()); @@ -468,9 +488,20 @@ const RefreshRate* RefreshRateConfigs::getBestRefreshRate(Iter begin, Iter end) return bestRefreshRate; } -const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { +std::optional RefreshRateConfigs::onKernelTimerChanged( + std::optional desiredActiveConfigId, bool timerExpired) const { std::lock_guard lock(mLock); - return getMinRefreshRateByPolicyLocked(); + + const auto& current = desiredActiveConfigId ? *mRefreshRates.at(*desiredActiveConfigId) + : *mCurrentRefreshRate; + const auto& min = *mMinSupportedRefreshRate; + + if (current != min) { + const auto& refreshRate = timerExpired ? min : current; + return refreshRate.getFps(); + } + + return {}; } const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { @@ -486,7 +517,7 @@ const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.front(); } -const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { +RefreshRate RefreshRateConfigs::getMaxRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getMaxRefreshRateByPolicyLocked(); } @@ -505,12 +536,12 @@ const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const { return *mPrimaryRefreshRates.back(); } -const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { +RefreshRate RefreshRateConfigs::getCurrentRefreshRate() const { std::lock_guard lock(mLock); return *mCurrentRefreshRate; } -const RefreshRate& RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { +RefreshRate RefreshRateConfigs::getCurrentRefreshRateByPolicy() const { std::lock_guard lock(mLock); return getCurrentRefreshRateByPolicyLocked(); } @@ -532,16 +563,23 @@ RefreshRateConfigs::RefreshRateConfigs( const std::vector>& configs, HwcConfigIndexType currentConfigId) : mKnownFrameRates(constructKnownFrameRates(configs)) { + updateDisplayConfigs(configs, currentConfigId); +} + +void RefreshRateConfigs::updateDisplayConfigs( + const std::vector>& configs, + HwcConfigIndexType currentConfigId) { + std::lock_guard lock(mLock); LOG_ALWAYS_FATAL_IF(configs.empty()); LOG_ALWAYS_FATAL_IF(currentConfigId.value() < 0); LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size()); + mRefreshRates.clear(); for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) { const auto& config = configs.at(static_cast(configId.value())); + const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod()); mRefreshRates.emplace(configId, - std::make_unique(configId, config, - Fps::fromPeriodNsecs( - config->getVsyncPeriod()), + std::make_unique(configId, config, fps, RefreshRate::ConstructorTag(0))); if (configId == currentConfigId) { mCurrentRefreshRate = mRefreshRates.at(configId).get(); @@ -549,7 +587,7 @@ RefreshRateConfigs::RefreshRateConfigs( } std::vector sortedConfigs; - getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); + getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs); mDisplayManagerPolicy.defaultConfig = currentConfigId; mMinSupportedRefreshRate = sortedConfigs.front(); mMaxSupportedRefreshRate = sortedConfigs.back(); @@ -566,7 +604,7 @@ RefreshRateConfigs::RefreshRateConfigs( constructAvailableRefreshRates(); } -bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { +bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const { // defaultConfig must be a valid config, and within the given refresh rate range. auto iter = mRefreshRates.find(policy.defaultConfig); if (iter == mRefreshRates.end()) { @@ -584,7 +622,7 @@ bool RefreshRateConfigs::isPolicyValid(const Policy& policy) { status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { std::lock_guard lock(mLock); - if (!isPolicyValid(policy)) { + if (!isPolicyValidLocked(policy)) { ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str()); return BAD_VALUE; } @@ -599,7 +637,7 @@ status_t RefreshRateConfigs::setDisplayManagerPolicy(const Policy& policy) { status_t RefreshRateConfigs::setOverridePolicy(const std::optional& policy) { std::lock_guard lock(mLock); - if (policy && !isPolicyValid(*policy)) { + if (policy && !isPolicyValidLocked(*policy)) { return BAD_VALUE; } Policy previousPolicy = *getCurrentPolicyLocked(); @@ -635,14 +673,14 @@ bool RefreshRateConfigs::isConfigAllowed(HwcConfigIndexType config) const { return false; } -void RefreshRateConfigs::getSortedRefreshRateList( +void RefreshRateConfigs::getSortedRefreshRateListLocked( const std::function& shouldAddRefreshRate, std::vector* outRefreshRates) { outRefreshRates->clear(); outRefreshRates->reserve(mRefreshRates.size()); for (const auto& [type, refreshRate] : mRefreshRates) { if (shouldAddRefreshRate(*refreshRate)) { - ALOGV("getSortedRefreshRateList: config %d added to list policy", + ALOGV("getSortedRefreshRateListLocked: config %d added to list policy", refreshRate->configId.value()); outRefreshRates->push_back(refreshRate.get()); } @@ -668,8 +706,9 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str()); auto filterRefreshRates = [&](Fps min, Fps max, const char* listName, - std::vector* outRefreshRates) { - getSortedRefreshRateList( + std::vector* + outRefreshRates) REQUIRES(mLock) { + getSortedRefreshRateListLocked( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { const auto& hwcConfig = refreshRate.hwcConfig; @@ -702,25 +741,6 @@ void RefreshRateConfigs::constructAvailableRefreshRates() { &mAppRequestRefreshRates); } -std::vector RefreshRateConfigs::constructKnownFrameRates( - const std::vector>& configs) { - std::vector knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)}; - knownFrameRates.reserve(knownFrameRates.size() + configs.size()); - - // Add all supported refresh rates to the set - for (const auto& config : configs) { - const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod()); - knownFrameRates.emplace_back(refreshRate); - } - - // Sort and remove duplicates - std::sort(knownFrameRates.begin(), knownFrameRates.end(), Fps::comparesLess); - knownFrameRates.erase(std::unique(knownFrameRates.begin(), knownFrameRates.end(), - Fps::EqualsWithMargin()), - knownFrameRates.end()); - return knownFrameRates; -} - Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { if (frameRate.lessThanOrEqualWithMargin(*mKnownFrameRates.begin())) { return *mKnownFrameRates.begin(); @@ -740,7 +760,7 @@ Fps RefreshRateConfigs::findClosestKnownFrameRate(Fps frameRate) const { RefreshRateConfigs::KernelIdleTimerAction RefreshRateConfigs::getIdleTimerAction() const { std::lock_guard lock(mLock); - const auto& deviceMin = getMinRefreshRate(); + const auto& deviceMin = *mMinSupportedRefreshRate; const auto& minByPolicy = getMinRefreshRateByPolicyLocked(); const auto& maxByPolicy = getMaxRefreshRateByPolicyLocked(); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index e4bbf7f516..4b99145184 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -68,8 +68,6 @@ public: std::shared_ptr config, Fps fps, ConstructorTag) : configId(configId), hwcConfig(config), fps(std::move(fps)) {} - RefreshRate(const RefreshRate&) = delete; - HwcConfigIndexType getConfigId() const { return configId; } nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); } int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); } @@ -111,27 +109,26 @@ public: using AllRefreshRatesMapType = std::unordered_map>; - struct Policy { - private: - static constexpr int kAllowGroupSwitchingDefault = false; + struct FpsRange { + Fps min{0.0f}; + Fps max{std::numeric_limits::max()}; - public: - struct Range { - Fps min{0.0f}; - Fps max{std::numeric_limits::max()}; + bool operator==(const FpsRange& other) const { + return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); + } - bool operator==(const Range& other) const { - return min.equalsWithMargin(other.min) && max.equalsWithMargin(other.max); - } + bool operator!=(const FpsRange& other) const { return !(*this == other); } - bool operator!=(const Range& other) const { return !(*this == other); } + std::string toString() const { + return base::StringPrintf("[%s %s]", to_string(min).c_str(), to_string(max).c_str()); + } + }; - std::string toString() const { - return base::StringPrintf("[%s %s]", to_string(min).c_str(), - to_string(max).c_str()); - } - }; + struct Policy { + private: + static constexpr int kAllowGroupSwitchingDefault = false; + public: // The default config, used to ensure we only initiate display config switches within the // same config group as defaultConfigId's group. HwcConfigIndexType defaultConfig; @@ -140,29 +137,29 @@ public: // The primary refresh rate range represents display manager's general guidance on the // display configs we'll consider when switching refresh rates. Unless we get an explicit // signal from an app, we should stay within this range. - Range primaryRange; + FpsRange primaryRange; // The app request refresh rate range allows us to consider more display configs when // switching refresh rates. Although we should generally stay within the primary range, // specific considerations, such as layer frame rate settings specified via the // setFrameRate() api, may cause us to go outside the primary range. We never go outside the // app request range. The app request range will be greater than or equal to the primary // refresh rate range, never smaller. - Range appRequestRange; + FpsRange appRequestRange; Policy() = default; - Policy(HwcConfigIndexType defaultConfig, const Range& range) + Policy(HwcConfigIndexType defaultConfig, const FpsRange& range) : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {} - Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const Range& range) + Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, const FpsRange& range) : Policy(defaultConfig, allowGroupSwitching, range, range) {} - Policy(HwcConfigIndexType defaultConfig, const Range& primaryRange, - const Range& appRequestRange) + Policy(HwcConfigIndexType defaultConfig, const FpsRange& primaryRange, + const FpsRange& appRequestRange) : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {} Policy(HwcConfigIndexType defaultConfig, bool allowGroupSwitching, - const Range& primaryRange, const Range& appRequestRange) + const FpsRange& primaryRange, const FpsRange& appRequestRange) : defaultConfig(defaultConfig), allowGroupSwitching(allowGroupSwitching), primaryRange(primaryRange), @@ -258,35 +255,35 @@ public: // globalSignals - global state of touch and idle // outSignalsConsidered - An output param that tells the caller whether the refresh rate was // chosen based on touch boost and/or idle timer. - const RefreshRate& getBestRefreshRate(const std::vector& layers, - const GlobalSignals& globalSignals, - GlobalSignals* outSignalsConsidered = nullptr) const + RefreshRate getBestRefreshRate(const std::vector& layers, + const GlobalSignals& globalSignals, + GlobalSignals* outSignalsConsidered = nullptr) const EXCLUDES(mLock); - // Returns the lowest refresh rate supported by the device. This won't change at runtime. - const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } + FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) { + std::lock_guard lock(mLock); + return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()}; + } - // Returns the lowest refresh rate according to the current policy. May change at runtime. Only - // uses the primary range, not the app request range. - const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); - - // Returns the highest refresh rate supported by the device. This won't change at runtime. - const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } + std::optional onKernelTimerChanged(std::optional desiredActiveConfigId, + bool timerExpired) const EXCLUDES(mLock); // Returns the highest refresh rate according to the current policy. May change at runtime. Only // uses the primary range, not the app request range. - const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); + RefreshRate getMaxRefreshRateByPolicy() const EXCLUDES(mLock); // Returns the current refresh rate - const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock); + RefreshRate getCurrentRefreshRate() const EXCLUDES(mLock); // Returns the current refresh rate, if allowed. Otherwise the default that is allowed by // the policy. - const RefreshRate& getCurrentRefreshRateByPolicy() const; + RefreshRate getCurrentRefreshRateByPolicy() const; - // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at + // Returns the refresh rate that corresponds to a HwcConfigIndexType. This may change at // runtime. - const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { + // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed. + RefreshRate getRefreshRateFromConfigId(HwcConfigIndexType configId) const EXCLUDES(mLock) { + std::lock_guard lock(mLock); return *mRefreshRates.at(configId); }; @@ -302,10 +299,17 @@ public: RefreshRateConfigs(const std::vector>& configs, HwcConfigIndexType currentConfigId); + void updateDisplayConfigs( + const std::vector>& configs, + HwcConfigIndexType currentConfig) EXCLUDES(mLock); + // Returns whether switching configs (refresh rate or resolution) is possible. // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only // differ in resolution. - bool canSwitch() const { return mRefreshRates.size() > 1; } + bool canSwitch() const EXCLUDES(mLock) { + std::lock_guard lock(mLock); + return mRefreshRates.size() > 1; + } // Class to enumerate options around toggling the kernel timer on and off. We have an option // for no change to avoid extra calls to kernel. @@ -334,12 +338,10 @@ private: friend class RefreshRateConfigsTest; void constructAvailableRefreshRates() REQUIRES(mLock); - static std::vector constructKnownFrameRates( - const std::vector>& configs); - void getSortedRefreshRateList( + void getSortedRefreshRateListLocked( const std::function& shouldAddRefreshRate, - std::vector* outRefreshRates); + std::vector* outRefreshRates) REQUIRES(mLock); // Returns the refresh rate with the highest score in the collection specified from begin // to end. If there are more than one with the same highest refresh rate, the first one is @@ -364,7 +366,7 @@ private: const RefreshRate& getCurrentRefreshRateByPolicyLocked() const REQUIRES(mLock); const Policy* getCurrentPolicyLocked() const REQUIRES(mLock); - bool isPolicyValid(const Policy& policy); + bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock); // Return the display refresh rate divider to match the layer // frame rate, or 0 if the display refresh rate is not a multiple of the @@ -376,9 +378,9 @@ private: float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&, bool isSeamlessSwitch) const REQUIRES(mLock); - // The list of refresh rates, indexed by display config ID. This must not change after this + // The list of refresh rates, indexed by display config ID. This may change after this // object is initialized. - AllRefreshRatesMapType mRefreshRates; + AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock); // The list of refresh rates in the primary range of the current policy, ordered by vsyncPeriod // (the first element is the lowest refresh rate). @@ -398,9 +400,9 @@ private: std::optional mOverridePolicy GUARDED_BY(mLock); // The min and max refresh rates supported by the device. - // This will not change at runtime. - const RefreshRate* mMinSupportedRefreshRate; - const RefreshRate* mMaxSupportedRefreshRate; + // This may change at runtime. + const RefreshRate* mMinSupportedRefreshRate GUARDED_BY(mLock); + const RefreshRate* mMaxSupportedRefreshRate GUARDED_BY(mLock); mutable std::mutex mLock; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 18c899bc0f..49e3903eb2 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -612,7 +612,7 @@ void Scheduler::chooseRefreshRateForContent() { mFeatures.contentRequirements = summary; newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals); - auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps()); @@ -629,7 +629,7 @@ void Scheduler::chooseRefreshRateForContent() { } } if (frameRateChanged) { - auto& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, consideredSignals.idle ? ConfigEvent::None : ConfigEvent::Changed); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6967f69876..abffb0b698 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -995,7 +995,7 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); - auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str()); std::lock_guard lock(mActiveConfigLock); @@ -1030,7 +1030,7 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { } if (mRefreshRateOverlay) { - mRefreshRateOverlay->changeRefreshRate(refreshRate); + mRefreshRateOverlay->changeRefreshRate(refreshRate.getFps()); } } @@ -1076,14 +1076,14 @@ void SurfaceFlinger::setActiveConfigInternal() { return; } - auto& oldRefreshRate = + auto oldRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(display->getActiveConfig()); std::lock_guard lock(mActiveConfigLock); mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId); display->setActiveConfig(mUpcomingActiveConfig.configId); - auto& refreshRate = + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); mRefreshRateStats->setRefreshRate(refreshRate.getFps()); @@ -1126,7 +1126,7 @@ void SurfaceFlinger::performSetActiveConfig() { return; } - auto& refreshRate = + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId); ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.getConfigId().value(), refreshRate.getName().c_str()); @@ -2621,6 +2621,9 @@ void SurfaceFlinger::processDisplayChanged(const wp& displayToken, if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) { const auto displayId = currentState.physical->id; const auto configs = getHwComposer().getConfigs(displayId); + const auto currentConfig = + HwcConfigIndexType(getHwComposer().getActiveConfigIndex(displayId)); + mRefreshRateConfigs->updateDisplayConfigs(configs, currentConfig); mVsyncConfiguration->reset(); updatePhaseConfiguration(mRefreshRateConfigs->getCurrentRefreshRate()); if (mRefreshRateOverlay) { @@ -5406,16 +5409,16 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { // mRefreshRateConfigs->getCurrentRefreshRate() static_cast(schedule([=] { const auto desiredActiveConfig = getDesiredActiveConfig(); - const auto& current = desiredActiveConfig - ? mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig->configId) - : mRefreshRateConfigs->getCurrentRefreshRate(); - const auto& min = mRefreshRateConfigs->getMinRefreshRate(); - - if (current != min) { - const bool timerExpired = mKernelIdleTimerEnabled && expired; - + const std::optional desiredConfigId = desiredActiveConfig + ? std::make_optional(desiredActiveConfig->configId) + : std::nullopt; + + const bool timerExpired = mKernelIdleTimerEnabled && expired; + const auto newRefreshRate = + mRefreshRateConfigs->onKernelTimerChanged(desiredConfigId, timerExpired); + if (newRefreshRate) { if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) { - mRefreshRateOverlay->changeRefreshRate(timerExpired ? min : current); + mRefreshRateOverlay->changeRefreshRate(*newRefreshRate); } mEventQueue->invalidate(); } @@ -6065,7 +6068,7 @@ status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal( toggleKernelIdleTimer(); auto configId = mScheduler->getPreferredConfigId(); - auto& preferredRefreshRate = configId + auto preferredRefreshRate = configId ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind. : mRefreshRateConfigs->getRefreshRateFromConfigId(currentPolicy.defaultConfig); @@ -6371,7 +6374,8 @@ void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { mRefreshRateOverlay->setViewport(display->getSize()); } - mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + mRefreshRateOverlay->changeRefreshRate( + mRefreshRateConfigs->getCurrentRefreshRate().getFps()); } })); } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 45f0ee6d38..0813968334 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -56,6 +56,21 @@ protected: return refreshRateConfigs.mKnownFrameRates; } + RefreshRate getMinRefreshRateByPolicy(const RefreshRateConfigs& refreshRateConfigs) { + std::lock_guard lock(refreshRateConfigs.mLock); + return refreshRateConfigs.getMinRefreshRateByPolicyLocked(); + } + + RefreshRate getMinSupportedRefreshRate(const RefreshRateConfigs& refreshRateConfigs) { + std::lock_guard lock(refreshRateConfigs.mLock); + return *refreshRateConfigs.mMinSupportedRefreshRate; + } + + RefreshRate getMaxSupportedRefreshRate(const RefreshRateConfigs& refreshRateConfigs) { + std::lock_guard lock(refreshRateConfigs.mLock); + return *refreshRateConfigs.mMaxSupportedRefreshRate; + } + // Test config IDs static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); @@ -209,13 +224,13 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { std::make_unique(m60_90Device, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto& minRate = refreshRateConfigs->getMinRefreshRate(); - const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto& minRate = getMinSupportedRefreshRate(*refreshRateConfigs); + const auto& performanceRate = getMaxSupportedRefreshRate(*refreshRateConfigs); ASSERT_EQ(mExpected60Config, minRate); ASSERT_EQ(mExpected90Config, performanceRate); - const auto& minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& minRateByPolicy = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(minRateByPolicy, minRate); ASSERT_EQ(performanceRateByPolicy, performanceRate); @@ -226,9 +241,9 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe std::make_unique(m60_90DeviceWithDifferentGroups, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); - const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& minRate = getMinRefreshRateByPolicy(*refreshRateConfigs); + const auto& performanceRate = getMaxSupportedRefreshRate(*refreshRateConfigs); + const auto& minRate60 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected60Config, minRate); @@ -239,7 +254,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected90DifferentGroupConfig, performanceRate); @@ -252,9 +267,9 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe std::make_unique(m60_90DeviceWithDifferentResolutions, /*currentConfigId=*/HWC_CONFIG_ID_60); - const auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - const auto& performanceRate = refreshRateConfigs->getMaxRefreshRate(); - const auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& minRate = getMinRefreshRateByPolicy(*refreshRateConfigs); + const auto& performanceRate = getMaxSupportedRefreshRate(*refreshRateConfigs); + const auto& minRate60 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected60Config, minRate); @@ -265,7 +280,7 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differe 0); refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); - const auto& minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs); const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected90DifferentResolutionConfig, performanceRate); @@ -278,8 +293,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { std::make_unique(m60_90Device, /*currentConfigId=*/HWC_CONFIG_ID_60); - auto& minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto& performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto minRate = getMinRefreshRateByPolicy(*refreshRateConfigs); + auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected60Config, minRate); ASSERT_EQ(mExpected90Config, performanceRate); @@ -287,8 +302,8 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {Fps(60), Fps(60)}}), 0); - auto& minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); - auto& performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + auto minRate60 = getMinRefreshRateByPolicy(*refreshRateConfigs); + auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); ASSERT_EQ(mExpected60Config, minRate60); ASSERT_EQ(mExpected60Config, performanceRate60); } @@ -298,20 +313,20 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { std::make_unique(m60_90Device, /*currentConfigId=*/HWC_CONFIG_ID_60); { - auto& current = refreshRateConfigs->getCurrentRefreshRate(); + auto current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_60); } refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); { - auto& current = refreshRateConfigs->getCurrentRefreshRate(); + auto current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}), 0); { - auto& current = refreshRateConfigs->getCurrentRefreshRate(); + auto current = refreshRateConfigs->getCurrentRefreshRate(); EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90); } } -- cgit v1.2.3-59-g8ed1b From adf632ba3a3298b4e66edfc468cf3888d5f2eac4 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Thu, 7 Jan 2021 14:05:08 -0800 Subject: BlastBufferQueue: Pass client dequeue times to SurfaceFlinger SF keeps track of client dequeue, queue, acquire etc. timestamps to construct frame rendering timelines for developers. With BBQ, SF no longer has access to this data, so pass the dequeue time along with the buffers. Ideally this data should flow to the perfetto trace directly from the client but this is a temp solution while some perf issues with client logging is sorted out. Bug: 176931912 Test: manual tests Change-Id: Ic88170c1fb20850662cb99325ac42b7232a02817 --- aidl/gui/android/view/LayerMetadataKey.aidl | 1 + libs/gui/BLASTBufferQueue.cpp | 20 ++++++++++++++++++++ libs/gui/LayerMetadata.cpp | 12 ++++++++++++ libs/gui/include/gui/BLASTBufferQueue.h | 12 +++++++++++- libs/gui/include/gui/LayerMetadata.h | 3 +++ services/surfaceflinger/BufferStateLayer.cpp | 3 ++- services/surfaceflinger/BufferStateLayer.h | 3 ++- services/surfaceflinger/Layer.h | 2 +- services/surfaceflinger/RefreshRateOverlay.cpp | 6 ++++-- services/surfaceflinger/SurfaceFlinger.cpp | 4 +++- 10 files changed, 59 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/aidl/gui/android/view/LayerMetadataKey.aidl b/aidl/gui/android/view/LayerMetadataKey.aidl index 491c629278..a1d8ce5962 100644 --- a/aidl/gui/android/view/LayerMetadataKey.aidl +++ b/aidl/gui/android/view/LayerMetadataKey.aidl @@ -25,4 +25,5 @@ enum LayerMetadataKey { METADATA_MOUSE_CURSOR = 4, METADATA_ACCESSIBILITY_ID = 5, METADATA_OWNER_PID = 6, + METADATA_DEQUEUE_TIME = 7, } diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index eaa47f9680..f4b5a26033 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -354,6 +354,16 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { t->setAutoRefresh(mSurfaceControl, bufferItem.mAutoRefresh); mAutoRefresh = bufferItem.mAutoRefresh; } + { + std::unique_lock _lock{mTimestampMutex}; + auto dequeueTime = mDequeueTimestamps.find(buffer->getId()); + if (dequeueTime != mDequeueTimestamps.end()) { + Parcel p; + p.writeInt64(dequeueTime->second); + t->setMetadata(mSurfaceControl, METADATA_DEQUEUE_TIME, p); + mDequeueTimestamps.erase(dequeueTime); + } + } auto mergeTransaction = [&t, currentFrameNumber = bufferItem.mFrameNumber]( @@ -412,6 +422,16 @@ void BLASTBufferQueue::onFrameReplaced(const BufferItem& item) { // Do nothing since we are not storing unacquired buffer items locally. } +void BLASTBufferQueue::onFrameDequeued(const uint64_t bufferId) { + std::unique_lock _lock{mTimestampMutex}; + mDequeueTimestamps[bufferId] = systemTime(); +}; + +void BLASTBufferQueue::onFrameCancelled(const uint64_t bufferId) { + std::unique_lock _lock{mTimestampMutex}; + mDequeueTimestamps.erase(bufferId); +}; + void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) { std::lock_guard _lock{mMutex}; mNextTransaction = t; diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp index 30c9b373ef..634d8b7df0 100644 --- a/libs/gui/LayerMetadata.cpp +++ b/libs/gui/LayerMetadata.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "android/view/LayerMetadataKey.h" @@ -113,6 +114,15 @@ void LayerMetadata::setInt32(uint32_t key, int32_t value) { memcpy(data.data(), p.data(), p.dataSize()); } +std::optional LayerMetadata::getInt64(uint32_t key) const { + if (!has(key)) return std::nullopt; + const std::vector& data = mMap.at(key); + if (data.size() < sizeof(int64_t)) return std::nullopt; + Parcel p; + p.setData(data.data(), data.size()); + return p.readInt64(); +} + std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const { if (!has(key)) return std::string(); switch (static_cast(key)) { @@ -124,6 +134,8 @@ std::string LayerMetadata::itemToString(uint32_t key, const char* separator) con return StringPrintf("taskId%s%d", separator, getInt32(key, 0)); case view::LayerMetadataKey::METADATA_OWNER_PID: return StringPrintf("ownerPID%s%d", separator, getInt32(key, 0)); + case view::LayerMetadataKey::METADATA_DEQUEUE_TIME: + return StringPrintf("dequeueTime%s%" PRId64, separator, *getInt64(key)); default: return StringPrintf("%d%s%dbytes", key, separator, static_cast(mMap.at(key).size())); diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index 1198135b0c..0fbcbdc50f 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -78,6 +78,8 @@ public: void onBufferFreed(const wp&/* graphicBuffer*/) override { /* TODO */ } void onFrameReplaced(const BufferItem& item) override; void onFrameAvailable(const BufferItem& item) override; + void onFrameDequeued(const uint64_t) override; + void onFrameCancelled(const uint64_t) override; void transactionCallback(nsecs_t latchTime, const sp& presentFence, const std::vector& stats); @@ -168,7 +170,15 @@ private: // Queues up transactions using this token in SurfaceFlinger. This prevents queued up // transactions from other parts of the client from blocking this transaction. - const sp mApplyToken = new BBinder(); + const sp mApplyToken GUARDED_BY(mMutex) = new BBinder(); + + // Guards access to mDequeueTimestamps since we cannot hold to mMutex in onFrameDequeued or + // we will deadlock. + std::mutex mTimestampMutex; + // Tracks buffer dequeue times by the client. This info is sent to SurfaceFlinger which uses + // it for debugging purposes. + std::unordered_map mDequeueTimestamps + GUARDED_BY(mTimestampMutex); }; } // namespace android diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h index ac48aefae6..41982c28a2 100644 --- a/libs/gui/include/gui/LayerMetadata.h +++ b/libs/gui/include/gui/LayerMetadata.h @@ -29,6 +29,7 @@ enum { METADATA_MOUSE_CURSOR = 4, METADATA_ACCESSIBILITY_ID = 5, METADATA_OWNER_PID = 6, + METADATA_DEQUEUE_TIME = 7 }; struct LayerMetadata : public Parcelable { @@ -51,6 +52,8 @@ struct LayerMetadata : public Parcelable { bool has(uint32_t key) const; int32_t getInt32(uint32_t key, int32_t fallback) const; void setInt32(uint32_t key, int32_t value); + std::optional getInt64(uint32_t key) const; + void setInt64(uint32_t key, int64_t value); std::string itemToString(uint32_t key, const char* separator) const; }; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index bca1c69c0f..a431028bde 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -343,7 +343,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber) { + const client_cache_t& clientCacheId, uint64_t frameNumber, + std::optional /* dequeueTime */) { ATRACE_CALL(); if (mCurrentState.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 6414e6be60..1098606cbb 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -71,7 +71,8 @@ public: bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber) override; + const client_cache_t& clientCacheId, uint64_t frameNumber, + std::optional dequeueTime) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d6023b66ac..f78b5f31e9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -446,7 +446,7 @@ public: virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, - uint64_t /* frameNumber */) { + uint64_t /* frameNumber */, std::optional /* dequeueTime */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 6a511a85a0..32110e9547 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -237,7 +237,8 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { mCurrentFps = refreshRate.getFps().getIntValue(); auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, - mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), + std::nullopt /* dequeueTime */); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -249,7 +250,8 @@ void RefreshRateOverlay::onInvalidate() { mFrame = (mFrame + 1) % buffers.size(); auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, - mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */)); + mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), + std::nullopt /* dequeueTime */); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6967f69876..6938d5de57 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3840,7 +3840,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); } } + std::optional dequeueBufferTimestamp; if (what & layer_state_t::eMetadataChanged) { + dequeueBufferTimestamp = s.metadata.getInt64(METADATA_DEQUEUE_TIME); if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded; } if (what & layer_state_t::eColorSpaceAgnosticChanged) { @@ -3928,7 +3930,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, - s.cachedBuffer, frameNumber)) { + s.cachedBuffer, frameNumber, dequeueBufferTimestamp)) { flags |= eTraversalNeeded; } } -- cgit v1.2.3-59-g8ed1b From b9a7dabfc3f6896986b54cf6b21bf1a483391256 Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Thu, 14 Jan 2021 23:49:46 +0000 Subject: Fix Transaction tracking for FrameTimeline The current setup only supports one SurfaceFrame per DrawingState for Transactions. This becomes problematic if more than one Transaction is submitted for the same vsync, on the same layer. On top of this, the Blast transactions can have a buffer that could result in a buffer drop. This change adds the support to hold multiple SurfaceFrames in the Layer's State. It also adds a bufferSurfaceFrame that's intended only for Blast Transactions with a Buffer. All other Transactions are tracked in the bufferlessSurfaceFrames. Additionally, this change also adds a lastLatchTime. It is needed for classifying BufferStuffing properly. Bug: 176106798 Test: open any app from the launcher and at the same time check dumpsys Change-Id: Id3b8369ca206f8b89be3041e5fc018f1f1be1d23 Merged-In: Id3b8369ca206f8b89be3041e5fc018f1f1be1d23 --- services/surfaceflinger/BufferQueueLayer.cpp | 27 +- services/surfaceflinger/BufferQueueLayer.h | 5 - services/surfaceflinger/BufferStateLayer.cpp | 25 +- services/surfaceflinger/BufferStateLayer.h | 4 +- .../surfaceflinger/FrameTimeline/FrameTimeline.cpp | 4 + services/surfaceflinger/Layer.cpp | 139 +++++++- services/surfaceflinger/Layer.h | 46 ++- services/surfaceflinger/RefreshRateOverlay.cpp | 4 +- services/surfaceflinger/SurfaceFlinger.cpp | 9 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../unittests/TransactionSurfaceFrameTest.cpp | 367 +++++++++++++++++++++ 11 files changed, 578 insertions(+), 53 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 52197873c5..3615a0209f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -282,8 +282,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); + addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; @@ -298,8 +297,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); for (auto& [item, surfaceFrame] : mQueueItems) { if (surfaceFrame) { - surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + addSurfaceFrameDroppedForBuffer(surfaceFrame); } } mQueueItems.clear(); @@ -329,8 +327,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage); mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); + addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame); } mQueueItems.erase(mQueueItems.begin()); mQueuedFrames--; @@ -342,11 +339,9 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t FrameTracer::FrameEvent::LATCH); if (mQueueItems[0].surfaceFrame) { - mQueueItems[0].surfaceFrame->setAcquireFenceTime( - mQueueItems[0].item.mFenceTime->getSignalTime()); - mQueueItems[0].surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); - mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame); - mLastLatchTime = latchTime; + addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame, + mQueueItems[0].item.mFenceTime->getSignalTime(), + latchTime); } mQueueItems.erase(mQueueItems.begin()); } @@ -444,10 +439,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { } } - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mName); - surfaceFrame->setActualQueueTime(systemTime()); + auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName); mQueueItems.push_back({item, surfaceFrame}); mQueuedFrames++; @@ -483,10 +475,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { return; } - auto surfaceFrame = - mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mName); - surfaceFrame->setActualQueueTime(systemTime()); + auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName); mQueueItems[mQueueItems.size() - 1].item = item; mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 41ff01262e..0ea02e19a7 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -149,11 +149,6 @@ private: // a buffer to correlate the buffer with the vsync id. Can only be accessed // with the SF state lock held. FrameTimelineInfo mFrameTimelineInfo; - - // Keeps track of the time SF latched the last buffer from this layer. - // Used in buffer stuffing analysis in FrameTimeline. - // TODO(b/176106798): Find a way to do this for BLASTBufferQueue as well. - nsecs_t mLastLatchTime = 0; }; } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 3dc62e3091..e470eb940c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -28,6 +28,7 @@ #include +#include #include #include #include @@ -38,6 +39,7 @@ namespace android { +using PresentState = frametimeline::SurfaceFrame::PresentState; // clang-format off const std::array BufferStateLayer::IDENTITY_MATRIX{ 1, 0, 0, 0, @@ -335,7 +337,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional /* dequeueTime */) { + std::optional /* dequeueTime */, + const FrameTimelineInfo& info) { ATRACE_CALL(); if (mCurrentState.buffer) { @@ -345,6 +348,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const sp& buffer, const sp(mDrawingState.acquireFence)); mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime); + auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; + if (bufferSurfaceFrame != nullptr && + bufferSurfaceFrame->getPresentState() != PresentState::Presented) { + // Update only if the bufferSurfaceFrame wasn't already presented. A Presented + // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we + // are processing the next state. + addSurfaceFramePresentedForBuffer(bufferSurfaceFrame, + mDrawingState.acquireFence->getSignalTime(), latchTime); + bufferSurfaceFrame.reset(); + } + mCurrentStateModified = false; return NO_ERROR; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index b93d567e20..ea832a2078 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -72,7 +72,7 @@ public: bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime) override; + std::optional dequeueTime, const FrameTimelineInfo& info) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; @@ -124,6 +124,8 @@ protected: private: friend class SlotGenerationTest; + friend class TransactionSurfaceFrameTest; + inline void tracePendingBufferCount(); bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index 3743716876..3f833f4890 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -312,6 +312,10 @@ void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) { void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) { std::scoped_lock lock(mMutex); + LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown, + "setPresentState called on a SurfaceFrame from Layer - %s, that has a " + "PresentState - %s set already.", + mDebugName.c_str(), toString(mPresentState).c_str()); mPresentState = presentState; mLastLatchTime = lastLatchTime; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 08a5f0fdb8..df14003c75 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -841,13 +841,35 @@ void Layer::pushPendingState() { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } + if (mCurrentState.bufferlessSurfaceFramesTX.size() >= State::kStateSurfaceFramesThreshold) { + // Ideally, the currentState would only contain one SurfaceFrame per transaction (assuming + // each Tx uses a different token). We don't expect the current state to hold a huge amount + // of SurfaceFrames. However, in the event it happens, this debug statement will leave a + // trail that can help in debugging. + ALOGW("Bufferless SurfaceFrames size on current state of layer %s is %" PRIu32 "", + mName.c_str(), static_cast(mCurrentState.bufferlessSurfaceFramesTX.size())); + } mPendingStates.push_back(mCurrentState); + // Since the current state along with the SurfaceFrames has been pushed into the pendingState, + // we no longer need to retain them. If multiple states are pushed and applied together, we have + // a merging logic to address the SurfaceFrames at mergeSurfaceFrames(). + mCurrentState.bufferlessSurfaceFramesTX.clear(); ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } +void Layer::mergeSurfaceFrames(State& source, State& target) { + // No need to merge BufferSurfaceFrame as the target's surfaceFrame, if it exists, will be used + // directly. Dropping of source's SurfaceFrame is taken care of at setBuffer(). + target.bufferlessSurfaceFramesTX.merge(source.bufferlessSurfaceFramesTX); + source.bufferlessSurfaceFramesTX.clear(); +} + void Layer::popPendingState(State* stateToCommit) { ATRACE_CALL(); + if (stateToCommit != nullptr) { + mergeSurfaceFrames(*stateToCommit, mPendingStates[0]); + } *stateToCommit = mPendingStates[0]; mPendingStates.pop_front(); ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); @@ -906,20 +928,6 @@ bool Layer::applyPendingStates(State* stateToCommit) { mFlinger->setTraversalNeeded(); } - if (stateUpdateAvailable) { - mSurfaceFrame = - mFlinger->mFrameTimeline - ->createSurfaceFrameForToken(stateToCommit->frameTimelineInfo, mOwnerPid, - mOwnerUid, mName, mTransactionName); - mSurfaceFrame->setActualQueueTime(stateToCommit->postTime); - // For transactions we set the acquire fence time to the post time as we - // don't have a buffer. For BufferStateLayer it is overridden in - // BufferStateLayer::applyPendingStates - mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime); - - onSurfaceFrameCreated(mSurfaceFrame); - } - mCurrentState.modified = false; return stateUpdateAvailable; } @@ -1048,10 +1056,22 @@ uint32_t Layer::doTransaction(uint32_t flags) { return flags; } -void Layer::commitTransaction(const State& stateToCommit) { +void Layer::commitTransaction(State& stateToCommit) { mDrawingState = stateToCommit; - mSurfaceFrame->setPresentState(PresentState::Presented); - mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame); + + // Set the present state for all bufferlessSurfaceFramesTX to Presented. The + // bufferSurfaceFrameTX will be presented in latchBuffer. + for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) { + if (surfaceFrame->getPresentState() != PresentState::Presented) { + // With applyPendingStates, we could end up having presented surfaceframes from previous + // states + surfaceFrame->setPresentState(PresentState::Presented); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + } + } + // Clear the surfaceFrames from the old state now that it has been copied into DrawingState. + stateToCommit.bufferSurfaceFrameTX.reset(); + stateToCommit.bufferlessSurfaceFramesTX.clear(); } uint32_t Layer::getTransactionFlags(uint32_t flags) { @@ -1474,11 +1494,94 @@ bool Layer::setFrameRate(FrameRate frameRate) { return true; } -void Layer::setFrameTimelineInfoForTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { +void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, + nsecs_t postTime) { + mCurrentState.postTime = postTime; + + // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if + // there are two transactions with the same token, the first one without a buffer and the + // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX + // in that case. + auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it != mCurrentState.bufferlessSurfaceFramesTX.end()) { + // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX + mCurrentState.bufferSurfaceFrameTX = it->second; + mCurrentState.bufferlessSurfaceFramesTX.erase(it); + mCurrentState.bufferSurfaceFrameTX->setActualQueueTime(postTime); + } else { + mCurrentState.bufferSurfaceFrameTX = + createSurfaceFrameForBuffer(info, postTime, mTransactionName); + } +} + +void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, + nsecs_t postTime) { mCurrentState.frameTimelineInfo = info; mCurrentState.postTime = postTime; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + + if (const auto& bufferSurfaceFrameTX = mCurrentState.bufferSurfaceFrameTX; + bufferSurfaceFrameTX != nullptr) { + if (bufferSurfaceFrameTX->getToken() == info.vsyncId) { + // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is + // being used for BufferSurfaceFrame, don't create a new one. + return; + } + } + // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple + // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are + // targeting different vsyncs). + auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it == mCurrentState.bufferlessSurfaceFramesTX.end()) { + auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime); + mCurrentState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame; + } else { + if (it->second->getPresentState() == PresentState::Presented) { + // If the SurfaceFrame was already presented, its safe to overwrite it since it must + // have been from previous vsync. + it->second = createSurfaceFrameForTransaction(info, postTime); + } + } +} + +void Layer::addSurfaceFrameDroppedForBuffer( + std::shared_ptr& surfaceFrame) { + surfaceFrame->setPresentState(PresentState::Dropped); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); +} + +void Layer::addSurfaceFramePresentedForBuffer( + std::shared_ptr& surfaceFrame, nsecs_t acquireFenceTime, + nsecs_t currentLatchTime) { + surfaceFrame->setAcquireFenceTime(acquireFenceTime); + surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime); + mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); + mLastLatchTime = currentLatchTime; +} + +std::shared_ptr Layer::createSurfaceFrameForTransaction( + const FrameTimelineInfo& info, nsecs_t postTime) { + auto surfaceFrame = + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, + mTransactionName); + // For Transactions, the post time is considered to be both queue and acquire fence time. + surfaceFrame->setActualQueueTime(postTime); + surfaceFrame->setAcquireFenceTime(postTime); + onSurfaceFrameCreated(surfaceFrame); + return surfaceFrame; +} + +std::shared_ptr Layer::createSurfaceFrameForBuffer( + const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName) { + auto surfaceFrame = + mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName, + debugName); + // For buffers, acquire fence time will set during latch. + surfaceFrame->setActualQueueTime(queueTime); + // TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well. + onSurfaceFrameCreated(surfaceFrame); + return surfaceFrame; } Layer::FrameRate Layer::getFrameRateForLayerTree() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4b40c8ed83..89f26966fb 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -309,6 +309,20 @@ public: // When the transaction was posted nsecs_t postTime; + + // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one + // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync. + // If multiple buffers are queued, the prior ones will be dropped, along with the + // SurfaceFrame that's tracking them. + std::shared_ptr bufferSurfaceFrameTX; + // A map of token(frametimelineVsyncId) to the SurfaceFrame that's tracking a transaction + // that contains the token. Only one SurfaceFrame exisits for transactions that share the + // same token, unless they are presented in different vsyncs. + std::unordered_map> + bufferlessSurfaceFramesTX; + // An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to + // trigger a warning if the number of SurfaceFrames crosses the threshold. + static constexpr uint32_t kStateSurfaceFramesThreshold = 25; }; /* @@ -447,7 +461,8 @@ public: virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, - uint64_t /* frameNumber */, std::optional /* dequeueTime */) { + uint64_t /* frameNumber */, std::optional /* dequeueTime */, + const FrameTimelineInfo& /*info*/) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; @@ -611,6 +626,12 @@ public: virtual void pushPendingState(); + /* + * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in + * both source and target, target's SurfaceFrame will be retained. + */ + void mergeSurfaceFrames(State& source, State& target); + /** * Returns active buffer size in the correct orientation. Buffer size is determined by undoing * any buffer transformations. If the layer has no buffer then return INVALID_RECT. @@ -866,8 +887,20 @@ public: bool setFrameRate(FrameRate); virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} - void setFrameTimelineInfoForTransaction(const FrameTimelineInfo& frameTimelineInfo, - nsecs_t postTime); + void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime); + void setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, + nsecs_t postTime); + + void addSurfaceFrameDroppedForBuffer( + std::shared_ptr& surfaceFrame); + void addSurfaceFramePresentedForBuffer( + std::shared_ptr& surfaceFrame, nsecs_t acquireFenceTime, + nsecs_t currentLatchTime); + + std::shared_ptr createSurfaceFrameForTransaction( + const FrameTimelineInfo& info, nsecs_t postTime); + std::shared_ptr createSurfaceFrameForBuffer( + const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName); // Creates a new handle each time, so we only expect // this to be called once. @@ -972,6 +1005,7 @@ protected: friend class TestableSurfaceFlinger; friend class RefreshRateSelectionTest; friend class SetFrameRateTest; + friend class TransactionSurfaceFrameTest; virtual void setInitialValuesForClone(const sp& clonedFrom); virtual std::optional prepareClientComposition( @@ -980,7 +1014,7 @@ protected: const LayerFE::LayerSettings&, const Rect& layerStackRect, ui::Dataspace outputDataspace); virtual void preparePerFrameCompositionState(); - virtual void commitTransaction(const State& stateToCommit); + virtual void commitTransaction(State& stateToCommit); virtual bool applyPendingStates(State* stateToCommit); virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); virtual void onSurfaceFrameCreated(const std::shared_ptr&) {} @@ -1116,6 +1150,10 @@ protected: // If created from a system process, the value can be passed in. pid_t mOwnerPid; + // Keeps track of the time SF latched the last buffer from this layer. + // Used in buffer stuffing analysis in FrameTimeline. + nsecs_t mLastLatchTime = 0; + private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 9230e72f45..49ffc81359 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -238,7 +238,7 @@ void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -251,7 +251,7 @@ void RefreshRateOverlay::onInvalidate() { auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9b587510a..4712328f18 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3931,10 +3931,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + FrameTimelineInfo info; if (what & layer_state_t::eFrameTimelineInfoChanged) { - layer->setFrameTimelineInfoForTransaction(s.frameTimelineInfo, postTime); + info = s.frameTimelineInfo; } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { - layer->setFrameTimelineInfoForTransaction(frameTimelineInfo, postTime); + info = frameTimelineInfo; } if (what & layer_state_t::eFixedTransformHintChanged) { if (layer->setFixedTransformHint(s.fixedTransformHint)) { @@ -3993,9 +3994,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, - s.cachedBuffer, frameNumber, dequeueBufferTimestamp)) { + s.cachedBuffer, frameNumber, dequeueBufferTimestamp, info)) { flags |= eTraversalNeeded; } + } else if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { + layer->setFrameTimelineVsyncForBufferlessTransaction(info, postTime); } if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 13b26fcc97..7ae09fa0b4 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -73,6 +73,7 @@ cc_test { "FrameTracerTest.cpp", "TimerTest.cpp", "TransactionApplicationTest.cpp", + "TransactionSurfaceFrameTest.cpp", "StrongTypingTest.cpp", "VSyncDispatchTimerQueueTest.cpp", "VSyncDispatchRealtimeTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp new file mode 100644 index 0000000000..aa6798d84c --- /dev/null +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -0,0 +1,367 @@ +/* + * Copyright 2021 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 "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockEventThread.h" +#include "mock/MockVsyncController.h" + +namespace android { + +using testing::_; +using testing::Mock; +using testing::Return; +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; +using PresentState = frametimeline::SurfaceFrame::PresentState; + +class TransactionSurfaceFrameTest : public testing::Test { +public: + TransactionSurfaceFrameTest() { + 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()); + setupScheduler(); + setupComposer(0); + } + + ~TransactionSurfaceFrameTest() { + 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()); + } + + sp createBufferStateLayer() { + sp client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerMetadata()); + return new BufferStateLayer(args); + } + + void commitTransaction(Layer* layer) { + layer->pushPendingState(); + // After pushing the state, the currentState should not store any BufferlessSurfaceFrames + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + auto c = layer->getCurrentState(); + if (layer->applyPendingStates(&c)) { + layer->commitTransaction(c); + } + } + + void setupScheduler() { + auto eventThread = std::make_unique(); + auto sfEventThread = std::make_unique(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique(); + auto vsyncTracker = std::make_unique(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread)); + } + + void setupComposer(uint32_t virtualDisplayCount) { + mComposer = new Hwc2::mock::Composer(); + EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount)); + mFlinger.setupComposer(std::unique_ptr(mComposer)); + + Mock::VerifyAndClear(mComposer); + } + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + FenceToFenceTimeMap fenceFactory; + client_cache_t mClientCache; + + void PresentedSurfaceFrameForBufferlessTransaction() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_TRUE(layer->mCurrentState.bufferSurfaceFrameTX == nullptr); + const auto surfaceFrame = layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + commitTransaction(layer.get()); + EXPECT_EQ(1, surfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void PresentedSurfaceFrameForBufferTransaction() { + sp layer = createBufferStateLayer(); + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence->signalForTest(12); + + commitTransaction(layer.get()); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(1, surfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void DroppedSurfaceFrameForBufferTransaction() { + sp layer = createBufferStateLayer(); + + sp fence1(new Fence()); + auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + sp fence2(new Fence()); + auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence2->signalForTest(12); + + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + commitTransaction(layer.get()); + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(1, droppedSurfaceFrame->getToken()); + EXPECT_EQ(PresentState::Dropped, droppedSurfaceFrame->getPresentState()); + + EXPECT_EQ(1, presentedSurfaceFrame->getToken()); + EXPECT_EQ(PresentState::Presented, presentedSurfaceFrame->getPresentState()); + } + + void BufferlessSurfaceFramePromotedToBufferSurfaceFrame() { + sp layer = createBufferStateLayer(); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + acquireFence->signalForTest(12); + + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + + commitTransaction(layer.get()); + EXPECT_EQ(1, surfaceFrame->getToken()); + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState()); + } + + void BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists() { + sp layer = createBufferStateLayer(); + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 1, /*inputEventId*/ 0}); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + } + + void MultipleSurfaceFramesPresentedTogether() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = layer->mCurrentState.bufferlessSurfaceFramesTX[4]; + + sp fence(new Fence()); + auto acquireFence = fenceFactory.createFenceTimeForTest(fence); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, + {/*vsyncId*/ 3, /*inputEventId*/ 0}); + EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX; + + acquireFence->signalForTest(12); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState()); + + EXPECT_EQ(4, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + + EXPECT_EQ(3, bufferSurfaceFrameTX->getToken()); + // Buffers are presented only at latch time. + EXPECT_EQ(PresentState::Unknown, bufferSurfaceFrameTX->getPresentState()); + + bool computeVisisbleRegions; + layer->updateTexImage(computeVisisbleRegions, 15, 0); + + EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState()); + } + + void MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->pushPendingState(); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, + 12); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 2); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState()); + EXPECT_EQ(10, bufferlessSurfaceFrame1->getActuals().endTime); + + EXPECT_EQ(2, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); + } + + void MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken() { + sp layer = createBufferStateLayer(); + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 10); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame1 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + layer->pushPendingState(); + EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + + layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, + 12); + EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = + layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + + commitTransaction(layer.get()); + + EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken()); + EXPECT_EQ(PresentState::Unknown, bufferlessSurfaceFrame1->getPresentState()); + + EXPECT_EQ(1, bufferlessSurfaceFrame2->getToken()); + EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState()); + EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime); + } +}; + +TEST_F(TransactionSurfaceFrameTest, PresentedBufferlessSurfaceFrame) { + PresentedSurfaceFrameForBufferlessTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, PresentedBufferSurfaceFrame) { + PresentedSurfaceFrameForBufferTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, DroppedBufferSurfaceFrame) { + DroppedSurfaceFrameForBufferTransaction(); +} + +TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFramePromotedToBufferSurfaceFrame) { + BufferlessSurfaceFramePromotedToBufferSurfaceFrame(); +} + +TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists) { + BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists(); +} + +TEST_F(TransactionSurfaceFrameTest, MultipleSurfaceFramesPresentedTogether) { + MultipleSurfaceFramesPresentedTogether(); +} + +TEST_F(TransactionSurfaceFrameTest, + MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken) { + MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken(); +} + +TEST_F(TransactionSurfaceFrameTest, + MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken) { + MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken(); +} + +} // namespace android \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 7013b6f31163d9850fffec36f9dfc1ea61877a42 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 12 Feb 2021 11:16:54 -0800 Subject: Check status codes of GraphicBuffers on allocation We're getting reports of buffers transiently missing usage bits when allocated from SurfaceFlinger causing strange issues. Fatal logging when there is an allocation error will hopefully aid in triaging future bug reports. Bug: 157562905 Bug: 179786581 Test: build, boots Change-Id: I715295c0b6b3450e71181d93391dd99616f89d26 --- services/surfaceflinger/RefreshRateOverlay.cpp | 3 +++ services/surfaceflinger/RegionSamplingThread.cpp | 3 +++ services/surfaceflinger/SurfaceFlinger.cpp | 4 ++++ 3 files changed, 10 insertions(+) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 49ffc81359..b29c624d00 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -125,6 +125,9 @@ std::vector> RefreshRateOverlay::SevenSegmentDrawer::drawNumbe GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_TEXTURE, "RefreshRateOverlayBuffer"); + const status_t bufferStatus = buffer->initCheck(); + LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "RefreshRateOverlay: Buffer failed to allocate: %d", + bufferStatus); uint8_t* pixels; buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast(&pixels)); // Clear buffer content diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 9186538c0a..09615f920d 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -447,6 +447,9 @@ void RegionSamplingThread::captureSample() { GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); + const status_t bufferStatus = buffer->initCheck(); + LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d", + bufferStatus); } const sp captureListener = new SyncScreenCaptureListener(); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7fada820e4..cb9fae388a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5851,6 +5851,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), static_cast(reqPixelFormat), 1 /* layerCount */, usage, "screenshot"); + + const status_t bufferStatus = buffer->initCheck(); + LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d", + bufferStatus); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, false /* regionSampling */, grayscale, captureListener); } -- cgit v1.2.3-59-g8ed1b From 1506b181085e1f2156283d0e7b62fe94a918427f Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Mon, 22 Feb 2021 14:35:15 -0800 Subject: Introduce release buffer callback for BufferStateLayer Currently BLAST clients use the TransactionCompleted callbacks to determine when to release buffers. The TransactionCompleted callback is overloaded. For transactions without buffers, the callback is called when the transaction is applied on the server. If the Transaction contains one or more buffers, the callback is called when all the buffers are latched and ready to be presented. If we have multiple buffers on multiple transactions, where one or more buffers maybe dropped, the pending callbacks are called together. This may delay signaling the client when a buffer can be released. To fix this, we introduce a new buffer release callback that is called as soon as a buffer is dropped by the server or when a new buffer has been latched and the buffer will no longer be presented. This new callback provides a graphic bufferid to identify the buffer that can be released and a release fence to wait on. BlastBufferQueue has been switched to use this new callback. Other BLAST users continue to use the existing callback. Test: go/wm-smoke Test: atest ReleaseBufferCallbackTest Bug: 178385281 Change-Id: Idd88e4994e543443198a5a8cfa0e3f5f67d5d482 --- libs/gui/BLASTBufferQueue.cpp | 107 +++---- libs/gui/ITransactionCompletedListener.cpp | 13 +- libs/gui/LayerState.cpp | 17 +- libs/gui/SurfaceComposerClient.cpp | 84 +++++- libs/gui/include/gui/BLASTBufferQueue.h | 18 +- .../include/gui/ITransactionCompletedListener.h | 8 +- libs/gui/include/gui/LayerState.h | 7 +- libs/gui/include/gui/SurfaceComposerClient.h | 19 +- libs/gui/tests/BLASTBufferQueue_test.cpp | 53 +++- services/surfaceflinger/BufferStateLayer.cpp | 54 +++- services/surfaceflinger/BufferStateLayer.h | 8 +- services/surfaceflinger/Layer.cpp | 3 + services/surfaceflinger/Layer.h | 10 +- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 +- .../surfaceflinger/TransactionCallbackInvoker.cpp | 3 +- .../surfaceflinger/TransactionCallbackInvoker.h | 1 + services/surfaceflinger/tests/Android.bp | 1 + .../surfaceflinger/tests/LayerCallback_test.cpp | 21 +- .../tests/ReleaseBufferCallback_test.cpp | 312 +++++++++++++++++++++ .../tests/unittests/TransactionFrameTracerTest.cpp | 3 +- .../unittests/TransactionSurfaceFrameTest.cpp | 26 +- 22 files changed, 652 insertions(+), 125 deletions(-) create mode 100644 services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 82c9268feb..f778232803 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -169,8 +169,6 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp= mTransactionCompleteFrameNumber) { + if (currFrameNumber > mTransactionCompleteFrameNumber) { + BQA_LOGE("transactionCallback received for a newer framenumber=%" PRIu64 + " than expected=%" PRIu64, + currFrameNumber, mTransactionCompleteFrameNumber); + } + transactionCompleteCallback = std::move(mTransactionCompleteCallback); + mTransactionCompleteFrameNumber = 0; } - mBufferItemConsumer->releaseBuffer(mPendingReleaseItem.item, - mPendingReleaseItem.releaseFence - ? mPendingReleaseItem.releaseFence - : Fence::NO_FENCE); - mNumAcquired--; - mPendingReleaseItem.item = BufferItem(); - mPendingReleaseItem.releaseFence = nullptr; - } - - if (mSubmitted.empty()) { - BQA_LOGE("ERROR: callback with no corresponding submitted buffer item"); } - mPendingReleaseItem.item = std::move(mSubmitted.front()); - mSubmitted.pop(); - - processNextBufferLocked(false /* useNextTransaction */); - currFrameNumber = mPendingReleaseItem.item.mFrameNumber; - if (mTransactionCompleteCallback && mTransactionCompleteFrameNumber == currFrameNumber) { - transactionCompleteCallback = std::move(mTransactionCompleteCallback); - mTransactionCompleteFrameNumber = 0; - } - - mCallbackCV.notify_all(); decStrong((void*)transactionCallbackThunk); } @@ -295,15 +274,46 @@ void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp context, uint64_t graphicBufferId, + const sp& releaseFence) { + sp blastBufferQueue = context.promote(); + ALOGV("releaseBufferCallbackThunk graphicBufferId=%" PRIu64 " blastBufferQueue=%s", + graphicBufferId, blastBufferQueue ? "alive" : "dead"); + if (blastBufferQueue) { + blastBufferQueue->releaseBufferCallback(graphicBufferId, releaseFence); + } +} + +void BLASTBufferQueue::releaseBufferCallback(uint64_t graphicBufferId, + const sp& releaseFence) { ATRACE_CALL(); - BQA_LOGV("processNextBufferLocked useNextTransaction=%s", toString(useNextTransaction)); + std::unique_lock _lock{mMutex}; + BQA_LOGV("releaseBufferCallback graphicBufferId=%" PRIu64, graphicBufferId); + + auto it = mSubmitted.find(graphicBufferId); + if (it == mSubmitted.end()) { + BQA_LOGE("ERROR: releaseBufferCallback without corresponding submitted buffer %" PRIu64, + graphicBufferId); + return; + } + mBufferItemConsumer->releaseBuffer(it->second, releaseFence); + mSubmitted.erase(it); + mNumAcquired--; + processNextBufferLocked(false /* useNextTransaction */); + mCallbackCV.notify_all(); +} + +void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { + ATRACE_CALL(); // If the next transaction is set, we want to guarantee the our acquire will not fail, so don't // include the extra buffer when checking if we can acquire the next buffer. const bool includeExtraAcquire = !useNextTransaction; if (mNumFrameAvailable == 0 || maxBuffersAcquired(includeExtraAcquire)) { - BQA_LOGV("processNextBufferLocked waiting for frame available or callback"); mCallbackCV.notify_all(); return; } @@ -353,7 +363,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { } mNumAcquired++; - mSubmitted.push(bufferItem); + mSubmitted[buffer->getId()] = bufferItem; bool needsDisconnect = false; mBufferItemConsumer->getConnectionEvents(bufferItem.mFrameNumber, &needsDisconnect); @@ -369,7 +379,10 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; - t->setBuffer(mSurfaceControl, buffer); + auto releaseBufferCallback = + std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, + std::placeholders::_1, std::placeholders::_2); + t->setBuffer(mSurfaceControl, buffer, releaseBufferCallback); t->setDataspace(mSurfaceControl, static_cast(bufferItem.mDataSpace)); t->setHdrMetadata(mSurfaceControl, bufferItem.mHdrMetadata); t->setSurfaceDamageRegion(mSurfaceControl, bufferItem.mSurfaceDamage); @@ -427,9 +440,12 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { } BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64 - " applyTransaction=%s mTimestamp=%" PRId64 " mPendingTransactions.size=%d", + " applyTransaction=%s mTimestamp=%" PRId64 "%s mPendingTransactions.size=%d" + " graphicBufferId=%" PRIu64, mSize.width, mSize.height, bufferItem.mFrameNumber, toString(applyTransaction), - bufferItem.mTimestamp, static_cast(mPendingTransactions.size())); + bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp ? "(auto)" : "", + static_cast(mPendingTransactions.size()), + bufferItem.mGraphicBuffer->getId()); } Rect BLASTBufferQueue::computeCrop(const BufferItem& item) { @@ -444,18 +460,17 @@ void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) { std::unique_lock _lock{mMutex}; const bool nextTransactionSet = mNextTransaction != nullptr; - BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s mFlushShadowQueue=%s", - item.mFrameNumber, toString(nextTransactionSet), toString(mFlushShadowQueue)); - - if (nextTransactionSet || mFlushShadowQueue) { + if (nextTransactionSet) { while (mNumFrameAvailable > 0 || maxBuffersAcquired(false /* includeExtraAcquire */)) { BQA_LOGV("waiting in onFrameAvailable..."); mCallbackCV.wait(_lock); } } - mFlushShadowQueue = false; // add to shadow queue mNumFrameAvailable++; + + BQA_LOGV("onFrameAvailable framenumber=%" PRIu64 " nextTransactionSet=%s", item.mFrameNumber, + toString(nextTransactionSet)); processNextBufferLocked(nextTransactionSet /* useNextTransaction */); } @@ -514,14 +529,12 @@ void BLASTBufferQueue::setTransactionCompleteCallback( } // Check if we have acquired the maximum number of buffers. -// As a special case, we wait for the first callback before acquiring the second buffer so we -// can ensure the first buffer is presented if multiple buffers are queued in succession. // Consumer can acquire an additional buffer if that buffer is not droppable. Set // includeExtraAcquire is true to include this buffer to the count. Since this depends on the state // of the buffer, the next acquire may return with NO_BUFFER_AVAILABLE. bool BLASTBufferQueue::maxBuffersAcquired(bool includeExtraAcquire) const { int maxAcquiredBuffers = MAX_ACQUIRED_BUFFERS + (includeExtraAcquire ? 2 : 1); - return mNumAcquired == maxAcquiredBuffers || (!mInitialCallbackReceived && mNumAcquired == 1); + return mNumAcquired == maxAcquiredBuffers; } class BBQSurface : public Surface { diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp index 0ded9361bf..9b5be1f15a 100644 --- a/libs/gui/ITransactionCompletedListener.cpp +++ b/libs/gui/ITransactionCompletedListener.cpp @@ -27,7 +27,8 @@ namespace { // Anonymous enum class Tag : uint32_t { ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION, - LAST = ON_TRANSACTION_COMPLETED, + ON_RELEASE_BUFFER, + LAST = ON_RELEASE_BUFFER, }; } // Anonymous namespace @@ -122,6 +123,7 @@ status_t SurfaceStats::writeToParcel(Parcel* output) const { for (const auto& data : jankData) { SAFE_PARCEL(output->writeParcelable, data); } + SAFE_PARCEL(output->writeUint64, previousBufferId); return NO_ERROR; } @@ -144,6 +146,7 @@ status_t SurfaceStats::readFromParcel(const Parcel* input) { SAFE_PARCEL(input->readParcelable, &data); jankData.push_back(data); } + SAFE_PARCEL(input->readUint64, &previousBufferId); return NO_ERROR; } @@ -245,6 +248,12 @@ public: onTransactionCompleted)>(Tag::ON_TRANSACTION_COMPLETED, stats); } + + void onReleaseBuffer(uint64_t graphicBufferId, sp releaseFence) override { + callRemoteAsync(Tag::ON_RELEASE_BUFFER, + graphicBufferId, releaseFence); + } }; // Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see @@ -263,6 +272,8 @@ status_t BnTransactionCompletedListener::onTransact(uint32_t code, const Parcel& case Tag::ON_TRANSACTION_COMPLETED: return callLocalAsync(data, reply, &ITransactionCompletedListener::onTransactionCompleted); + case Tag::ON_RELEASE_BUFFER: + return callLocalAsync(data, reply, &ITransactionCompletedListener::onReleaseBuffer); } } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6bb8bf2d5b..7a18ca61fe 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -63,7 +63,8 @@ layer_state_t::layer_state_t() fixedTransformHint(ui::Transform::ROT_INVALID), frameNumber(0), frameTimelineInfo(), - autoRefresh(false) { + autoRefresh(false), + releaseBufferListener(nullptr) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -152,6 +153,7 @@ status_t layer_state_t::write(Parcel& output) const SAFE_PARCEL(output.writeUint64, frameNumber); SAFE_PARCEL(frameTimelineInfo.write, output); SAFE_PARCEL(output.writeBool, autoRefresh); + SAFE_PARCEL(output.writeStrongBinder, IInterface::asBinder(releaseBufferListener)); SAFE_PARCEL(output.writeUint32, blurRegions.size()); for (auto region : blurRegions) { @@ -275,6 +277,12 @@ status_t layer_state_t::read(const Parcel& input) SAFE_PARCEL(frameTimelineInfo.read, input); SAFE_PARCEL(input.readBool, &autoRefresh); + tmpBinder = nullptr; + SAFE_PARCEL(input.readNullableStrongBinder, &tmpBinder); + if (tmpBinder) { + releaseBufferListener = checked_interface_cast(tmpBinder); + } + uint32_t numRegions = 0; SAFE_PARCEL(input.readUint32, &numRegions); blurRegions.clear(); @@ -543,6 +551,13 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eAutoRefreshChanged; autoRefresh = other.autoRefresh; } + if (other.what & eReleaseBufferListenerChanged) { + if (releaseBufferListener) { + ALOGW("Overriding releaseBufferListener"); + } + what |= eReleaseBufferListenerChanged; + releaseBufferListener = other.releaseBufferListener; + } if (other.what & eStretchChanged) { what |= eStretchChanged; stretchEffect = other.stretchEffect; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index c16a98f42f..11fe49039d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -195,6 +195,17 @@ void TransactionCompletedListener::removeJankListener(const sp } } +void TransactionCompletedListener::setReleaseBufferCallback(uint64_t graphicBufferId, + ReleaseBufferCallback listener) { + std::scoped_lock lock(mMutex); + mReleaseBufferCallbacks[graphicBufferId] = listener; +} + +void TransactionCompletedListener::removeReleaseBufferCallback(uint64_t graphicBufferId) { + std::scoped_lock lock(mMutex); + mReleaseBufferCallbacks.erase(graphicBufferId); +} + void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie, sp surfaceControl, SurfaceStatsCallback listener) { std::lock_guard lock(mMutex); @@ -275,6 +286,20 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener .surfaceControls[surfaceStats.surfaceControl] ->setTransformHint(surfaceStats.transformHint); } + // If there is buffer id set, we look up any pending client release buffer callbacks + // and call them. This is a performance optimization when we have a transaction + // callback and a release buffer callback happening at the same time to avoid an + // additional ipc call from the server. + if (surfaceStats.previousBufferId) { + ReleaseBufferCallback callback = + popReleaseBufferCallbackLocked(surfaceStats.previousBufferId); + if (callback) { + callback(surfaceStats.previousBufferId, + surfaceStats.previousReleaseFence + ? surfaceStats.previousReleaseFence + : Fence::NO_FENCE); + } + } } callbackFunction(transactionStats.latchTime, transactionStats.presentFence, @@ -297,6 +322,32 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener } } +void TransactionCompletedListener::onReleaseBuffer(uint64_t graphicBufferId, + sp releaseFence) { + ReleaseBufferCallback callback; + { + std::scoped_lock lock(mMutex); + callback = popReleaseBufferCallbackLocked(graphicBufferId); + } + if (!callback) { + ALOGE("Could not call release buffer callback, buffer not found %" PRIu64, graphicBufferId); + return; + } + callback(graphicBufferId, releaseFence); +} + +ReleaseBufferCallback TransactionCompletedListener::popReleaseBufferCallbackLocked( + uint64_t graphicBufferId) { + ReleaseBufferCallback callback; + auto itr = mReleaseBufferCallbacks.find(graphicBufferId); + if (itr == mReleaseBufferCallbacks.end()) { + return nullptr; + } + callback = itr->second; + mReleaseBufferCallbacks.erase(itr); + return callback; +} + // --------------------------------------------------------------------------- void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId); @@ -1219,17 +1270,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrame } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( - const sp& sc, const sp& buffer) { + const sp& sc, const sp& buffer, + ReleaseBufferCallback callback) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } + removeReleaseBufferCallback(s); s->what |= layer_state_t::eBufferChanged; s->buffer = buffer; if (mIsAutoTimestamp) { mDesiredPresentTime = systemTime(); } + setReleaseBufferCallback(s, callback); registerSurfaceControlForCallback(sc); @@ -1237,6 +1291,34 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffe return *this; } +void SurfaceComposerClient::Transaction::removeReleaseBufferCallback(layer_state_t* s) { + if (!s->releaseBufferListener) { + return; + } + + s->what &= ~static_cast(layer_state_t::eReleaseBufferListenerChanged); + s->releaseBufferListener = nullptr; + TransactionCompletedListener::getInstance()->removeReleaseBufferCallback(s->buffer->getId()); +} + +void SurfaceComposerClient::Transaction::setReleaseBufferCallback(layer_state_t* s, + ReleaseBufferCallback callback) { + if (!callback) { + return; + } + + if (!s->buffer) { + ALOGW("Transaction::setReleaseBufferCallback" + "ignored trying to set a callback on a null buffer."); + return; + } + + s->what |= layer_state_t::eReleaseBufferListenerChanged; + s->releaseBufferListener = TransactionCompletedListener::getIInstance(); + auto listener = TransactionCompletedListener::getInstance(); + listener->setReleaseBufferCallback(s->buffer->getId(), callback); +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAcquireFence( const sp& sc, const sp& fence) { layer_state_t* s = getLayerState(sc); diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index dd8e714e23..0173ffd68e 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -89,13 +89,14 @@ public: void transactionCallback(nsecs_t latchTime, const sp& presentFence, const std::vector& stats); + void releaseBufferCallback(uint64_t graphicBufferId, const sp& releaseFence); void setNextTransaction(SurfaceComposerClient::Transaction *t); void mergeWithNextTransaction(SurfaceComposerClient::Transaction* t, uint64_t frameNumber); void setTransactionCompleteCallback(uint64_t frameNumber, std::function&& transactionCompleteCallback); void update(const sp& surface, uint32_t width, uint32_t height, int32_t format); - void flushShadowQueue() { mFlushShadowQueue = true; } + void flushShadowQueue() {} status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless); status_t setFrameTimelineInfo(const FrameTimelineInfo& info); @@ -132,16 +133,10 @@ private: int32_t mNumFrameAvailable GUARDED_BY(mMutex); int32_t mNumAcquired GUARDED_BY(mMutex); - bool mInitialCallbackReceived GUARDED_BY(mMutex) = false; - struct PendingReleaseItem { - BufferItem item; - sp releaseFence; - }; - std::queue mSubmitted GUARDED_BY(mMutex); - // Keep a reference to the currently presented buffer so we can release it when the next buffer - // is ready to be presented. - PendingReleaseItem mPendingReleaseItem GUARDED_BY(mMutex); + // Keep a reference to the submitted buffers so we can release when surfaceflinger drops the + // buffer or the buffer has been presented and a new buffer is ready to be presented. + std::unordered_map mSubmitted GUARDED_BY(mMutex); ui::Size mSize GUARDED_BY(mMutex); ui::Size mRequestedSize GUARDED_BY(mMutex); @@ -157,9 +152,6 @@ private: std::vector> mPendingTransactions GUARDED_BY(mMutex); - // If set to true, the next queue buffer will wait until the shadow queue has been processed by - // the adapter. - bool mFlushShadowQueue = false; // Last requested auto refresh state set by the producer. The state indicates that the consumer // should acquire the next frame as soon as it can and not wait for a frame to become available. // This is only relevant for shared buffer mode. diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h index cb17ceecd3..098760e89d 100644 --- a/libs/gui/include/gui/ITransactionCompletedListener.h +++ b/libs/gui/include/gui/ITransactionCompletedListener.h @@ -87,13 +87,14 @@ public: SurfaceStats() = default; SurfaceStats(const sp& sc, nsecs_t time, const sp& prevReleaseFence, uint32_t hint, FrameEventHistoryStats frameEventStats, - std::vector jankData) + std::vector jankData, uint64_t previousBufferId) : surfaceControl(sc), acquireTime(time), previousReleaseFence(prevReleaseFence), transformHint(hint), eventStats(frameEventStats), - jankData(std::move(jankData)) {} + jankData(std::move(jankData)), + previousBufferId(previousBufferId) {} sp surfaceControl; nsecs_t acquireTime = -1; @@ -101,6 +102,7 @@ public: uint32_t transformHint = 0; FrameEventHistoryStats eventStats; std::vector jankData; + uint64_t previousBufferId; }; class TransactionStats : public Parcelable { @@ -139,6 +141,8 @@ public: DECLARE_META_INTERFACE(TransactionCompletedListener) virtual void onTransactionCompleted(ListenerStats stats) = 0; + + virtual void onReleaseBuffer(uint64_t graphicBufferId, sp releaseFence) = 0; }; class BnTransactionCompletedListener : public SafeBnInterface { diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 183ec40fba..d68a9cfa4a 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -100,7 +100,7 @@ struct layer_state_t { eLayerStackChanged = 0x00000080, /* was eCropChanged_legacy, now available 0x00000100, */ eDeferTransaction_legacy = 0x00000200, - /* was ScalingModeChanged, now available 0x00000400, */ + eReleaseBufferListenerChanged = 0x00000400, eShadowRadiusChanged = 0x00000800, eReparentChildren = 0x00001000, /* was eDetachChildren, now available 0x00002000, */ @@ -248,6 +248,11 @@ struct layer_state_t { // Stretch effect to be applied to this layer StretchEffect stretchEffect; + + // Listens to when the buffer is safe to be released. This is used for blast + // layers only. The callback includes a release fence as well as the graphic + // buffer id to identify the buffer. + sp releaseBufferListener; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 88484c0bbf..f29983cef7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -80,6 +80,9 @@ using TransactionCompletedCallbackTakesContext = using TransactionCompletedCallback = std::function& /*presentFence*/, const std::vector& /*stats*/)>; +using ReleaseBufferCallback = + std::function& /*releaseFence*/)>; + using SurfaceStatsCallback = std::function& /*presentFence*/, @@ -388,6 +391,8 @@ public: void cacheBuffers(); void registerSurfaceControlForCallback(const sp& sc); + void setReleaseBufferCallback(layer_state_t* state, ReleaseBufferCallback callback); + void removeReleaseBufferCallback(layer_state_t* state); public: Transaction(); @@ -471,7 +476,8 @@ public: Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); Transaction& setFrame(const sp& sc, const Rect& frame); - Transaction& setBuffer(const sp& sc, const sp& buffer); + Transaction& setBuffer(const sp& sc, const sp& buffer, + ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); Transaction& setAcquireFence(const sp& sc, const sp& fence); Transaction& setDataspace(const sp& sc, ui::Dataspace dataspace); @@ -650,6 +656,8 @@ class TransactionCompletedListener : public BnTransactionCompletedListener { std::unordered_map mCallbacks GUARDED_BY(mMutex); std::multimap, sp> mJankListeners GUARDED_BY(mMutex); + std::unordered_map + mReleaseBufferCallbacks GUARDED_BY(mMutex); std::multimap, SurfaceStatsCallbackEntry> mSurfaceStatsListeners GUARDED_BY(mMutex); @@ -683,8 +691,15 @@ public: SurfaceStatsCallback listener); void removeSurfaceStatsListener(void* context, void* cookie); - // Overrides BnTransactionCompletedListener's onTransactionCompleted + void setReleaseBufferCallback(uint64_t /* graphicsBufferId */, ReleaseBufferCallback); + void removeReleaseBufferCallback(uint64_t /* graphicsBufferId */); + + // BnTransactionCompletedListener overrides void onTransactionCompleted(ListenerStats stats) override; + void onReleaseBuffer(uint64_t /* graphicsBufferId */, sp releaseFence) override; + +private: + ReleaseBufferCallback popReleaseBufferCallbackLocked(uint64_t /* graphicsBufferId */); }; } // namespace android diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 7895e99cc3..fe48d88376 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -73,13 +73,34 @@ public: void waitForCallbacks() { std::unique_lock lock{mBlastBufferQueueAdapter->mMutex}; - while (mBlastBufferQueueAdapter->mSubmitted.size() > 0) { + // Wait until all but one of the submitted buffers have been released. + while (mBlastBufferQueueAdapter->mSubmitted.size() > 1) { mBlastBufferQueueAdapter->mCallbackCV.wait(lock); } } + void setTransactionCompleteCallback(int64_t frameNumber) { + mBlastBufferQueueAdapter->setTransactionCompleteCallback(frameNumber, [&](int64_t frame) { + std::unique_lock lock{mMutex}; + mLastTransactionCompleteFrameNumber = frame; + mCallbackCV.notify_all(); + }); + } + + void waitForCallback(int64_t frameNumber) { + std::unique_lock lock{mMutex}; + // Wait until all but one of the submitted buffers have been released. + while (mLastTransactionCompleteFrameNumber < frameNumber) { + mCallbackCV.wait(lock); + } + } + private: sp mBlastBufferQueueAdapter; + + std::mutex mMutex; + std::condition_variable mCallbackCV; + int64_t mLastTransactionCompleteFrameNumber = -1; }; class BLASTBufferQueueTest : public ::testing::Test { @@ -128,7 +149,7 @@ protected: mCaptureArgs.dataspace = ui::Dataspace::V0_SRGB; } - void setUpProducer(BLASTBufferQueueHelper adapter, sp& producer) { + void setUpProducer(BLASTBufferQueueHelper& adapter, sp& producer) { producer = adapter.getIGraphicBufferProducer(); setUpProducer(producer); } @@ -205,10 +226,10 @@ protected: EXPECT_GE(epsilon, abs(g - *(pixel + 1))); EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } + ASSERT_EQ(false, ::testing::Test::HasFailure()); } } captureBuf->unlock(); - ASSERT_EQ(false, ::testing::Test::HasFailure()); } static status_t captureDisplay(DisplayCaptureArgs& captureArgs, @@ -315,7 +336,8 @@ TEST_F(BLASTBufferQueueTest, DISABLED_onFrameAvailable_ApplyDesiredPresentTime) nsecs_t desiredPresentTime = systemTime() + nsecs_t(5 * 1e8); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(desiredPresentTime, false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(desiredPresentTime, true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(mDisplayWidth, mDisplayHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -351,7 +373,8 @@ TEST_F(BLASTBufferQueueTest, onFrameAvailable_Apply) { buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(mDisplayWidth, mDisplayHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -396,7 +419,8 @@ TEST_F(BLASTBufferQueueTest, TripleBuffering) { nullptr, nullptr); ASSERT_EQ(NO_ERROR, ret); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(mDisplayWidth, mDisplayHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -429,7 +453,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(mDisplayWidth, mDisplayHeight / 2), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -486,7 +511,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { buf->unlock(); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(bufferSideLength, finalCropSideLength), NATIVE_WINDOW_SCALING_MODE_SCALE_CROP, 0, Fence::NO_FENCE); @@ -537,7 +563,8 @@ TEST_F(BLASTBufferQueueTest, CustomProducerListener) { ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret); ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf)); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(mDisplayWidth, mDisplayHeight), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE); @@ -577,7 +604,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { sp slowIgbProducer; setUpProducer(slowAdapter, slowIgbProducer); nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count(); - queueBuffer(slowIgbProducer, 0 /* r */, 0 /* g */, 0 /* b */, presentTimeDelay); + queueBuffer(slowIgbProducer, 0 /* r */, 255 /* g */, 0 /* b */, presentTimeDelay); BLASTBufferQueueHelper fastAdapter(bgSurface, mDisplayWidth, mDisplayHeight); sp fastIgbProducer; @@ -617,7 +644,8 @@ public: fillQuadrants(buf); IGraphicBufferProducer::QueueBufferOutput qbOutput; - IGraphicBufferProducer::QueueBufferInput input(systemTime(), false, HAL_DATASPACE_UNKNOWN, + IGraphicBufferProducer::QueueBufferInput input(systemTime(), true /* autotimestamp */, + HAL_DATASPACE_UNKNOWN, Rect(bufWidth, bufHeight), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, tr, Fence::NO_FENCE); @@ -838,6 +866,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { IGraphicBufferProducer::QueueBufferOutput qbOutput; nsecs_t requestedPresentTimeA = 0; nsecs_t postedTimeA = 0; + adapter.setTransactionCompleteCallback(1); setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true); history.applyDelta(qbOutput.frameTimestamps); @@ -848,7 +877,7 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) { ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime); ASSERT_GE(events->postedTime, postedTimeA); - adapter.waitForCallbacks(); + adapter.waitForCallback(1); // queue another buffer so we query for frame event deltas nsecs_t requestedPresentTimeB = 0; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 96a0c3cd75..89dfb6fb6b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -41,6 +41,16 @@ namespace android { using PresentState = frametimeline::SurfaceFrame::PresentState; +namespace { +void callReleaseBufferCallback(const sp& listener, + const sp& buffer, const sp& releaseFence) { + if (!listener) { + return; + } + listener->onReleaseBuffer(buffer->getId(), releaseFence ? releaseFence : Fence::NO_FENCE); +} +} // namespace + // clang-format off const std::array BufferStateLayer::IDENTITY_MATRIX{ 1, 0, 0, 0, @@ -65,7 +75,10 @@ BufferStateLayer::~BufferStateLayer() { // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. auto& engine(mFlinger->getRenderEngine()); - engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); + const uint64_t bufferId = mBufferInfo.mBuffer->getId(); + engine.unbindExternalTextureBuffer(bufferId); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, + mBufferInfo.mFence); } } @@ -74,6 +87,7 @@ status_t BufferStateLayer::addReleaseFence(const sp& ch, if (ch == nullptr) { return OK; } + ch->previousBufferId = mPreviousBufferId; if (!ch->previousReleaseFence.get()) { ch->previousReleaseFence = fence; return OK; @@ -190,6 +204,19 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { handle->dequeueReadyTime = dequeueReadyTime; } + // If there are multiple transactions in this frame, set the previous id on the earliest + // transacton. We don't need to pass in the released buffer id to multiple transactions. + // The buffer id does not have to correspond to any particular transaction as long as the + // listening end point is the same but the client expects the first transaction callback that + // replaces the presented buffer to contain the release fence. This follows the same logic. + // see BufferStateLayer::onLayerDisplayed. + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer) { + handle->previousBufferId = mPreviousBufferId; + break; + } + } + std::vector jankData; jankData.reserve(mPendingJankClassifications.size()); while (!mPendingJankClassifications.empty() @@ -344,8 +371,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime, - const FrameTimelineInfo& info) { + std::optional dequeueTime, const FrameTimelineInfo& info, + const sp& releaseBufferListener) { ATRACE_CALL(); if (mCurrentState.buffer) { @@ -353,7 +380,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const sp& buffer, const sp& newBuffer) { + if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && + newBuffer != mDrawingState.buffer) { // If we are about to update mDrawingState.buffer but it has not yet latched - // then we will drop a buffer and should decrement the pending buffer count. - // This logic may not work perfectly in the face of a BufferStateLayer being the - // deferred side of a deferred transaction, but we don't expect this use case. + // then we will drop a buffer and should decrement the pending buffer count and + // call any release buffer callbacks if set. + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, + mDrawingState.acquireFence); decrementPendingBufferCount(); } - return Layer::doTransaction(flags); } } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index ebf40cb6e4..036e8d2e85 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -70,7 +70,8 @@ public: bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, - std::optional dequeueTime, const FrameTimelineInfo& info) override; + std::optional dequeueTime, const FrameTimelineInfo& info, + const sp& transactionListener) override; bool setAcquireFence(const sp& fence) override; bool setDataspace(ui::Dataspace dataspace) override; bool setHdrMetadata(const HdrMetadata& hdrMetadata) override; @@ -111,7 +112,7 @@ public: // See mPendingBufferTransactions void decrementPendingBufferCount(); - uint32_t doTransaction(uint32_t flags) override; + void bufferMayChange(sp& newBuffer) override; std::atomic* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } @@ -170,6 +171,9 @@ private: mutable bool mCurrentStateModified = false; bool mReleasePreviousBuffer = false; + + // Stores the last set acquire fence signal time used to populate the callback handle's acquire + // time. nsecs_t mCallbackHandleAcquireTime = -1; std::deque> mPendingJankClassifications; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 0015bf27d1..cd3e8add9a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1048,6 +1048,9 @@ uint32_t Layer::doTransaction(uint32_t flags) { c.callbackHandles.push_back(handle); } + // Allow BufferStateLayer to release any unlatched buffers in drawing state. + bufferMayChange(c.buffer); + // Commit the transaction commitTransaction(c); mPendingStatesSnapshot = mPendingStates; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 26d8e7472a..85ff479344 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -312,6 +312,7 @@ public: // When the transaction was posted nsecs_t postTime; + sp releaseBufferListener; // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync. // If multiple buffers are queued, the prior ones will be dropped, along with the @@ -466,7 +467,8 @@ public: nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, std::optional /* dequeueTime */, - const FrameTimelineInfo& /*info*/) { + const FrameTimelineInfo& /*info*/, + const sp& /* releaseBufferListener */) { return false; }; virtual bool setAcquireFence(const sp& /*fence*/) { return false; }; @@ -773,6 +775,12 @@ public: */ virtual uint32_t doTransaction(uint32_t transactionFlags); + /* + * Called before updating the drawing state buffer. Used by BufferStateLayer to release any + * unlatched buffers in the drawing state. + */ + virtual void bufferMayChange(sp& /* newBuffer */){}; + /* * Remove relative z for the layer if its relative parent is not part of the * provided layer tree. diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index b29c624d00..1d00cc38f2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -241,7 +241,8 @@ void RefreshRateOverlay::changeRefreshRate(const Fps& fps) { auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */, FrameTimelineInfo{}); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}, + nullptr /* releaseBufferListener */); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } @@ -254,7 +255,8 @@ void RefreshRateOverlay::onInvalidate() { auto buffer = buffers[mFrame]; mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {}, mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */), - std::nullopt /* dequeueTime */, FrameTimelineInfo{}); + std::nullopt /* dequeueTime */, FrameTimelineInfo{}, + nullptr /* releaseBufferListener */); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index d048380dd2..61cc8a2ff0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4027,7 +4027,8 @@ uint32_t SurfaceFlinger::setClientStateLocked( : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1; if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp, - s.cachedBuffer, frameNumber, dequeueBufferTimestamp, info)) { + s.cachedBuffer, frameNumber, dequeueBufferTimestamp, info, + s.releaseBufferListener)) { flags |= eTraversalNeeded; } } else if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index a78510e902..3590e76cb9 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -201,7 +201,8 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& handle->dequeueReadyTime); transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime, handle->previousReleaseFence, - handle->transformHint, eventStats, jankData); + handle->transformHint, eventStats, jankData, + handle->previousBufferId); } return NO_ERROR; } diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index a240c824a1..caa8a4fb45 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -50,6 +50,7 @@ public: nsecs_t refreshStartTime = 0; nsecs_t dequeueReadyTime = 0; uint64_t frameNumber = 0; + uint64_t previousBufferId = 0; }; class TransactionCallbackInvoker { diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 78187f7e9d..b96725fa12 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -44,6 +44,7 @@ cc_test { "MultiDisplayLayerBounds_test.cpp", "RefreshRateOverlay_test.cpp", "RelativeZ_test.cpp", + "ReleaseBufferCallback_test.cpp", "ScreenCapture_test.cpp", "SetFrameRate_test.cpp", "SetGeometry_test.cpp", diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index aa1cce2586..158801a705 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -14,10 +14,6 @@ * limitations under the License. */ -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" - #include #include @@ -25,6 +21,8 @@ #include "LayerTransactionTest.h" #include "utils/CallbackUtils.h" +using namespace std::chrono_literals; + namespace android { using android::hardware::graphics::common::V1_1::BufferUsage; @@ -801,7 +799,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime) { } // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); + nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -825,7 +823,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) { } // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); + nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -842,7 +840,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) { } // Try to present 33ms after the first frame - time += (33.3 * 1e6); + time += std::chrono::nanoseconds(33ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -870,7 +868,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) { } // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); + nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -887,7 +885,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) { } // Try to present 33ms before the previous frame - time -= (33.3 * 1e6); + time -= std::chrono::nanoseconds(33ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -914,7 +912,7 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { } // Try to present 100ms in the past - nsecs_t time = systemTime() - (100 * 1e6); + nsecs_t time = systemTime() - std::chrono::nanoseconds(100ms).count(); transaction.setDesiredPresentTime(time); transaction.apply(); @@ -948,6 +946,3 @@ TEST_F(LayerCallbackTest, ExpectedPresentTime) { } } // namespace android - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp new file mode 100644 index 0000000000..fb7d41c81e --- /dev/null +++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2021 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 "LayerTransactionTest.h" +#include "utils/CallbackUtils.h" + +using namespace std::chrono_literals; + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +// b/181132765 - disabled until cuttlefish failures are investigated +class ReleaseBufferCallbackHelper { +public: + static void function(void* callbackContext, uint64_t graphicsBufferId, + const sp& releaseFence) { + if (!callbackContext) { + FAIL() << "failed to get callback context"; + } + ReleaseBufferCallbackHelper* helper = + static_cast(callbackContext); + std::lock_guard lock(helper->mMutex); + helper->mCallbackDataQueue.emplace(graphicsBufferId, releaseFence); + helper->mConditionVariable.notify_all(); + } + + void getCallbackData(uint64_t* bufferId) { + std::unique_lock lock(mMutex); + if (mCallbackDataQueue.empty()) { + if (!mConditionVariable.wait_for(lock, std::chrono::seconds(3), + [&] { return !mCallbackDataQueue.empty(); })) { + FAIL() << "failed to get releaseBuffer callback"; + } + } + + auto callbackData = mCallbackDataQueue.front(); + mCallbackDataQueue.pop(); + *bufferId = callbackData.first; + } + + void verifyNoCallbacks() { + // Wait to see if there are extra callbacks + std::this_thread::sleep_for(300ms); + + std::lock_guard lock(mMutex); + EXPECT_EQ(mCallbackDataQueue.size(), 0) << "extra callbacks received"; + mCallbackDataQueue = {}; + } + + android::ReleaseBufferCallback getCallback() { + return std::bind(function, static_cast(this) /* callbackContext */, + std::placeholders::_1, std::placeholders::_2); + } + + std::mutex mMutex; + std::condition_variable mConditionVariable; + std::queue>> mCallbackDataQueue; +}; + +class ReleaseBufferCallbackTest : public LayerTransactionTest { +public: + virtual sp createBufferStateLayer() { + return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState); + } + + static void submitBuffer(const sp& layer, sp buffer, + sp fence, CallbackHelper& callback, + ReleaseBufferCallbackHelper& releaseCallback) { + Transaction t; + t.setBuffer(layer, buffer, releaseCallback.getCallback()); + t.setAcquireFence(layer, fence); + t.addTransactionCompletedCallback(callback.function, callback.getContext()); + t.apply(); + } + + static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult) { + CallbackData callbackData; + helper.getCallbackData(&callbackData); + expectedResult.verifyCallbackData(callbackData); + } + + static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback, + uint64_t expectedReleaseBufferId) { + uint64_t actualReleaseBufferId; + releaseCallback.getCallbackData(&actualReleaseBufferId); + EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId); + releaseCallback.verifyNoCallbacks(); + } + static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() { + static std::vector sCallbacks; + sCallbacks.emplace_back(new ReleaseBufferCallbackHelper()); + return sCallbacks.back(); + } + + static sp getBuffer() { + return new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + } +}; + +TEST_F(ReleaseBufferCallbackTest, DISABLED_PresentBuffer) { + sp layer = createBufferStateLayer(); + CallbackHelper transactionCallback; + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + // If a buffer is being presented, we should not emit a release callback. + sp firstBuffer = getBuffer(); + submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback); + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + + // if state doesn't change, no release callbacks are expected + Transaction t; + t.addTransactionCompletedCallback(transactionCallback.function, + transactionCallback.getContext()); + t.apply(); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, ExpectedResult())); + EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + + // If a presented buffer is replaced, we should emit a release callback for the + // previously presented buffer. + sp secondBuffer = getBuffer(); + submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback); + expected = ExpectedResult(); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId())); +} + +TEST_F(ReleaseBufferCallbackTest, DISABLED_OffScreenLayer) { + sp layer = createBufferStateLayer(); + + CallbackHelper transactionCallback; + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + // If a buffer is being presented, we should not emit a release callback. + sp firstBuffer = getBuffer(); + submitBuffer(layer, firstBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback); + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + releaseCallback->verifyNoCallbacks(); + + // If a layer is parented offscreen then it should not emit a callback since sf still owns + // the buffer and can render it again. + Transaction t; + t.reparent(layer, nullptr); + t.addTransactionCompletedCallback(transactionCallback.function, + transactionCallback.getContext()); + t.apply(); + expected = ExpectedResult(); + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::NOT_RELEASED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + + // If a presented buffer is replaced, we should emit a release callback for the + // previously presented buffer. + sp secondBuffer = getBuffer(); + submitBuffer(layer, secondBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback); + expected = ExpectedResult(); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::NOT_RELEASED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId())); + + // If continue to submit buffer we continue to get release callbacks + sp thirdBuffer = getBuffer(); + submitBuffer(layer, thirdBuffer, Fence::NO_FENCE, transactionCallback, *releaseCallback); + expected = ExpectedResult(); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::NOT_RELEASED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId())); +} + +TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_layerdestroy) { + sp layer = createBufferStateLayer(); + CallbackHelper* transactionCallback = new CallbackHelper(); + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + // If a buffer is being presented, we should not emit a release callback. + sp firstBuffer = getBuffer(); + submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback); + { + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + } + + // Destroying a currently presenting layer emits a callback. + Transaction t; + t.reparent(layer, nullptr); + t.apply(); + layer = nullptr; + + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId())); +} + +// Destroying a never presented layer emits a callback. +TEST_F(ReleaseBufferCallbackTest, DISABLED_LayerLifecycle_OffScreenLayerDestroy) { + sp layer = createBufferStateLayer(); + + // make layer offscreen + Transaction t; + t.reparent(layer, nullptr); + t.apply(); + + CallbackHelper* transactionCallback = new CallbackHelper(); + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + // Submitting a buffer does not emit a callback. + sp firstBuffer = getBuffer(); + submitBuffer(layer, firstBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback); + { + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + } + + // Submitting a second buffer will replace the drawing state buffer and emit a callback. + sp secondBuffer = getBuffer(); + submitBuffer(layer, secondBuffer, Fence::NO_FENCE, *transactionCallback, *releaseCallback); + { + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(*transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE( + waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId())); + } + + // Destroying the offscreen layer emits a callback. + layer = nullptr; + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, secondBuffer->getId())); +} + +TEST_F(ReleaseBufferCallbackTest, DISABLED_FrameDropping) { + sp layer = createBufferStateLayer(); + CallbackHelper transactionCallback; + ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper(); + + // If a buffer is being presented, we should not emit a release callback. + sp firstBuffer = getBuffer(); + + // Try to present 100ms in the future + nsecs_t time = systemTime() + std::chrono::nanoseconds(100ms).count(); + + Transaction t; + t.setBuffer(layer, firstBuffer, releaseCallback->getCallback()); + t.setAcquireFence(layer, Fence::NO_FENCE); + t.addTransactionCompletedCallback(transactionCallback.function, + transactionCallback.getContext()); + t.setDesiredPresentTime(time); + t.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + EXPECT_NO_FATAL_FAILURE(releaseCallback->verifyNoCallbacks()); + + // Dropping frames in transaction queue emits a callback + sp secondBuffer = getBuffer(); + t.setBuffer(layer, secondBuffer, releaseCallback->getCallback()); + t.setAcquireFence(layer, Fence::NO_FENCE); + t.addTransactionCompletedCallback(transactionCallback.function, + transactionCallback.getContext()); + t.setDesiredPresentTime(time); + t.apply(); + + expected = ExpectedResult(); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + ASSERT_NO_FATAL_FAILURE(waitForCallback(transactionCallback, expected)); + ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBuffer->getId())); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index dbadf75d44..b5ef0a1334 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -123,7 +123,8 @@ public: traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE, /*duration*/ 0)); layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache, - frameNumber, dequeueTime, FrameTimelineInfo{}); + frameNumber, dequeueTime, FrameTimelineInfo{}, + nullptr /* releaseBufferCallback */); commitTransaction(layer.get()); bool computeVisisbleRegions; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 623a5e0608..c75538f476 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -126,7 +126,7 @@ public: auto acquireFence = fenceFactory.createFenceTimeForTest(fence); sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); commitTransaction(layer.get()); @@ -151,7 +151,7 @@ public: auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; @@ -161,7 +161,7 @@ public: sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; nsecs_t start = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); nsecs_t end = systemTime(); acquireFence2->signalForTest(12); @@ -199,7 +199,7 @@ public: sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -225,7 +225,7 @@ public: sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -255,7 +255,7 @@ public: sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 3, /*inputEventId*/ 0}); + {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX; @@ -353,7 +353,7 @@ public: auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; @@ -361,7 +361,7 @@ public: auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -388,7 +388,7 @@ public: auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame1 = layer->mCurrentState.bufferSurfaceFrameTX; @@ -398,7 +398,8 @@ public: sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime1 = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}); + {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, + nullptr /* releaseBufferCallback */); auto dropEndTime1 = systemTime(); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -409,7 +410,7 @@ public: sp buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime2 = systemTime(); layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 2, /*inputEventId*/ 0}); + {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); auto dropEndTime2 = systemTime(); acquireFence3->signalForTest(12); @@ -448,7 +449,8 @@ public: sp fence1(new Fence()); sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, - {/*vsyncId*/ 1, /*inputEventId*/ 0}); + {/*vsyncId*/ 1, /*inputEventId*/ 0}, + nullptr /* releaseBufferCallback */); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, 10); -- cgit v1.2.3-59-g8ed1b From 9a93ea66bb7116b8821877a69991ae94557b1303 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 11 Mar 2021 16:44:42 -0600 Subject: Remove setFrame from BufferStateLayer Replace setFrame with setCrop, setMatrix, and setPosition Test: SurfaceFlinger_tests Test: ASurfaceControlTest Bug: 170765639 Change-Id: I32ee0e3e48e5171d99a5f5af0b7583165d4dd9f9 --- libs/gui/BLASTBufferQueue.cpp | 29 +++- libs/gui/LayerState.cpp | 4 - libs/gui/SurfaceComposerClient.cpp | 14 -- libs/gui/include/gui/BLASTBufferQueue.h | 32 +++- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 1 - libs/gui/tests/BLASTBufferQueue_test.cpp | 34 ++-- services/surfaceflinger/BufferStateLayer.cpp | 98 +++++------- services/surfaceflinger/BufferStateLayer.h | 10 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 - services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 - services/surfaceflinger/tests/BufferGenerator.cpp | 14 +- services/surfaceflinger/tests/BufferGenerator.h | 2 + services/surfaceflinger/tests/EffectLayer_test.cpp | 1 - services/surfaceflinger/tests/IPC_test.cpp | 1 - .../surfaceflinger/tests/LayerCallback_test.cpp | 131 +++++++++++++--- .../tests/LayerRenderTypeTransaction_test.cpp | 174 ++++++++++----------- .../surfaceflinger/tests/LayerTransactionTest.h | 5 + .../LayerTypeAndRenderTypeTransaction_test.cpp | 60 ++----- services/surfaceflinger/tests/MirrorLayer_test.cpp | 2 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 18 ++- 23 files changed, 353 insertions(+), 295 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 1976b493b2..1d7ed2f97b 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,13 +204,16 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - t.setFrame(mSurfaceControl, - {0, 0, static_cast(mSize.width), - static_cast(mSize.height)}); + // We only need to update the scale if we've received at least one buffer. The reason + // for this is the scale is calculated based on the requested size and buffer size. + // If there's no buffer, the scale will always be 1. + if (mLastBufferInfo.hasBuffer) { + setMatrix(&t, mLastBufferInfo); + } applyTransaction = true; } } @@ -374,8 +377,10 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); - mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; + mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), + bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, + bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, @@ -388,8 +393,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); - t->setFrame(mSurfaceControl, - {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); + setMatrix(t, mLastBufferInfo); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -515,6 +519,17 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } +void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, + const BufferInfo& bufferInfo) { + uint32_t bufWidth = bufferInfo.width; + uint32_t bufHeight = bufferInfo.height; + + float dsdx = mSize.width / static_cast(bufWidth); + float dsdy = mSize.height / static_cast(bufHeight); + + t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); +} + void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index d653ae71be..8c21553bff 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -458,10 +458,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } - if (other.what & eFrameChanged) { - what |= eFrameChanged; - orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; - } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 0b01084633..f12b77e48f 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1246,20 +1246,6 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const Rect& frame) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eFrameChanged; - s->orientedDisplaySpaceRect = frame; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index fbd16f4ea2..a48f95ae73 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,6 +142,33 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); + struct BufferInfo { + bool hasBuffer = false; + uint32_t width; + uint32_t height; + uint32_t transform; + // This is used to check if we should update the blast layer size immediately or wait until + // we get the next buffer. This will support scenarios where the layer can change sizes + // and the buffer will scale to fit the new size. + uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + + void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, + uint32_t scalingMode) { + this->hasBuffer = hasBuffer; + this->width = width; + this->height = height; + this->transform = transform; + this->scalingMode = scalingMode; + } + }; + + // Last acquired buffer's info. This is used to calculate the correct scale when size change is + // requested. We need to use the old buffer's info to determine what scale we need to apply to + // ensure the correct size. + BufferInfo mLastBufferInfo GUARDED_BY(mMutex); + void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) + REQUIRES(mMutex); + uint32_t mTransformHint GUARDED_BY(mMutex); sp mConsumer; @@ -159,11 +186,6 @@ private: std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); - // Last acquired buffer's scaling mode. This is used to check if we should update the blast - // layer size immediately or wait until we get the next buffer. This will support scenarios - // where the layer can change sizes and the buffer will scale to fit the new size. - uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 92747779fd..9186ed289e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -106,7 +106,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - eFrameChanged = 0x1'00000000, + /* was eFrameChanged, now available 0x1'00000000, */ eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index c38375cf77..19d898c96a 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -474,7 +474,6 @@ public: Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); - Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index fe48d88376..9b1f0db83b 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,7 +140,6 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) - .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -218,13 +217,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -466,7 +465,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,13 +523,15 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); + Rect bounds; + bounds.left = finalCropSideLength / 2; + bounds.top = 0; + bounds.right = bounds.left + finalCropSideLength; + bounds.bottom = finalCropSideLength; + + ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); - ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, - /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -596,7 +598,6 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) - .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits::max() - 1) .apply(); @@ -619,7 +620,8 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index a974dc4488..7a10769757 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -278,9 +278,8 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -// Crop that applies to the window -Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { - return Rect::INVALID_RECT; +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return s.crop; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -301,57 +300,53 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - Rect c = crop; - if (c.left < 0) { - c.left = 0; - } - if (c.top < 0) { - c.top = 0; - } - // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below - // treats all invalid rectangles the same. - if (!c.isValid()) { - c.makeInvalid(); - } + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; - if (mCurrentState.crop == c) return false; - mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setFrame(const Rect& frame) { - int x = frame.left; - int y = frame.top; - int w = frame.getWidth(); - int h = frame.getHeight(); - - if (x < 0) { - x = 0; - w = frame.right; +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + if (mCurrentState.transform.dsdx() == matrix.dsdx && + mCurrentState.transform.dtdy() == matrix.dtdy && + mCurrentState.transform.dtdx() == matrix.dtdx && + mCurrentState.transform.dsdy() == matrix.dsdy) { + return false; } - if (y < 0) { - y = 0; - h = frame.bottom; - } + ui::Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && - mCurrentState.width == w && mCurrentState.height == h) { + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " + "ROTATE_SURFACE_FLINGER ignored"); return false; } - if (!frame.isValid()) { - x = y = w = h = 0; + mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + return true; +} + +bool BufferStateLayer::setPosition(float x, float y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + return false; } + mCurrentState.transform.set(x, y); - mCurrentState.width = w; - mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + return true; } @@ -428,6 +423,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } + + mCurrentState.width = mCurrentState.buffer->width; + mCurrentState.height = mCurrentState.buffer->height; + return true; } @@ -855,33 +854,6 @@ sp BufferStateLayer::createClone() { return layer; } -Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - RoundedCornerState parentState = p->getRoundedCornerState(); - if (parentState.radius > 0) { - ui::Transform t = getActiveTransform(getDrawingState()); - t = t.inverse(); - parentState.cropRect = t.transform(parentState.cropRect); - // The rounded corners shader only accepts 1 corner radius for performance reasons, - // but a transform matrix can define horizontal and vertical scales. - // Let's take the average between both of them and pass into the shader, practically we - // never do this type of transformation on windows anyway. - parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; - return parentState; - } - } - const float radius = getDrawingState().cornerRadius; - const State& s(getDrawingState()); - if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) - return RoundedCornerState(); - return RoundedCornerState(FloatRect(static_cast(s.transform.tx()), - static_cast(s.transform.ty()), - static_cast(s.transform.tx() + s.width), - static_cast(s.transform.ty() + s.height)), - radius); -} - bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 7a3da6fec1..af2819eac7 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,7 +66,6 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -81,15 +80,13 @@ public: bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; + bool setPosition(float /*x*/, float /*y*/) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/); // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/) override { - return false; - } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -97,7 +94,6 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; - Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index cd3e8add9a..447cbb3854 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2312,8 +2312,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCrop(getDrawingState()).isValid() - ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() + ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 1c5d6ecb03..4cd379b963 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -462,7 +462,6 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 1d00cc38f2..7a3e433660 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,8 +231,14 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); - mLayer->setFrame(frame); + layer_state_t::matrix22_t matrix; + matrix.dsdx = frame.getWidth() / static_cast(SevenSegmentDrawer::getWidth()); + matrix.dtdx = 0; + matrix.dtdy = 0; + matrix.dsdy = frame.getHeight() / static_cast(SevenSegmentDrawer::getHeight()); + mLayer->setMatrix(matrix, true); + mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a387587d7f..b1d63f0ce7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3936,9 +3936,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFrameChanged) { - if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; - } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 03f8e1afba..47a150dd35 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - const float width = 1000.0; - const float height = 1000.0; + mBufferSize.set(1000.0, 1000.0); auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); + mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, + setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,7 +309,9 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); + mProgram->bindVec4(0, + vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, + 1.0f / mBufferSize.height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -372,6 +374,10 @@ status_t BufferGenerator::get(sp* outBuffer, sp* outFence) return NO_ERROR; } +ui::Size BufferGenerator::getSize() { + return mBufferSize; +} + // static void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index a3ffe86572..f7d548b6bf 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,6 +37,7 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); + ui::Size getSize(); private: bool mInitialized = false; @@ -53,6 +54,7 @@ private: using Epoch = std::chrono::time_point; Epoch mEpoch = std::chrono::steady_clock::now(); + ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index f470eda7d3..af00ec7fc9 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,7 +149,6 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); - t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index a8647c3e50..9fa3d4c417 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,7 +161,6 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) - .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 158801a705..011ff70409 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,7 +164,10 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -184,7 +187,10 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -203,7 +209,10 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -238,7 +247,10 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(-100, -100, 100, 100)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -263,8 +275,15 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -290,8 +309,15 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -318,8 +344,15 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -405,8 +438,15 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -491,7 +531,11 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -523,8 +567,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -564,8 +616,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -606,8 +666,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -661,8 +728,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -682,7 +756,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + transaction2.merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -762,7 +839,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -781,7 +861,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 7505e6ea9b..53d230abe7 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,11 +204,7 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(16, 16, 48, 48)) - .setRelativeLayer(layerG, layerR, 1) - .apply(); + Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -260,10 +256,9 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(8, 8, 40, 40)) + .setPosition(layerG, 8, 8) .setRelativeLayer(layerG, layerR, 3) - .setFrame(layerB, Rect(16, 16, 48, 48)) + .setPosition(layerB, 16, 16) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -388,7 +383,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) - .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -447,7 +441,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setFrame(layerR, Rect(16, 16, 48, 48)) + .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -477,8 +471,7 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setFrame(layer1, Rect(0, 0, 32, 32)) - .setFrame(layer2, Rect(16, 0, 48, 32)) + .setPosition(layer2, 16, 0) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -573,7 +566,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); + Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -849,42 +842,39 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction() - .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) - .setFrame(layer, Rect(0, 0, 32, 32)) - .apply(); + Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, + Color::WHITE, Color::BLUE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, + Color::RED, Color::GREEN); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, + Color::WHITE, Color::GREEN); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE, 1 /* tolerance */); } } @@ -955,8 +945,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -986,13 +976,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1016,8 +1006,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); - Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); - Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1025,8 +1013,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1034,8 +1022,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 16, 32, 64), Color::RED); + shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1043,9 +1031,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); - shot->expectColor(Rect(0, 16, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1068,12 +1054,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); + Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(frame, Color::RED); - shot->expectBorder(frame, Color::BLACK); + shot->expectColor(Rect(40, 40, 56, 56), Color::RED); + shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1121,7 +1106,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction().setFrame(layer, frame).apply(); + Transaction t; + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); + t.apply(); + auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1133,16 +1121,23 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction t; { SCOPED_TRACE("empty rect"); - Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); + t.apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); + t.apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 8, 8), Color::RED); + shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); } } @@ -1152,10 +1147,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A parentless layer will default to a frame with the same size as the buffer + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 10, 10), Color::RED); + shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1163,17 +1158,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1183,14 +1177,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1199,11 +1193,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); + Transaction().setPosition(layer, 16, 16).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1215,18 +1208,20 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); + Rect childDst(0, 16, 32, 32); + Transaction t; + TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); + t.apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); + shot->expectColor(childDst, Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1238,8 +1233,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1252,8 +1247,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1261,8 +1256,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1270,8 +1265,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1286,7 +1281,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); - Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1295,7 +1289,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); - Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1350,8 +1343,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1383,8 +1376,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1416,8 +1409,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1435,7 +1428,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1452,7 +1444,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1469,7 +1460,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1518,8 +1508,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1534,8 +1524,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1552,8 +1542,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1570,8 +1560,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1586,8 +1576,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 87c7b7d829..0bc8fe7aa0 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,6 +244,11 @@ protected: return bufferGenerator.get(outBuffer, outFence); } + static ui::Size getBufferSize() { + static BufferGenerator bufferGenerator; + return bufferGenerator.getSize(); + } + sp mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index ac5e297e43..edf55ea6ef 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,17 +196,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setCrop(layer, Rect(0, 0, size, size)) - .apply(); - } else { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setFrame(layer, Rect(0, 0, size, size)) - .apply(); - } + Transaction().setCornerRadius(layer, cornerRadius).apply(); { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -234,19 +224,13 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - auto transaction = Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - transaction.setCrop(parent, Rect(0, 0, size, size)); - } else { - transaction.setFrame(parent, Rect(0, 0, size, size)); - } - transaction.apply(); + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) + .apply(); { const uint8_t bottom = size - 1; @@ -275,21 +259,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - } else { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setFrame(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setFrame(child, Rect(0, size / 2, size, size)) - .apply(); - } + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -331,12 +306,9 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) - .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) - .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) - .setFrame(rightLayer, rightRect) .apply(); { @@ -352,7 +324,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) - .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -435,10 +406,8 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) - .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) - .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -457,7 +426,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect - .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index 613b21ef04..ccf434d63a 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); + Transaction().show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 3cbfed98f5..8c448e2f96 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,6 +161,22 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } + + static void setFrame(Transaction& t, const sp& sc, Rect source, Rect dest, + int32_t transform = 0) { + uint32_t sourceWidth = source.getWidth(); + uint32_t sourceHeight = source.getHeight(); + + if (transform & ui::Transform::ROT_90) { + std::swap(sourceWidth, sourceHeight); + } + + float dsdx = dest.getWidth() / static_cast(sourceWidth); + float dsdy = dest.getHeight() / static_cast(sourceHeight); + + t.setMatrix(sc, dsdx, 0, 0, dsdy); + t.setPosition(sc, dest.left, dest.top); + } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; -- cgit v1.2.3-59-g8ed1b From 1014c4bf14f5c250b78d7e917fb59aaa9b0d9b0a Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Thu, 8 Apr 2021 12:30:21 +0000 Subject: Revert "Remove setFrame from BufferStateLayer" Revert "Update tests to reflect the new behavior for setGeometry" Revert submission 13843937-sc_remove_set_frame Reason for revert: Candidate CL for b/184807094 Reverted Changes: Iffbd955a3:Remove setFrame I27f17bc61:Update tests to reflect the new behavior for setGe... I5720276c1:Remove setFrame from surface_control setGeometry I32ee0e3e4:Remove setFrame from BufferStateLayer Bug: 184807094 Change-Id: I8330f374c50c76d8c2e70b79815bc2bc32b89480 --- libs/gui/BLASTBufferQueue.cpp | 29 +--- libs/gui/LayerState.cpp | 4 + libs/gui/SurfaceComposerClient.cpp | 14 ++ libs/gui/include/gui/BLASTBufferQueue.h | 32 +--- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 1 + libs/gui/tests/BLASTBufferQueue_test.cpp | 34 ++-- services/surfaceflinger/BufferStateLayer.cpp | 98 +++++++----- services/surfaceflinger/BufferStateLayer.h | 10 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 + services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/tests/BufferGenerator.cpp | 14 +- services/surfaceflinger/tests/BufferGenerator.h | 2 - services/surfaceflinger/tests/EffectLayer_test.cpp | 1 + services/surfaceflinger/tests/IPC_test.cpp | 1 + .../surfaceflinger/tests/LayerCallback_test.cpp | 131 +++------------- .../tests/LayerRenderTypeTransaction_test.cpp | 174 +++++++++++---------- .../surfaceflinger/tests/LayerTransactionTest.h | 5 - .../LayerTypeAndRenderTypeTransaction_test.cpp | 60 +++++-- services/surfaceflinger/tests/MirrorLayer_test.cpp | 2 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 18 +-- 23 files changed, 295 insertions(+), 353 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index 1d7ed2f97b..1976b493b2 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,16 +204,13 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - // We only need to update the scale if we've received at least one buffer. The reason - // for this is the scale is calculated based on the requested size and buffer size. - // If there's no buffer, the scale will always be 1. - if (mLastBufferInfo.hasBuffer) { - setMatrix(&t, mLastBufferInfo); - } + t.setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), + static_cast(mSize.height)}); applyTransaction = true; } } @@ -377,10 +374,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); + mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; - mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), - bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, - bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, @@ -393,7 +388,8 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); - setMatrix(t, mLastBufferInfo); + t->setFrame(mSurfaceControl, + {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -519,17 +515,6 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } -void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, - const BufferInfo& bufferInfo) { - uint32_t bufWidth = bufferInfo.width; - uint32_t bufHeight = bufferInfo.height; - - float dsdx = mSize.width / static_cast(bufWidth); - float dsdy = mSize.height / static_cast(bufHeight); - - t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); -} - void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 8c21553bff..d653ae71be 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -458,6 +458,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } + if (other.what & eFrameChanged) { + what |= eFrameChanged; + orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; + } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index f12b77e48f..0b01084633 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1246,6 +1246,20 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const Rect& frame) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameChanged; + s->orientedDisplaySpaceRect = frame; + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index a48f95ae73..fbd16f4ea2 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,33 +142,6 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); - struct BufferInfo { - bool hasBuffer = false; - uint32_t width; - uint32_t height; - uint32_t transform; - // This is used to check if we should update the blast layer size immediately or wait until - // we get the next buffer. This will support scenarios where the layer can change sizes - // and the buffer will scale to fit the new size. - uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - - void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, - uint32_t scalingMode) { - this->hasBuffer = hasBuffer; - this->width = width; - this->height = height; - this->transform = transform; - this->scalingMode = scalingMode; - } - }; - - // Last acquired buffer's info. This is used to calculate the correct scale when size change is - // requested. We need to use the old buffer's info to determine what scale we need to apply to - // ensure the correct size. - BufferInfo mLastBufferInfo GUARDED_BY(mMutex); - void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) - REQUIRES(mMutex); - uint32_t mTransformHint GUARDED_BY(mMutex); sp mConsumer; @@ -186,6 +159,11 @@ private: std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); + // Last acquired buffer's scaling mode. This is used to check if we should update the blast + // layer size immediately or wait until we get the next buffer. This will support scenarios + // where the layer can change sizes and the buffer will scale to fit the new size. + uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 9186ed289e..92747779fd 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -106,7 +106,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - /* was eFrameChanged, now available 0x1'00000000, */ + eFrameChanged = 0x1'00000000, eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 19d898c96a..c38375cf77 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -474,6 +474,7 @@ public: Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); + Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index 9b1f0db83b..fe48d88376 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,6 +140,7 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -217,13 +218,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - ASSERT_GE(epsilon, abs(r - *(pixel))); - ASSERT_GE(epsilon, abs(g - *(pixel + 1))); - ASSERT_GE(epsilon, abs(b - *(pixel + 2))); + EXPECT_GE(epsilon, abs(r - *(pixel))); + EXPECT_GE(epsilon, abs(g - *(pixel + 1))); + EXPECT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -465,8 +466,7 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,15 +523,13 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); - Rect bounds; - bounds.left = finalCropSideLength / 2; - bounds.top = 0; - bounds.right = bounds.left + finalCropSideLength; - bounds.bottom = finalCropSideLength; - - ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); + ASSERT_NO_FATAL_FAILURE( + checkScreenCapture(0, 0, 0, + {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, + /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -598,6 +596,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) + .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits::max() - 1) .apply(); @@ -620,8 +619,7 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); + checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 7a10769757..a974dc4488 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -278,8 +278,9 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -Rect BufferStateLayer::getCrop(const Layer::State& s) const { - return s.crop; +// Crop that applies to the window +Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { + return Rect::INVALID_RECT; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -300,53 +301,57 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - if (mCurrentState.crop == crop) return false; - mCurrentState.sequence++; - mCurrentState.crop = crop; + Rect c = crop; + if (c.left < 0) { + c.left = 0; + } + if (c.top < 0) { + c.top = 0; + } + // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below + // treats all invalid rectangles the same. + if (!c.isValid()) { + c.makeInvalid(); + } + if (mCurrentState.crop == c) return false; + mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, - bool allowNonRectPreservingTransforms) { - if (mCurrentState.transform.dsdx() == matrix.dsdx && - mCurrentState.transform.dtdy() == matrix.dtdy && - mCurrentState.transform.dtdx() == matrix.dtdx && - mCurrentState.transform.dsdy() == matrix.dsdy) { - return false; - } +bool BufferStateLayer::setFrame(const Rect& frame) { + int x = frame.left; + int y = frame.top; + int w = frame.getWidth(); + int h = frame.getHeight(); - ui::Transform t; - t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - if (!allowNonRectPreservingTransforms && !t.preserveRects()) { - ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " - "ROTATE_SURFACE_FLINGER ignored"); - return false; + if (x < 0) { + x = 0; + w = frame.right; } - mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - - mCurrentState.sequence++; - mCurrentState.modified = true; - setTransactionFlags(eTransactionNeeded); - - return true; -} + if (y < 0) { + y = 0; + h = frame.bottom; + } -bool BufferStateLayer::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && + mCurrentState.width == w && mCurrentState.height == h) { return false; } + if (!frame.isValid()) { + x = y = w = h = 0; + } mCurrentState.transform.set(x, y); + mCurrentState.width = w; + mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - return true; } @@ -423,10 +428,6 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } - - mCurrentState.width = mCurrentState.buffer->width; - mCurrentState.height = mCurrentState.buffer->height; - return true; } @@ -854,6 +855,33 @@ sp BufferStateLayer::createClone() { return layer; } +Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { + const auto& p = mDrawingParent.promote(); + if (p != nullptr) { + RoundedCornerState parentState = p->getRoundedCornerState(); + if (parentState.radius > 0) { + ui::Transform t = getActiveTransform(getDrawingState()); + t = t.inverse(); + parentState.cropRect = t.transform(parentState.cropRect); + // The rounded corners shader only accepts 1 corner radius for performance reasons, + // but a transform matrix can define horizontal and vertical scales. + // Let's take the average between both of them and pass into the shader, practically we + // never do this type of transformation on windows anyway. + parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; + return parentState; + } + } + const float radius = getDrawingState().cornerRadius; + const State& s(getDrawingState()); + if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) + return RoundedCornerState(); + return RoundedCornerState(FloatRect(static_cast(s.transform.tx()), + static_cast(s.transform.ty()), + static_cast(s.transform.tx() + s.width), + static_cast(s.transform.ty() + s.height)), + radius); +} + bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index af2819eac7..7a3da6fec1 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,6 +66,7 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; + bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -80,13 +81,15 @@ public: bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; - bool setPosition(float /*x*/, float /*y*/) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/); // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } + bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/) override { + return false; + } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -94,6 +97,7 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; + Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 447cbb3854..cd3e8add9a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2312,8 +2312,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() - ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCrop(getDrawingState()).isValid() + ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 4cd379b963..1c5d6ecb03 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -462,6 +462,7 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; + virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 7a3e433660..1d00cc38f2 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,14 +231,8 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); + mLayer->setFrame(frame); - layer_state_t::matrix22_t matrix; - matrix.dsdx = frame.getWidth() / static_cast(SevenSegmentDrawer::getWidth()); - matrix.dtdx = 0; - matrix.dtdy = 0; - matrix.dsdy = frame.getHeight() / static_cast(SevenSegmentDrawer::getHeight()); - mLayer->setMatrix(matrix, true); - mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b1d63f0ce7..a387587d7f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3936,6 +3936,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eFrameChanged) { + if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; + } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 47a150dd35..03f8e1afba 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - mBufferSize.set(1000.0, 1000.0); + const float width = 1000.0; + const float height = 1000.0; auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, - setBufferWithContext); + mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,9 +309,7 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, - vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, - 1.0f / mBufferSize.height}); + mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -374,10 +372,6 @@ status_t BufferGenerator::get(sp* outBuffer, sp* outFence) return NO_ERROR; } -ui::Size BufferGenerator::getSize() { - return mBufferSize; -} - // static void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index f7d548b6bf..a3ffe86572 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,7 +37,6 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); - ui::Size getSize(); private: bool mInitialized = false; @@ -54,7 +53,6 @@ private: using Epoch = std::chrono::time_point; Epoch mEpoch = std::chrono::steady_clock::now(); - ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index af00ec7fc9..f470eda7d3 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,6 +149,7 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); + t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index 9fa3d4c417..a8647c3e50 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,6 +161,7 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) + .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 011ff70409..158801a705 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,10 +164,7 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -187,10 +184,7 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -209,10 +203,7 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -247,10 +238,7 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(-100, -100, 100, 100)); - transaction.apply(); + transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -275,15 +263,8 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -309,15 +290,8 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -344,15 +318,8 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -438,15 +405,8 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -531,11 +491,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -567,16 +523,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -616,16 +564,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -666,15 +606,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -728,15 +661,8 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - ui::Size bufferSize = getBufferSize(); - - TransactionUtils::setFrame(transaction1, layer1, - Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - - transaction2.merge(std::move(transaction1)).apply(); + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -756,10 +682,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - TransactionUtils::setFrame(transaction2, layer2, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(32, 32, 64, 64)); - transaction2.merge(std::move(transaction1)).apply(); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -839,10 +762,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - ui::Size bufferSize = getBufferSize(); - TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -861,10 +781,7 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - TransactionUtils::setFrame(transaction, layer, - Rect(0, 0, bufferSize.width, bufferSize.height), - Rect(0, 0, 32, 32)); - transaction.apply(); + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 53d230abe7..7505e6ea9b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,7 +204,11 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(16, 16, 48, 48)) + .setRelativeLayer(layerG, layerR, 1) + .apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -256,9 +260,10 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setPosition(layerG, 8, 8) + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(8, 8, 40, 40)) .setRelativeLayer(layerG, layerR, 3) - .setPosition(layerB, 16, 16) + .setFrame(layerB, Rect(16, 16, 48, 48)) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -383,6 +388,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) + .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -441,7 +447,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setPosition(layerR, 16, 16) + .setFrame(layerR, Rect(16, 16, 48, 48)) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -471,7 +477,8 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setPosition(layer2, 16, 0) + .setFrame(layer1, Rect(0, 0, 32, 32)) + .setFrame(layer2, Rect(16, 0, 48, 32)) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -566,7 +573,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); + Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -842,39 +849,42 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); + Transaction() + .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, - Color::WHITE, Color::BLUE); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, - Color::RED, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, - Color::WHITE, Color::GREEN); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, 1 /* tolerance */); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); } } @@ -945,8 +955,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -976,13 +986,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); } } @@ -1006,6 +1016,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); + Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); + Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1013,8 +1025,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1022,8 +1034,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 16, 32, 64), Color::RED); - shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1031,7 +1043,9 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); + shot->expectColor(Rect(0, 16, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1054,11 +1068,12 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); + Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(40, 40, 56, 56), Color::RED); - shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1106,10 +1121,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction t; - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); - t.apply(); - + Transaction().setFrame(layer, frame).apply(); auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1121,23 +1133,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction t; { SCOPED_TRACE("empty rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); - t.apply(); - + Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); - t.apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 8, 8), Color::RED); - shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); + Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1147,10 +1152,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A layer with a buffer will have a computed size that matches the buffer size. + // A parentless layer will default to a frame with the same size as the buffer auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::RED); - shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1158,16 +1163,17 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1177,14 +1183,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer with a buffer will have a computed size that matches the buffer size. + // A layer will default to the frame of its parent auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1193,10 +1199,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setPosition(layer, 16, 16).apply(); + Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1208,20 +1215,18 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Rect childDst(0, 16, 32, 32); - Transaction t; - TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); - t.apply(); + Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(childDst, Color::BLUE); + shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1233,8 +1238,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1247,8 +1252,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1256,8 +1261,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1265,8 +1270,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } } @@ -1281,6 +1286,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1289,6 +1295,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1343,8 +1350,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1376,8 +1383,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } idx++; } @@ -1409,8 +1416,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), color); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1428,6 +1435,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1444,6 +1452,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1460,6 +1469,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1508,8 +1518,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1524,8 +1534,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1542,8 +1552,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1560,8 +1570,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1576,8 +1586,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 0bc8fe7aa0..87c7b7d829 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,11 +244,6 @@ protected: return bufferGenerator.get(outBuffer, outFence); } - static ui::Size getBufferSize() { - static BufferGenerator bufferGenerator; - return bufferGenerator.getSize(); - } - sp mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index edf55ea6ef..ac5e297e43 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,7 +196,17 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - Transaction().setCornerRadius(layer, cornerRadius).apply(); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setCrop(layer, Rect(0, 0, size, size)) + .apply(); + } else { + Transaction() + .setCornerRadius(layer, cornerRadius) + .setFrame(layer, Rect(0, 0, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -224,13 +234,19 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) - .apply(); + auto transaction = Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + transaction.setCrop(parent, Rect(0, 0, size, size)); + } else { + transaction.setFrame(parent, Rect(0, 0, size, size)); + } + transaction.apply(); { const uint8_t bottom = size - 1; @@ -259,12 +275,21 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - Transaction() - .setCornerRadius(parent, cornerRadius) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - + if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + } else { + Transaction() + .setCornerRadius(parent, cornerRadius) + .setFrame(parent, Rect(0, 0, size, size)) + .reparent(child, parent) + .setFrame(child, Rect(0, size / 2, size, size)) + .apply(); + } { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -306,9 +331,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) + .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) + .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) + .setFrame(rightLayer, rightRect) .apply(); { @@ -324,6 +352,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) + .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -406,8 +435,10 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) + .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) + .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -426,6 +457,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect + .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index ccf434d63a..613b21ef04 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().show(bufferStateLayer).apply(); + Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 8c448e2f96..3cbfed98f5 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,22 +161,6 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } - - static void setFrame(Transaction& t, const sp& sc, Rect source, Rect dest, - int32_t transform = 0) { - uint32_t sourceWidth = source.getWidth(); - uint32_t sourceHeight = source.getHeight(); - - if (transform & ui::Transform::ROT_90) { - std::swap(sourceWidth, sourceHeight); - } - - float dsdx = dest.getWidth() / static_cast(sourceWidth); - float dsdy = dest.getHeight() / static_cast(sourceHeight); - - t.setMatrix(sc, dsdx, 0, 0, dsdy); - t.setPosition(sc, dest.left, dest.top); - } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; -- cgit v1.2.3-59-g8ed1b From a5aedbd7ffaf42b7f287b587035018b42d61a41c Mon Sep 17 00:00:00 2001 From: Chavi Weingarten Date: Fri, 9 Apr 2021 13:37:33 +0000 Subject: Revert^2 "Remove setFrame from BufferStateLayer" 1014c4bf14f5c250b78d7e917fb59aaa9b0d9b0a Change-Id: I4c1cbc2b40e4f5f68bd5e6dcbe6c77405ad155b0 --- libs/gui/BLASTBufferQueue.cpp | 29 +++- libs/gui/LayerState.cpp | 4 - libs/gui/SurfaceComposerClient.cpp | 14 -- libs/gui/include/gui/BLASTBufferQueue.h | 32 +++- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 1 - libs/gui/tests/BLASTBufferQueue_test.cpp | 34 ++-- services/surfaceflinger/BufferStateLayer.cpp | 98 +++++------- services/surfaceflinger/BufferStateLayer.h | 10 +- services/surfaceflinger/Layer.cpp | 4 +- services/surfaceflinger/Layer.h | 1 - services/surfaceflinger/RefreshRateOverlay.cpp | 8 +- services/surfaceflinger/SurfaceFlinger.cpp | 3 - services/surfaceflinger/tests/BufferGenerator.cpp | 14 +- services/surfaceflinger/tests/BufferGenerator.h | 2 + services/surfaceflinger/tests/EffectLayer_test.cpp | 1 - services/surfaceflinger/tests/IPC_test.cpp | 1 - .../surfaceflinger/tests/LayerCallback_test.cpp | 131 +++++++++++++--- .../tests/LayerRenderTypeTransaction_test.cpp | 174 ++++++++++----------- .../surfaceflinger/tests/LayerTransactionTest.h | 5 + .../LayerTypeAndRenderTypeTransaction_test.cpp | 60 ++----- services/surfaceflinger/tests/MirrorLayer_test.cpp | 2 +- .../surfaceflinger/tests/utils/TransactionUtils.h | 18 ++- 23 files changed, 353 insertions(+), 295 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp index bcdd06b6c8..e5afd408a9 100644 --- a/libs/gui/BLASTBufferQueue.cpp +++ b/libs/gui/BLASTBufferQueue.cpp @@ -204,13 +204,16 @@ void BLASTBufferQueue::update(const sp& surface, uint32_t width, if (mRequestedSize != newSize) { mRequestedSize.set(newSize); mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height); - if (mLastBufferScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { + if (mLastBufferInfo.scalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) { // If the buffer supports scaling, update the frame immediately since the client may // want to scale the existing buffer to the new size. mSize = mRequestedSize; - t.setFrame(mSurfaceControl, - {0, 0, static_cast(mSize.width), - static_cast(mSize.height)}); + // We only need to update the scale if we've received at least one buffer. The reason + // for this is the scale is calculated based on the requested size and buffer size. + // If there's no buffer, the scale will always be 1. + if (mLastBufferInfo.hasBuffer) { + setMatrix(&t, mLastBufferInfo); + } applyTransaction = true; } } @@ -374,8 +377,10 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback. incStrong((void*)transactionCallbackThunk); - mLastBufferScalingMode = bufferItem.mScalingMode; mLastAcquiredFrameNumber = bufferItem.mFrameNumber; + mLastBufferInfo.update(true /* hasBuffer */, bufferItem.mGraphicBuffer->getWidth(), + bufferItem.mGraphicBuffer->getHeight(), bufferItem.mTransform, + bufferItem.mScalingMode); auto releaseBufferCallback = std::bind(releaseBufferCallbackThunk, wp(this) /* callbackContext */, @@ -388,8 +393,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) { bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE); t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast(this)); - t->setFrame(mSurfaceControl, - {0, 0, static_cast(mSize.width), static_cast(mSize.height)}); + setMatrix(t, mLastBufferInfo); t->setCrop(mSurfaceControl, computeCrop(bufferItem)); t->setTransform(mSurfaceControl, bufferItem.mTransform); t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse); @@ -515,6 +519,17 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) { return mSize != bufferSize; } +void BLASTBufferQueue::setMatrix(SurfaceComposerClient::Transaction* t, + const BufferInfo& bufferInfo) { + uint32_t bufWidth = bufferInfo.width; + uint32_t bufHeight = bufferInfo.height; + + float dsdx = mSize.width / static_cast(bufWidth); + float dsdy = mSize.height / static_cast(bufHeight); + + t->setMatrix(mSurfaceControl, dsdx, 0, 0, dsdy); +} + void BLASTBufferQueue::setTransactionCompleteCallback( uint64_t frameNumber, std::function&& transactionCompleteCallback) { std::lock_guard _lock{mMutex}; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 5b213ad5c3..809438534c 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -455,10 +455,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eCropChanged; crop = other.crop; } - if (other.what & eFrameChanged) { - what |= eFrameChanged; - orientedDisplaySpaceRect = other.orientedDisplaySpaceRect; - } if (other.what & eBufferChanged) { what |= eBufferChanged; buffer = other.buffer; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index e01a5aee32..9ce094aa77 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1232,20 +1232,6 @@ SurfaceComposerClient::Transaction::setTransformToDisplayInverse(const sp& sc, const Rect& frame) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eFrameChanged; - s->orientedDisplaySpaceRect = frame; - - registerSurfaceControlForCallback(sc); - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setBuffer( const sp& sc, const sp& buffer, ReleaseBufferCallback callback) { diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h index fbd16f4ea2..a48f95ae73 100644 --- a/libs/gui/include/gui/BLASTBufferQueue.h +++ b/libs/gui/include/gui/BLASTBufferQueue.h @@ -142,6 +142,33 @@ private: ui::Size mRequestedSize GUARDED_BY(mMutex); int32_t mFormat GUARDED_BY(mMutex); + struct BufferInfo { + bool hasBuffer = false; + uint32_t width; + uint32_t height; + uint32_t transform; + // This is used to check if we should update the blast layer size immediately or wait until + // we get the next buffer. This will support scenarios where the layer can change sizes + // and the buffer will scale to fit the new size. + uint32_t scalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + + void update(bool hasBuffer, uint32_t width, uint32_t height, uint32_t transform, + uint32_t scalingMode) { + this->hasBuffer = hasBuffer; + this->width = width; + this->height = height; + this->transform = transform; + this->scalingMode = scalingMode; + } + }; + + // Last acquired buffer's info. This is used to calculate the correct scale when size change is + // requested. We need to use the old buffer's info to determine what scale we need to apply to + // ensure the correct size. + BufferInfo mLastBufferInfo GUARDED_BY(mMutex); + void setMatrix(SurfaceComposerClient::Transaction* t, const BufferInfo& bufferInfo) + REQUIRES(mMutex); + uint32_t mTransformHint GUARDED_BY(mMutex); sp mConsumer; @@ -159,11 +186,6 @@ private: std::queue mNextFrameTimelineInfoQueue GUARDED_BY(mMutex); - // Last acquired buffer's scaling mode. This is used to check if we should update the blast - // layer size immediately or wait until we get the next buffer. This will support scenarios - // where the layer can change sizes and the buffer will scale to fit the new size. - uint32_t mLastBufferScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; - // Tracks the last acquired frame number uint64_t mLastAcquiredFrameNumber GUARDED_BY(mMutex) = 0; diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 65d771053b..41a022f90e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -105,7 +105,7 @@ struct layer_state_t { eHasListenerCallbacksChanged = 0x20000000, eInputInfoChanged = 0x40000000, eCornerRadiusChanged = 0x80000000, - eFrameChanged = 0x1'00000000, + /* was eFrameChanged, now available 0x1'00000000, */ eCachedBufferChanged = 0x2'00000000, eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 2487961426..1590b10a00 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -473,7 +473,6 @@ public: Transaction& setTransform(const sp& sc, uint32_t transform); Transaction& setTransformToDisplayInverse(const sp& sc, bool transformToDisplayInverse); - Transaction& setFrame(const sp& sc, const Rect& frame); Transaction& setBuffer(const sp& sc, const sp& buffer, ReleaseBufferCallback callback = nullptr); Transaction& setCachedBuffer(const sp& sc, int32_t bufferId); diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp index fe48d88376..9b1f0db83b 100644 --- a/libs/gui/tests/BLASTBufferQueue_test.cpp +++ b/libs/gui/tests/BLASTBufferQueue_test.cpp @@ -140,7 +140,6 @@ protected: /*parent*/ nullptr); t.setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) - .setFrame(mSurfaceControl, Rect(resolution)) .show(mSurfaceControl) .setDataspace(mSurfaceControl, ui::Dataspace::V0_SRGB) .apply(); @@ -218,13 +217,13 @@ protected: col >= region.left - border && col < region.right + border; } if (!outsideRegion && inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } else if (outsideRegion && !inRegion) { - EXPECT_GE(epsilon, abs(r - *(pixel))); - EXPECT_GE(epsilon, abs(g - *(pixel + 1))); - EXPECT_GE(epsilon, abs(b - *(pixel + 2))); + ASSERT_GE(epsilon, abs(r - *(pixel))); + ASSERT_GE(epsilon, abs(g - *(pixel + 1))); + ASSERT_GE(epsilon, abs(b - *(pixel + 2))); } ASSERT_EQ(false, ::testing::Test::HasFailure()); } @@ -466,7 +465,8 @@ TEST_F(BLASTBufferQueueTest, SetCrop_Item) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { @@ -523,13 +523,15 @@ TEST_F(BLASTBufferQueueTest, SetCrop_ScalingModeScaleCrop) { // capture screen and verify that it is red ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); + Rect bounds; + bounds.left = finalCropSideLength / 2; + bounds.top = 0; + bounds.right = bounds.left + finalCropSideLength; + bounds.bottom = finalCropSideLength; + + ASSERT_NO_FATAL_FAILURE(checkScreenCapture(r, g, b, bounds)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength})); - ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(0, 0, 0, - {0, 0, (int32_t)bufferSideLength, (int32_t)bufferSideLength}, - /*border*/ 0, /*outsideRegion*/ true)); + checkScreenCapture(0, 0, 0, bounds, /*border*/ 0, /*outsideRegion*/ true)); } class TestProducerListener : public BnProducerListener { @@ -596,7 +598,6 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { t.setLayerStack(bgSurface, 0) .show(bgSurface) .setDataspace(bgSurface, ui::Dataspace::V0_SRGB) - .setFrame(bgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)) .setLayer(bgSurface, std::numeric_limits::max() - 1) .apply(); @@ -619,7 +620,8 @@ TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) { ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults)); ASSERT_NO_FATAL_FAILURE( - checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight})); + checkScreenCapture(r, g, b, + {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight / 2})); } class BLASTBufferQueueTransformTest : public BLASTBufferQueueTest { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 48a0be2c45..ed826a0100 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -278,9 +278,8 @@ bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { return stateUpdateAvailable; } -// Crop that applies to the window -Rect BufferStateLayer::getCrop(const Layer::State& /*s*/) const { - return Rect::INVALID_RECT; +Rect BufferStateLayer::getCrop(const Layer::State& s) const { + return s.crop; } bool BufferStateLayer::setTransform(uint32_t transform) { @@ -301,57 +300,53 @@ bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInver } bool BufferStateLayer::setCrop(const Rect& crop) { - Rect c = crop; - if (c.left < 0) { - c.left = 0; - } - if (c.top < 0) { - c.top = 0; - } - // If the width and/or height are < 0, make it [0, 0, -1, -1] so the equality comparision below - // treats all invalid rectangles the same. - if (!c.isValid()) { - c.makeInvalid(); - } + if (mCurrentState.crop == crop) return false; + mCurrentState.sequence++; + mCurrentState.crop = crop; - if (mCurrentState.crop == c) return false; - mCurrentState.crop = c; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } -bool BufferStateLayer::setFrame(const Rect& frame) { - int x = frame.left; - int y = frame.top; - int w = frame.getWidth(); - int h = frame.getHeight(); - - if (x < 0) { - x = 0; - w = frame.right; +bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, + bool allowNonRectPreservingTransforms) { + if (mCurrentState.transform.dsdx() == matrix.dsdx && + mCurrentState.transform.dtdy() == matrix.dtdy && + mCurrentState.transform.dtdx() == matrix.dtdx && + mCurrentState.transform.dsdy() == matrix.dsdy) { + return false; } - if (y < 0) { - y = 0; - h = frame.bottom; - } + ui::Transform t; + t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y && - mCurrentState.width == w && mCurrentState.height == h) { + if (!allowNonRectPreservingTransforms && !t.preserveRects()) { + ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER nor " + "ROTATE_SURFACE_FLINGER ignored"); return false; } - if (!frame.isValid()) { - x = y = w = h = 0; + mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + + return true; +} + +bool BufferStateLayer::setPosition(float x, float y) { + if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) { + return false; } + mCurrentState.transform.set(x, y); - mCurrentState.width = w; - mCurrentState.height = h; mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + return true; } @@ -428,6 +423,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spmFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE); } + + mCurrentState.width = mCurrentState.buffer->width; + mCurrentState.height = mCurrentState.buffer->height; + return true; } @@ -858,33 +857,6 @@ sp BufferStateLayer::createClone() { return layer; } -Layer::RoundedCornerState BufferStateLayer::getRoundedCornerState() const { - const auto& p = mDrawingParent.promote(); - if (p != nullptr) { - RoundedCornerState parentState = p->getRoundedCornerState(); - if (parentState.radius > 0) { - ui::Transform t = getActiveTransform(getDrawingState()); - t = t.inverse(); - parentState.cropRect = t.transform(parentState.cropRect); - // The rounded corners shader only accepts 1 corner radius for performance reasons, - // but a transform matrix can define horizontal and vertical scales. - // Let's take the average between both of them and pass into the shader, practically we - // never do this type of transformation on windows anyway. - parentState.radius *= (t[0][0] + t[1][1]) / 2.0f; - return parentState; - } - } - const float radius = getDrawingState().cornerRadius; - const State& s(getDrawingState()); - if (radius <= 0 || (getActiveWidth(s) == UINT32_MAX && getActiveHeight(s) == UINT32_MAX)) - return RoundedCornerState(); - return RoundedCornerState(FloatRect(static_cast(s.transform.tx()), - static_cast(s.transform.ty()), - static_cast(s.transform.tx() + s.width), - static_cast(s.transform.ty() + s.height)), - radius); -} - bool BufferStateLayer::bufferNeedsFiltering() const { const State& s(getDrawingState()); if (!s.buffer) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 3878f50776..8ce3e1f55b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,7 +66,6 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setFrame(const Rect& frame) override; bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, @@ -81,15 +80,13 @@ public: bool setTransactionCompletedListeners(const std::vector>& handles) override; bool addFrameEvent(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime) override; + bool setPosition(float /*x*/, float /*y*/) override; + bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, + bool /*allowNonRectPreservingTransforms*/); // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; - bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, - bool /*allowNonRectPreservingTransforms*/) override { - return false; - } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} void deferTransactionUntil_legacy(const sp& /*barrierLayer*/, @@ -97,7 +94,6 @@ public: Rect getBufferSize(const State& s) const override; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; - Layer::RoundedCornerState getRoundedCornerState() const override; void setAutoRefresh(bool autoRefresh) override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 94fd62fa7a..6038658ee6 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2287,8 +2287,8 @@ Layer::RoundedCornerState Layer::getRoundedCornerState() const { } } const float radius = getDrawingState().cornerRadius; - return radius > 0 && getCrop(getDrawingState()).isValid() - ? RoundedCornerState(getCrop(getDrawingState()).toFloatRect(), radius) + return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid() + ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius) : RoundedCornerState(); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3a45c949a4..5528a8190f 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -412,7 +412,6 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setFrame(const Rect& /*frame*/) { return false; }; virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 1d00cc38f2..7a3e433660 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -231,8 +231,14 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin void RefreshRateOverlay::setViewport(ui::Size viewport) { Rect frame((3 * viewport.width) >> 4, viewport.height >> 5); frame.offsetBy(viewport.width >> 5, viewport.height >> 4); - mLayer->setFrame(frame); + layer_state_t::matrix22_t matrix; + matrix.dsdx = frame.getWidth() / static_cast(SevenSegmentDrawer::getWidth()); + matrix.dtdx = 0; + matrix.dtdy = 0; + matrix.dsdy = frame.getHeight() / static_cast(SevenSegmentDrawer::getHeight()); + mLayer->setMatrix(matrix, true); + mLayer->setPosition(frame.left, frame.top); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 825834bb4f..8a8ccb91c0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4033,9 +4033,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eCropChanged) { if (layer->setCrop(s.crop)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eFrameChanged) { - if (layer->setFrame(s.orientedDisplaySpaceRect)) flags |= eTraversalNeeded; - } if (what & layer_state_t::eAcquireFenceChanged) { if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded; } diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 03f8e1afba..47a150dd35 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -296,12 +296,12 @@ private: BufferGenerator::BufferGenerator() : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) { - const float width = 1000.0; - const float height = 1000.0; + mBufferSize.set(1000.0, 1000.0); auto setBufferWithContext = std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this); - mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext); + mSurfaceManager->initialize(mBufferSize.width, mBufferSize.height, HAL_PIXEL_FORMAT_RGBA_8888, + setBufferWithContext); if (!mEglManager->initialize(mSurfaceManager->getSurface())) return; @@ -309,7 +309,9 @@ BufferGenerator::BufferGenerator() if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return; mProgram->use(); - mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height}); + mProgram->bindVec4(0, + vec4{mBufferSize.width, mBufferSize.height, 1.0f / mBufferSize.width, + 1.0f / mBufferSize.height}); mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4); glEnableVertexAttribArray(0); @@ -372,6 +374,10 @@ status_t BufferGenerator::get(sp* outBuffer, sp* outFence) return NO_ERROR; } +ui::Size BufferGenerator::getSize() { + return mBufferSize; +} + // static void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, void* bufferGenerator) { diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h index a3ffe86572..f7d548b6bf 100644 --- a/services/surfaceflinger/tests/BufferGenerator.h +++ b/services/surfaceflinger/tests/BufferGenerator.h @@ -37,6 +37,7 @@ public: /* Static callback that sets the fence on a particular instance */ static void setBuffer(const sp& buffer, int32_t fence, void* fenceGenerator); + ui::Size getSize(); private: bool mInitialized = false; @@ -53,6 +54,7 @@ private: using Epoch = std::chrono::time_point; Epoch mEpoch = std::chrono::steady_clock::now(); + ui::Size mBufferSize; }; } // namespace android diff --git a/services/surfaceflinger/tests/EffectLayer_test.cpp b/services/surfaceflinger/tests/EffectLayer_test.cpp index f470eda7d3..af00ec7fc9 100644 --- a/services/surfaceflinger/tests/EffectLayer_test.cpp +++ b/services/surfaceflinger/tests/EffectLayer_test.cpp @@ -149,7 +149,6 @@ TEST_F(EffectLayerTest, BlurEffectLayerIsVisible) { t.reparent(blurLayer, mParentLayer); t.setBackgroundBlurRadius(blurLayer, blurRadius); t.setCrop(blurLayer, blurRect); - t.setFrame(blurLayer, blurRect); t.setAlpha(blurLayer, 0.0f); t.show(blurLayer); }); diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp index a8647c3e50..9fa3d4c417 100644 --- a/services/surfaceflinger/tests/IPC_test.cpp +++ b/services/surfaceflinger/tests/IPC_test.cpp @@ -161,7 +161,6 @@ public: Color::RED); transaction->setLayerStack(mSurfaceControl, 0) .setLayer(mSurfaceControl, std::numeric_limits::max()) - .setFrame(mSurfaceControl, Rect(0, 0, width, height)) .setBuffer(mSurfaceControl, gb) .setAcquireFence(mSurfaceControl, fence) .show(mSurfaceControl) diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 158801a705..011ff70409 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -164,7 +164,10 @@ TEST_F(LayerCallbackTest, NoBufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, @@ -184,7 +187,10 @@ TEST_F(LayerCallbackTest, BufferNoColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -203,7 +209,10 @@ TEST_F(LayerCallbackTest, NoBufferColor) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, @@ -238,7 +247,10 @@ TEST_F(LayerCallbackTest, OffScreen) { return; } - transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(-100, -100, 100, 100)); + transaction.apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -263,8 +275,15 @@ TEST_F(LayerCallbackTest, MergeBufferNoColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -290,8 +309,15 @@ TEST_F(LayerCallbackTest, MergeNoBufferColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -318,8 +344,15 @@ TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); @@ -405,8 +438,15 @@ TEST_F(LayerCallbackTest, Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -491,7 +531,11 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { } } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expected; expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED @@ -523,8 +567,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -564,8 +616,16 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, @@ -606,8 +666,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateCha return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -661,8 +728,15 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + ui::Size bufferSize = getBufferSize(); + + TransactionUtils::setFrame(transaction1, layer1, + Rect(0, 0, bufferSize.width, bufferSize.height), Rect(0, 0, 32, 32)); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + + transaction2.merge(std::move(transaction1)).apply(); ExpectedResult expected; expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); @@ -682,7 +756,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateC return; } - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + TransactionUtils::setFrame(transaction2, layer2, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(32, 32, 64, 64)); + transaction2.merge(std::move(transaction1)).apply(); expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, ExpectedResult::Buffer::NOT_ACQUIRED); @@ -762,7 +839,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + ui::Size bufferSize = getBufferSize(); + TransactionUtils::setFrame(transaction, layer, Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); ExpectedResult expectedResult; expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); @@ -781,7 +861,10 @@ TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { return; } - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + TransactionUtils::setFrame(transaction, layer, + Rect(0, 0, bufferSize.width, bufferSize.height), + Rect(0, 0, 32, 32)); + transaction.apply(); } EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); } diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 7505e6ea9b..53d230abe7 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -204,11 +204,7 @@ void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(16, 16, 48, 48)) - .setRelativeLayer(layerG, layerR, 1) - .apply(); + Transaction().setPosition(layerG, 16, 16).setRelativeLayer(layerG, layerR, 1).apply(); break; default: ASSERT_FALSE(true) << "Unsupported layer type"; @@ -260,10 +256,9 @@ void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) break; case ISurfaceComposerClient::eFXSurfaceBufferState: Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(8, 8, 40, 40)) + .setPosition(layerG, 8, 8) .setRelativeLayer(layerG, layerR, 3) - .setFrame(layerB, Rect(16, 16, 48, 48)) + .setPosition(layerB, 16, 16) .setLayer(layerB, mLayerZBase + 2) .apply(); break; @@ -388,7 +383,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState Transaction() .setTransparentRegionHint(layer, Region(top)) .setBuffer(layer, buffer) - .setFrame(layer, Rect(0, 0, 32, 32)) .apply(); { SCOPED_TRACE("top transparent"); @@ -447,7 +441,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_Buffe // check that transparent region hint is bound by the layer size Transaction() .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setFrame(layerR, Rect(16, 16, 48, 48)) + .setPosition(layerR, 16, 16) .setLayer(layerR, mLayerZBase + 1) .apply(); ASSERT_NO_FATAL_FAILURE( @@ -477,8 +471,7 @@ void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { Transaction() .setAlpha(layer1, 0.25f) .setAlpha(layer2, 0.75f) - .setFrame(layer1, Rect(0, 0, 32, 32)) - .setFrame(layer2, Rect(16, 0, 48, 32)) + .setPosition(layer2, 16, 0) .setLayer(layer2, mLayerZBase + 1) .apply(); break; @@ -573,7 +566,7 @@ void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); expectedColor = fillColor; } - Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); + Transaction().setCrop(layer, Rect(0, 0, width, height)).apply(); break; default: GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; @@ -849,42 +842,39 @@ TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE)); - Transaction() - .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) - .setFrame(layer, Rect(0, 0, 32, 32)) - .apply(); + Transaction().setPosition(layer, 32, 32).setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + getScreenCapture()->expectQuadrant(Rect(32, 32, 64, 64), Color::RED, Color::GREEN, Color::BLUE, Color::WHITE); } Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); { SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::GREEN, Color::RED, + Color::WHITE, Color::BLUE); } Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); { SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 0, 64, 32), Color::BLUE, Color::WHITE, + Color::RED, Color::GREEN); } Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); { SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(0, 32, 32, 64), Color::BLUE, Color::RED, + Color::WHITE, Color::GREEN); } Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); { SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); + getScreenCapture()->expectQuadrant(Rect(32, 32, 96, 96), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE, 1 /* tolerance */); } } @@ -955,8 +945,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { Transaction().setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { @@ -986,13 +976,13 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { { SCOPED_TRACE("empty rect"); Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } { SCOPED_TRACE("negative rect"); Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); } } @@ -1016,8 +1006,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); - Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); - Transaction().setBuffer(layer, buffer).apply(); // Partially out of bounds in the negative (upper left) direction @@ -1025,8 +1013,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, negative (upper left) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 16), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 16), Color::BLACK); } // Partially out of bounds in the positive (lower right) direction @@ -1034,8 +1022,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("out of bounds, positive (lower right) direction"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 16, 32, 64), Color::RED); + shot->expectBorder(Rect(0, 16, 32, 64), Color::BLACK); } // Fully out of buffer space bounds @@ -1043,9 +1031,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { { SCOPED_TRACE("Fully out of bounds"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); - shot->expectColor(Rect(0, 16, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLACK); } } @@ -1068,12 +1054,11 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Rect frame(32, 32, 64, 64); const Rect crop(8, 8, 24, 24); - Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); + Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply(); auto shot = getScreenCapture(); - shot->expectColor(frame, Color::RED); - shot->expectBorder(frame, Color::BLACK); + shot->expectColor(Rect(40, 40, 56, 56), Color::RED); + shot->expectBorder(Rect(40, 40, 56, 56), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { @@ -1121,7 +1106,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); const Rect frame(8, 8, 24, 24); - Transaction().setFrame(layer, frame).apply(); + Transaction t; + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), frame); + t.apply(); + auto shot = getScreenCapture(); shot->expectColor(frame, Color::RED); shot->expectBorder(frame, Color::BLACK); @@ -1133,16 +1121,23 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction t; { SCOPED_TRACE("empty rect"); - Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 8, 8)); + t.apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); } { SCOPED_TRACE("negative rect"); - Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + TransactionUtils::setFrame(t, layer, Rect(0, 0, 32, 32), Rect(8, 8, 0, 0)); + t.apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 8, 8), Color::RED); + shot->expectBorder(Rect(0, 0, 8, 8), Color::BLACK); } } @@ -1152,10 +1147,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - // A parentless layer will default to a frame with the same size as the buffer + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 10, 10), Color::RED); + shot->expectBorder(Rect(0, 0, 10, 10), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { @@ -1163,17 +1158,16 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1183,14 +1177,14 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); Transaction().reparent(child, parent).apply(); - // A layer will default to the frame of its parent + // A layer with a buffer will have a computed size that matches the buffer size. auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 0, 10, 10), Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1199,11 +1193,10 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); std::this_thread::sleep_for(500ms); - Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); + Transaction().setPosition(layer, 16, 16).apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(16, 16, 48, 48), Color::RED); @@ -1215,18 +1208,20 @@ TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState)); Transaction().reparent(child, parent).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); + Rect childDst(0, 16, 32, 32); + Transaction t; + TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst); + t.apply(); auto shot = getScreenCapture(); shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); + shot->expectColor(childDst, Color::BLUE); shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } @@ -1238,8 +1233,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { @@ -1252,8 +1247,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 1"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); @@ -1261,8 +1256,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 2"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); @@ -1270,8 +1265,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { { SCOPED_TRACE("set buffer 3"); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } } @@ -1286,7 +1281,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); - Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); { SCOPED_TRACE("set layer 1 buffer red"); auto shot = getScreenCapture(); @@ -1295,7 +1289,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); - Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); { SCOPED_TRACE("set layer 2 buffer blue"); auto shot = getScreenCapture(); @@ -1350,8 +1343,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1383,8 +1376,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } idx++; } @@ -1416,8 +1409,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt Color color = colors[idx % colors.size()]; auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), color); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } if (idx == 0) { buffers[0].clear(); @@ -1435,7 +1428,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) .apply(); @@ -1452,7 +1444,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) .apply(); @@ -1469,7 +1460,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { Color::BLUE, Color::WHITE)); Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) .apply(); @@ -1518,8 +1508,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { @@ -1534,8 +1524,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { @@ -1552,8 +1542,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { @@ -1570,8 +1560,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { @@ -1586,8 +1576,8 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); } TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 87c7b7d829..0bc8fe7aa0 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -244,6 +244,11 @@ protected: return bufferGenerator.get(outBuffer, outFence); } + static ui::Size getBufferSize() { + static BufferGenerator bufferGenerator; + return bufferGenerator.getSize(); + } + sp mClient; bool deviceSupportsBlurs() { diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index ac5e297e43..edf55ea6ef 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -196,17 +196,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setCrop(layer, Rect(0, 0, size, size)) - .apply(); - } else { - Transaction() - .setCornerRadius(layer, cornerRadius) - .setFrame(layer, Rect(0, 0, size, size)) - .apply(); - } + Transaction().setCornerRadius(layer, cornerRadius).apply(); { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -234,19 +224,13 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusRotated) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); - auto transaction = Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size) - // Rotate by half PI - .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - transaction.setCrop(parent, Rect(0, 0, size, size)); - } else { - transaction.setFrame(parent, Rect(0, 0, size, size)); - } - transaction.apply(); + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size) + // Rotate by half PI + .setMatrix(child, 0.0f, -1.0f, 1.0f, 0.0f) + .apply(); { const uint8_t bottom = size - 1; @@ -275,21 +259,12 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setPosition(child, 0, size / 2) - .apply(); - } else { - Transaction() - .setCornerRadius(parent, cornerRadius) - .setFrame(parent, Rect(0, 0, size, size)) - .reparent(child, parent) - .setFrame(child, Rect(0, size / 2, size, size)) - .apply(); - } + Transaction() + .setCornerRadius(parent, cornerRadius) + .reparent(child, parent) + .setPosition(child, 0, size / 2) + .apply(); + { const uint8_t bottom = size - 1; const uint8_t right = size - 1; @@ -331,12 +306,9 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { Transaction() .setLayer(greenLayer, mLayerZBase) - .setFrame(leftLayer, {0, 0, canvasSize * 2, canvasSize * 2}) .setLayer(leftLayer, mLayerZBase + 1) - .setFrame(leftLayer, leftRect) .setLayer(rightLayer, mLayerZBase + 2) .setPosition(rightLayer, rightRect.left, rightRect.top) - .setFrame(rightLayer, rightRect) .apply(); { @@ -352,7 +324,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) { .setLayer(blurLayer, mLayerZBase + 3) .setBackgroundBlurRadius(blurLayer, blurRadius) .setCrop(blurLayer, blurRect) - .setFrame(blurLayer, blurRect) .setSize(blurLayer, blurRect.getWidth(), blurRect.getHeight()) .setAlpha(blurLayer, 0.0f) .apply(); @@ -435,10 +406,8 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA Transaction() .setLayer(left, mLayerZBase + 1) - .setFrame(left, {0, 0, size, size}) .setLayer(right, mLayerZBase + 2) .setPosition(right, size, 0) - .setFrame(right, {size, 0, size * 2, size}) .apply(); { @@ -457,7 +426,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurAffectedByParentA .setAlpha(blurParent, 0.5) .setLayer(blur, mLayerZBase + 4) .setBackgroundBlurRadius(blur, size) // set the blur radius to the size of one rect - .setFrame(blur, {0, 0, size * 2, size}) .reparent(blur, blurParent) .apply(); diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index 613b21ef04..ccf434d63a 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -195,7 +195,7 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, mChildLayer.get()); fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); - Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); + Transaction().show(bufferStateLayer).apply(); { SCOPED_TRACE("Initial Mirror BufferStateLayer"); diff --git a/services/surfaceflinger/tests/utils/TransactionUtils.h b/services/surfaceflinger/tests/utils/TransactionUtils.h index 3cbfed98f5..8c448e2f96 100644 --- a/services/surfaceflinger/tests/utils/TransactionUtils.h +++ b/services/surfaceflinger/tests/utils/TransactionUtils.h @@ -126,7 +126,7 @@ public: const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4; for (int32_t i = 0; i < width; i++) { const uint8_t expected[4] = {color.r, color.g, color.b, color.a}; - EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare)) + ASSERT_TRUE(std::equal(src, src + 4, expected, colorCompare)) << "pixel @ (" << x + i << ", " << y + j << "): " << "expected (" << color << "), " << "got (" << Color{src[0], src[1], src[2], src[3]} << ")"; @@ -161,6 +161,22 @@ public: ASSERT_EQ(NO_ERROR, s->unlockAndPost()); } } + + static void setFrame(Transaction& t, const sp& sc, Rect source, Rect dest, + int32_t transform = 0) { + uint32_t sourceWidth = source.getWidth(); + uint32_t sourceHeight = source.getHeight(); + + if (transform & ui::Transform::ROT_90) { + std::swap(sourceWidth, sourceHeight); + } + + float dsdx = dest.getWidth() / static_cast(sourceWidth); + float dsdy = dest.getHeight() / static_cast(sourceHeight); + + t.setMatrix(sc, dsdx, 0, 0, dsdy); + t.setPosition(sc, dest.left, dest.top); + } }; enum class RenderPath { SCREENSHOT, VIRTUAL_DISPLAY }; -- cgit v1.2.3-59-g8ed1b From 2daef3c6ba72f364f9ac3859efc1cf2782fff67f Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 2 Apr 2021 16:29:27 -0700 Subject: Add ExternalTexture class into RenderEngine interface ExternalTexture is an RAII structure that wraps raw GraphicBuffers that are passed into RenderEngine. ExternalTexture's role is to help with managing GPU resources of GraphicBuffers by mapping buffers into textures, EGLImages, or AutoBackendTextures depending on the RenderEngine backend. Under the hood, mapExternalTextureBuffer and unmapExternalTextureBuffer (renamed from cacheExternalTextureBuffer and unbindExternalTextureBuffer respectively) are used to help tie resource management to the ExternalTexture lifetime. The main motivation for this is that currently managing buffer lifecycle has historically been errorprone and caused memory leaks, so this improves code health. As part of this: * mapExternalTextureBuffer and unmapExternalTextureBuffer are now protected methods, and are never called outside of RenderEngine with the exception of creating and destroying ExternalTextures. * Because GLESRenderEngine's output buffers are cached differently from Skia RenderEngine, if there are output-only buffers then disable the mapExternalTextureBuffer calls whenever GLESRenderEngine is used. * Custom RAII classes in the Planner and in BufferLayerConsumer are now removed since they're subsumed by ExternalTexture * RenderSurface now controls its own management of ExternalTextures in a small queue * cleanFramebufferCache is now unimplemented for Skia, because ExternalTextures are now deleted whenever a RenderSurface is deleted. Bug: 180767535 Test: libsurfaceflinger_unittest Test: libcompositionengine_test Test: librenderengine_test Test: Simulate virtual displays Test: Screen reotation Test: Movie playback on Google TV Test: Force GPU composition Test: screenshot Change-Id: I222c71e6e1c67485cdeac49e2cb829289af9efec --- libs/renderengine/Android.bp | 1 + libs/renderengine/ExternalTexture.cpp | 43 ++++ libs/renderengine/gl/GLESRenderEngine.cpp | 30 +-- libs/renderengine/gl/GLESRenderEngine.h | 11 +- .../include/renderengine/ExternalTexture.h | 61 ++++++ .../include/renderengine/LayerSettings.h | 8 +- .../include/renderengine/RenderEngine.h | 57 +++--- .../include/renderengine/mock/RenderEngine.h | 9 +- libs/renderengine/skia/AutoBackendTexture.h | 15 +- libs/renderengine/skia/Cache.cpp | 47 +++-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 110 +++++----- libs/renderengine/skia/SkiaGLRenderEngine.h | 16 +- libs/renderengine/skia/SkiaRenderEngine.h | 10 +- libs/renderengine/tests/RenderEngineTest.cpp | 228 +++++++-------------- .../tests/RenderEngineThreadedTest.cpp | 9 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 15 +- libs/renderengine/threaded/RenderEngineThreaded.h | 11 +- services/surfaceflinger/BufferLayer.cpp | 38 ++-- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 56 ++--- services/surfaceflinger/BufferLayerConsumer.h | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 57 +++--- services/surfaceflinger/BufferStateLayer.h | 8 +- services/surfaceflinger/ClientCache.cpp | 13 +- services/surfaceflinger/ClientCache.h | 10 +- .../include/compositionengine/RenderSurface.h | 10 +- .../compositionengine/RenderSurfaceCreationArgs.h | 7 + .../impl/OutputLayerCompositionState.h | 4 +- .../include/compositionengine/impl/RenderSurface.h | 20 +- .../compositionengine/impl/planner/CachedSet.h | 30 +-- .../include/compositionengine/mock/RenderSurface.h | 2 +- .../CompositionEngine/src/Output.cpp | 31 +-- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/src/RenderSurface.cpp | 64 ++++-- .../CompositionEngine/src/planner/CachedSet.cpp | 14 +- .../CompositionEngine/src/planner/Planner.cpp | 7 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 12 +- .../CompositionEngine/tests/OutputTest.cpp | 15 +- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 46 +++-- .../tests/planner/CachedSetTest.cpp | 6 +- services/surfaceflinger/DisplayDevice.cpp | 12 +- services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/Layer.h | 13 +- services/surfaceflinger/RefreshRateOverlay.cpp | 15 +- services/surfaceflinger/RefreshRateOverlay.h | 11 +- services/surfaceflinger/RegionSamplingThread.cpp | 30 ++- services/surfaceflinger/RegionSamplingThread.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 67 +++--- services/surfaceflinger/SurfaceFlinger.h | 12 +- .../tests/unittests/CompositionTest.cpp | 33 +-- .../tests/unittests/TestableSurfaceFlinger.h | 4 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 10 +- .../unittests/TransactionSurfaceFrameTest.cpp | 67 ++++-- 53 files changed, 803 insertions(+), 643 deletions(-) create mode 100644 libs/renderengine/ExternalTexture.cpp create mode 100644 libs/renderengine/include/renderengine/ExternalTexture.h (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index ec39137e24..f395ab43d8 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -48,6 +48,7 @@ filegroup { name: "librenderengine_sources", srcs: [ "Description.cpp", + "ExternalTexture.cpp", "Mesh.cpp", "RenderEngine.cpp", "Texture.cpp", diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp new file mode 100644 index 0000000000..eabff58eba --- /dev/null +++ b/libs/renderengine/ExternalTexture.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2021 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 + +#include "log/log_main.h" + +namespace android::renderengine { + +ExternalTexture::ExternalTexture(const sp& buffer, RenderEngine& renderEngine, + uint32_t usage) + : mBuffer(buffer), mRenderEngine(renderEngine) { + LOG_ALWAYS_FATAL_IF(buffer == nullptr, + "Attempted to bind a null buffer to an external texture!"); + // GLESRenderEngine has a separate texture cache for output buffers, + if (usage == Usage::WRITEABLE && + (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES || + mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) { + return; + } + mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE); +} + +ExternalTexture::~ExternalTexture() { + mRenderEngine.unmapExternalTextureBuffer(mBuffer); +} + +} // namespace android::renderengine diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index a2963a7c33..d87315fdc2 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -746,7 +746,8 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp& buffer) { +void GLESRenderEngine::mapExternalTextureBuffer(const sp& buffer, + bool /*isRenderable*/) { ATRACE_CALL(); mImageManager->cacheAsync(buffer, nullptr); } @@ -797,8 +798,8 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const spreleaseAsync(bufferId, nullptr); +void GLESRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { + mImageManager->releaseAsync(buffer->getId(), nullptr); } std::shared_ptr GLESRenderEngine::unbindExternalTextureBufferForTesting( @@ -1102,7 +1103,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, + const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); @@ -1125,7 +1126,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer); + validateOutputBufferUsage(buffer->getBuffer()); std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an @@ -1142,11 +1143,13 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, if (blurLayersSize == 0) { fbo = std::make_unique(*this, - buffer.get()->getNativeBuffer(), + buffer->getBuffer() + .get() + ->getNativeBuffer(), useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors(); return fbo->getStatus(); } @@ -1157,7 +1160,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors(); return status; } @@ -1194,7 +1197,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't render first blur pass"); return status; } @@ -1203,6 +1206,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique(*this, buffer.get() + ->getBuffer() ->getNativeBuffer(), useFramebufferCache); status = fbo->getStatus(); @@ -1215,7 +1219,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't bind native framebuffer"); return status; } @@ -1223,7 +1227,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't render blur filter"); return status; } @@ -1250,7 +1254,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, disableTexture = false; isOpaque = layer->source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer; + sp gBuf = layer->source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); @@ -1274,7 +1278,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Do not cache protected EGLImage, protected memory is limited. if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) { - unbindExternalTextureBuffer(gBuf->getId()); + unmapExternalTextureBuffer(gBuf); } } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index cd7a86bb0e..e7ed9c01fa 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -60,16 +60,14 @@ public: void primeCache() override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; - void cacheExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); - void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); - bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; bool cleanupPostRender(CleanupMode mode) override; int getContextPriority() override; bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } @@ -105,6 +103,9 @@ protected: EXCLUDES(mFramebufferImageCacheMutex); size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) + EXCLUDES(mRenderingMutex); + void unmapExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); private: friend class BindNativeBufferAsFramebuffer; diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h new file mode 100644 index 0000000000..07f0833d4a --- /dev/null +++ b/libs/renderengine/include/renderengine/ExternalTexture.h @@ -0,0 +1,61 @@ +/* + * Copyright 2021 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 + +namespace android::renderengine { + +class RenderEngine; + +/** + * Manages GPU image resources on behalf of clients using RenderEngine. + * + * Clients of RenderEngine are required to wrap their GraphicBuffer objects as an ExternalTexture, + * which is then mapped into GPU resources required by RenderEngine. When a client no longer needs + * to use the GraphicBuffer as input into RenderEngine::drawLayers, then the client should delete + * their ExternalTexture so that resources may be freed. + */ +class ExternalTexture { +public: + // Usage specifies the rendering intent for the buffer. + enum Usage : uint32_t { + // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a + // hint to load the buffer into a separate cache + READABLE = 1 << 0, + + // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an + // external texture + WRITEABLE = 1 << 1, + }; + // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given + // usage hint of type Usage. + ExternalTexture(const sp& buffer, RenderEngine& renderEngine, uint32_t usage); + + ~ExternalTexture(); + + // Retrieves the buffer that is bound to this texture. + const sp& getBuffer() const { return mBuffer; } + +private: + sp mBuffer; + RenderEngine& mRenderEngine; + DISALLOW_COPY_AND_ASSIGN(ExternalTexture); +}; + +} // namespace android::renderengine diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 7661233967..c54c5ba047 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -16,11 +16,9 @@ #pragma once -#include - #include #include -#include +#include #include #include #include @@ -31,6 +29,8 @@ #include #include +#include + namespace android { namespace renderengine { @@ -39,7 +39,7 @@ struct Buffer { // Buffer containing the image that we will render. // If buffer == nullptr, then the rest of the fields in this struct will be // ignored. - sp buffer = nullptr; + std::shared_ptr buffer = nullptr; // Fence that will fire when the buffer is ready to be bound. sp fence = nullptr; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 8dd98c3ba3..c8a0f0a034 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -17,19 +17,20 @@ #ifndef SF_RENDERENGINE_H_ #define SF_RENDERENGINE_H_ -#include -#include -#include - #include #include #include +#include #include #include #include +#include +#include #include #include +#include + /** * Allows to set RenderEngine backend to GLES (default) or SkiaGL (NOT yet supported). */ @@ -51,6 +52,7 @@ class Region; namespace renderengine { +class ExternalTexture; class Image; class Mesh; class Texture; @@ -104,23 +106,6 @@ public: virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - // Caches Image resources for this buffer, but does not bind the buffer to - // a particular texture. - // Note that work is deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that cache/unbind calls - // are performed in a manner that's conflict serializable, i.e. unbinding - // a buffer should never occur before binding the buffer if the caller - // called {bind, cache}ExternalTextureBuffer before calling unbind. - virtual void cacheExternalTextureBuffer(const sp& buffer) = 0; - // Removes internal resources referenced by the bufferId. This method should be - // invoked when the caller will no longer hold a reference to a GraphicBuffer - // and needs to clean up its resources. - // Note that work is deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that cache/unbind calls - // are performed in a manner that's conflict serializable, i.e. unbinding - // a buffer should never occur before binding the buffer if the caller - // called {bind, cache}ExternalTextureBuffer before calling unbind. - virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0; enum class CleanupMode { CLEAN_OUTPUT_RESOURCES, @@ -191,8 +176,9 @@ public: // now, this always returns NO_ERROR. virtual status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) = 0; virtual void cleanFramebufferCache() = 0; // Returns the priority this context was actually created with. Note: this may not be // the same as specified at context creation time, due to implementation limits on the @@ -213,6 +199,31 @@ public: static void validateOutputBufferUsage(const sp&); protected: + // Maps GPU resources for this buffer. + // Note that work may be deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that map/unmap calls + // are performed in a manner that's conflict serializable, i.e. unmapping + // a buffer should never occur before binding the buffer if the caller + // called mapExternalTextureBuffer before calling unmap. + // Note also that if the buffer contains protected content, then mapping those GPU resources may + // be deferred until the buffer is really used for drawing. This is because typical SoCs that + // support protected memory only support a limited amount, so optimisitically mapping protected + // memory may be too burdensome. If a buffer contains protected content and the RenderEngine + // implementation supports protected context, then GPU resources may be mapped into both the + // protected and unprotected contexts. + // If the buffer may ever be written to by RenderEngine, then isRenderable must be true. + virtual void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) = 0; + // Unmaps GPU resources used by this buffer. This method should be + // invoked when the caller will no longer hold a reference to a GraphicBuffer + // and needs to clean up its resources. + // Note that if there are multiple callers holding onto the same buffer, then the buffer's + // resources may be internally ref-counted to guard against use-after-free errors. Note that + // work may be deferred to an additional thread, i.e. this call is expected to be made + // asynchronously, but the caller can expect that map/unmap calls are performed in a manner + // that's conflict serializable, i.e. unmap a buffer should never occur before binding the + // buffer if the caller called mapExternalTextureBuffer before calling unmap. + virtual void unmapExternalTextureBuffer(const sp& buffer) = 0; + friend class ExternalTexture; friend class threaded::RenderEngineThreaded; const RenderEngineType mRenderEngineType; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 228553d643..27dbd1ecf3 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -39,8 +39,6 @@ public: MOCK_METHOD1(dump, void(std::string&)); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); - MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); - MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); @@ -50,12 +48,17 @@ public: MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode)); MOCK_METHOD6(drawLayers, status_t(const DisplaySettings&, const std::vector&, - const sp&, const bool, base::unique_fd&&, + const std::shared_ptr&, const bool, base::unique_fd&&, base::unique_fd*)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size)); + +protected: + // mock renderengine still needs to implement these, but callers should never need to call them. + void mapExternalTextureBuffer(const sp&, bool) {} + void unmapExternalTextureBuffer(const sp&) {} }; } // namespace mock diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index bb758780e1..2d61cf854b 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -21,9 +21,9 @@ #include #include #include +#include #include "android-base/macros.h" -#include "ui/GraphicTypes.h" namespace android { namespace renderengine { @@ -41,13 +41,18 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef() {} + LocalRef(AutoBackendTexture* texture) { setTexture(texture); } ~LocalRef() { // Destroying the texture is the same as setting it to null setTexture(nullptr); } + AutoBackendTexture* getTexture() const { return mTexture; } + + DISALLOW_COPY_AND_ASSIGN(LocalRef); + + private: // Sets the texture to locally ref-track. void setTexture(AutoBackendTexture* texture) { if (mTexture != nullptr) { @@ -59,12 +64,6 @@ public: mTexture->ref(); } } - - AutoBackendTexture* getTexture() const { return mTexture; } - - DISALLOW_COPY_AND_ASSIGN(LocalRef); - - private: AutoBackendTexture* mTexture = nullptr; }; diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 1db20c0be0..1c2b2fc3ca 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -46,7 +46,7 @@ constexpr auto kDestDataSpace = ui::Dataspace::SRGB; } // namespace static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { // Somewhat arbitrary dimensions, but on screen and slightly shorter, based // on actual use. FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30); @@ -73,7 +73,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin auto layers = std::vector{&layer}; // The identity matrix will generate the fast shader - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); // This matrix, which has different scales for x and y, will // generate the slower (more general case) version, which has variants for translucent @@ -86,13 +86,14 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin // clang-format on for (auto translucent : {false, true}) { layer.shadow.casterIsTranslucent = translucent; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer, sp srcBuffer) { + const std::shared_ptr& dstTexture, + const std::shared_ptr& srcTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -103,7 +104,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }, .source = PixelSource{.buffer = Buffer{ - .buffer = srcBuffer, + .buffer = srcTexture, .maxMasteringLuminance = 1000.f, .maxContentLuminance = 1000.f, }}, @@ -126,7 +127,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.source.buffer.isOpaque = isOpaque; for (auto alpha : {half(.23999f), half(1.0f)}) { layer.alpha = alpha; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -135,7 +136,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting } static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -143,11 +144,11 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting Geometry{ .boundaries = rect, }, - .alpha = 1, .source = PixelSource{ .solidColor = half3(0.1f, 0.2f, 0.3f), }, + .alpha = 1, }; auto layers = std::vector{&layer}; @@ -155,14 +156,14 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) { layer.geometry.roundedCornersRadius = roundedCornersRadius; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } } static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -176,7 +177,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings auto layers = std::vector{&layer}; for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -214,6 +215,9 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp dstBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "primeShaderCache_dst"); + + const auto dstTexture = std::make_shared(dstBuffer, *renderengine, + ExternalTexture::Usage::WRITEABLE); // This buffer will be the source for the call to drawImageLayers. Draw // something to it as a placeholder for what an app draws. We should draw // something, but the details are not important. Make use of the shadow layer drawing step @@ -222,11 +226,16 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src"); - drawSolidLayers(renderengine, display, dstBuffer); - drawShadowLayers(renderengine, display, srcBuffer); - drawBlurLayers(renderengine, display, dstBuffer); + const auto srcTexture = + std::make_shared(srcBuffer, *renderengine, + ExternalTexture::Usage::READABLE | + ExternalTexture::Usage::WRITEABLE); + + drawSolidLayers(renderengine, display, dstTexture); + drawShadowLayers(renderengine, display, srcTexture); + drawBlurLayers(renderengine, display, dstTexture); // The majority of shaders are related to sampling images. - drawImageLayers(renderengine, display, dstBuffer, srcBuffer); + drawImageLayers(renderengine, display, dstTexture, srcTexture); // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; @@ -234,12 +243,12 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp externalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usageExternal, "primeShaderCache_external"); + const auto externalTexture = + std::make_shared(externalBuffer, *renderengine, + ExternalTexture::Usage::READABLE); // TODO(b/184665179) doubles number of image shader compilations, but only somewhere // between 6 and 8 will occur in real uses. - drawImageLayers(renderengine, display, dstBuffer, externalBuffer); - renderengine->unbindExternalTextureBuffer(externalBuffer->getId()); - - renderengine->unbindExternalTextureBuffer(srcBuffer->getId()); + drawImageLayers(renderengine, display, dstTexture, externalTexture); const nsecs_t timeAfter = systemTime(); const float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 3b2c7e5f66..e781584a9b 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -329,8 +329,6 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL } SkiaGLRenderEngine::~SkiaGLRenderEngine() { - cleanFramebufferCache(); - std::lock_guard lock(mRenderingMutex); if (mBlurFilter) { delete mBlurFilter; @@ -484,7 +482,8 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { +void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffer, + bool isRenderable) { // Only run this if RE is running on its own thread. This way the access to GL // operations is guaranteed to be happening on the same thread. if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) { @@ -505,25 +504,41 @@ void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buf auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; std::lock_guard lock(mRenderingMutex); - auto iter = cache.find(buffer->getId()); - if (iter != cache.end()) { - ALOGV("Texture already exists in cache."); - } else { + mGraphicBufferExternalRefs[buffer->getId()]++; + + if (const auto& iter = cache.find(buffer->getId()); iter == cache.end()) { std::shared_ptr imageTextureRef = - std::make_shared(); - imageTextureRef->setTexture( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), false)); + std::make_shared( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), + isRenderable)); cache.insert({buffer->getId(), imageTextureRef}); } // restore the original state of the protected context if necessary useProtectedContext(protectedContextState); } -void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { +void SkiaGLRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { ATRACE_CALL(); std::lock_guard lock(mRenderingMutex); - mTextureCache.erase(bufferId); - mProtectedTextureCache.erase(bufferId); + if (const auto& iter = mGraphicBufferExternalRefs.find(buffer->getId()); + iter != mGraphicBufferExternalRefs.end()) { + if (iter->second == 0) { + ALOGW("Attempted to unmap GraphicBuffer from RenderEngine texture, but the " + "ref count was already zero!", + buffer->getId()); + mGraphicBufferExternalRefs.erase(buffer->getId()); + return; + } + + iter->second--; + + if (iter->second == 0) { + mTextureCache.erase(buffer->getId()); + mProtectedTextureCache.erase(buffer->getId()); + mGraphicBufferExternalRefs.erase(buffer->getId()); + } + } } sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, @@ -621,8 +636,8 @@ private: status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, - const bool useFramebufferCache, + const std::shared_ptr& buffer, + const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -645,32 +660,18 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer); + validateOutputBufferUsage(buffer->getBuffer()); auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext; auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; - AHardwareBuffer_Desc bufferDesc; - AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); - - std::shared_ptr surfaceTextureRef = nullptr; - if (useFramebufferCache) { - auto iter = cache.find(buffer->getId()); - if (iter != cache.end()) { - ALOGV("Cache hit!"); - ATRACE_NAME("Cache hit"); - surfaceTextureRef = iter->second; - } - } - if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) { - ATRACE_NAME("Cache miss"); - surfaceTextureRef = std::make_shared(); - surfaceTextureRef->setTexture( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true)); - if (useFramebufferCache) { - ALOGD("Adding to cache"); - cache.insert({buffer->getId(), surfaceTextureRef}); - } + std::shared_ptr surfaceTextureRef; + if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) { + surfaceTextureRef = it->second; + } else { + surfaceTextureRef = std::make_shared( + new AutoBackendTexture(grContext.get(), buffer->getBuffer()->toAHardwareBuffer(), + true)); } const ui::Dataspace dstDataspace = @@ -876,18 +877,22 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer); + validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; - auto iter = cache.find(item.buffer->getId()); - if (iter != cache.end()) { + + if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); + iter != cache.end()) { imageTextureRef = iter->second; } else { - imageTextureRef = std::make_shared(); - imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(), - item.buffer->toAHardwareBuffer(), - false)); - cache.insert({item.buffer->getId(), imageTextureRef}); + // If we didn't find the image in the cache, then create a local ref but don't cache + // it. If we're using skia, we're guaranteed to run on a dedicated GPU thread so if + // we didn't find anything in the cache then we intentionally did not cache this + // buffer's resources. + imageTextureRef = std::make_shared( + new AutoBackendTexture(grContext.get(), + item.buffer->getBuffer()->toAHardwareBuffer(), + false)); } sk_sp image = @@ -1200,15 +1205,6 @@ EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay dis return eglCreatePbufferSurface(display, placeholderConfig, attributes.data()); } -void SkiaGLRenderEngine::cleanFramebufferCache() { - // TODO(b/180767535) Remove this method and use b/180767535 instead, which would allow - // SF to control texture lifecycle more tightly rather than through custom hooks into RE. - std::lock_guard lock(mRenderingMutex); - mRuntimeEffects.clear(); - mProtectedTextureCache.clear(); - mTextureCache.clear(); -} - int SkiaGLRenderEngine::getContextPriority() { int value; eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value); @@ -1281,6 +1277,12 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "Skia's Wrapped Objects:\n"); gpuReporter.logOutput(result, true); + StringAppendF(&result, "RenderEngine tracked buffers: %zu\n", + mGraphicBufferExternalRefs.size()); + StringAppendF(&result, "Dumping buffer ids...\n"); + for (const auto& [id, refCounts] : mGraphicBufferExternalRefs) { + StringAppendF(&result, "- 0x%" PRIx64 " - %d refs \n", id, refCounts); + } StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n", mTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 8e77c16b40..e71c560a1f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -52,13 +53,12 @@ public: ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex); void primeCache() override; - void cacheExternalTextureBuffer(const sp& buffer) override; - void unbindExternalTextureBuffer(uint64_t bufferId) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; - void cleanFramebufferCache() override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; + void cleanFramebufferCache() override {} int getContextPriority() override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -72,6 +72,8 @@ protected: void dump(std::string& result) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; + void unmapExternalTextureBuffer(const sp& buffer) override; private: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); @@ -114,7 +116,9 @@ private: const PixelFormat mDefaultPixelFormat; const bool mUseColorManagement; - // Cache of GL textures that we'll store per GraphicBuffer ID + // Number of external holders of ExternalTexture references, per GraphicBuffer ID. + std::unordered_map mGraphicBufferExternalRefs GUARDED_BY(mRenderingMutex); + // Cache of GL textures that we'll store per GraphicBuffer ID, sliced by GPU context. std::unordered_map> mTextureCache GUARDED_BY(mRenderingMutex); std::unordered_map> diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 51ef088a25..308c5ffa9f 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -42,15 +42,12 @@ public: virtual void primeCache() override{}; virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; - virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; - virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; - virtual bool isProtected() const override { return false; } // mInProtectedContext; } virtual bool supportsProtectedContent() const override { return false; }; virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; }; virtual status_t drawLayers(const DisplaySettings& /*display*/, const std::vector& /*layers*/, - const sp& /*buffer*/, + const std::shared_ptr& /*buffer*/, const bool /*useFramebufferCache*/, base::unique_fd&& /*bufferFence*/, base::unique_fd* /*drawFence*/) override { @@ -60,6 +57,11 @@ public: virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} virtual int reportShadersCompiled() { return 0; } + +protected: + virtual void mapExternalTextureBuffer(const sp& /*buffer*/, + bool /*isRenderable*/) override; + virtual void unmapExternalTextureBuffer(const sp& /*buffer*/) override; }; } // namespace skia diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 7846156383..d63c88bc02 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -160,27 +161,42 @@ public: class RenderEngineTest : public ::testing::TestWithParam> { public: - static sp allocateDefaultBuffer() { - return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, - "output"); + std::shared_ptr allocateDefaultBuffer() { + return std::make_shared< + renderengine:: + ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, + DEFAULT_DISPLAY_HEIGHT, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "output"), + *mRE, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); } // Allocates a 1x1 buffer to fill with a solid color - static sp allocateSourceBuffer(uint32_t width, uint32_t height) { - return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_TEXTURE, - "input"); + std::shared_ptr allocateSourceBuffer(uint32_t width, + uint32_t height) { + return std::make_shared< + renderengine:: + ExternalTexture>(new GraphicBuffer(width, height, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE, + "input"), + *mRE, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); } RenderEngineTest() { 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()); - mBuffer = allocateDefaultBuffer(); } ~RenderEngineTest() { @@ -211,20 +227,21 @@ public: } uint8_t* pixels; - mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); file << "P6\n"; - file << mBuffer->getWidth() << "\n"; - file << mBuffer->getHeight() << "\n"; + file << mBuffer->getBuffer()->getWidth() << "\n"; + file << mBuffer->getBuffer()->getHeight() << "\n"; file << 255 << "\n"; - std::vector outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3); + std::vector outBuffer(mBuffer->getBuffer()->getWidth() * + mBuffer->getBuffer()->getHeight() * 3); auto outPtr = reinterpret_cast(outBuffer.data()); - for (int32_t j = 0; j < mBuffer->getHeight(); j++) { - const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4; - for (int32_t i = 0; i < mBuffer->getWidth(); i++) { + for (int32_t j = 0; j < mBuffer->getBuffer()->getHeight(); j++) { + const uint8_t* src = pixels + (mBuffer->getBuffer()->getStride() * j) * 4; + for (int32_t i = 0; i < mBuffer->getBuffer()->getWidth(); i++) { // Only copy R, G and B components outPtr[0] = src[0]; outPtr[1] = src[1]; @@ -235,7 +252,7 @@ public: } } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); - mBuffer->unlock(); + mBuffer->getBuffer()->unlock(); } void expectBufferColor(const Region& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -262,13 +279,13 @@ public: void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, std::function colorCompare) { uint8_t* pixels; - mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); int32_t maxFails = 10; int32_t fails = 0; for (int32_t j = 0; j < region.getHeight(); j++) { - const uint8_t* src = - pixels + (mBuffer->getStride() * (region.top + j) + region.left) * 4; + const uint8_t* src = pixels + + (mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4; for (int32_t i = 0; i < region.getWidth(); i++) { const uint8_t expected[4] = {r, g, b, a}; bool equal = colorCompare(src, expected); @@ -289,7 +306,7 @@ public: break; } } - mBuffer->unlock(); + mBuffer->getBuffer()->unlock(); } void expectAlpha(const Rect& rect, uint8_t a) { @@ -387,7 +404,6 @@ public: base::unique_fd fence; status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence); - mCurrentBuffer = mBuffer; int fd = fence.release(); if (fd >= 0) { @@ -397,7 +413,7 @@ public: ASSERT_EQ(NO_ERROR, status); if (layers.size() > 0 && mGLESRE != nullptr) { - ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); + ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); } } @@ -503,17 +519,11 @@ public: void initializeRenderEngine(); std::unique_ptr mRE; + std::shared_ptr mBuffer; // GLESRenderEngine for testing GLES-specific behavior. // Owened by mRE, but this is downcasted. renderengine::gl::GLESRenderEngine* mGLESRE = nullptr; - // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to - // be freed *after* RenderEngine is destroyed, so that the EGL image is - // destroyed first. - sp mCurrentBuffer; - - sp mBuffer; - std::vector mTexNames; }; @@ -530,6 +540,7 @@ void RenderEngineTest::initializeRenderEngine() { } else { mRE = renderEngineFactory->createRenderEngine(); } + mBuffer = allocateDefaultBuffer(); } struct ColorSourceVariant { @@ -566,18 +577,18 @@ template struct BufferSourceVariant { static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b, RenderEngineTest* fixture) { - sp buf = RenderEngineTest::allocateSourceBuffer(1, 1); + const auto buf = fixture->allocateSourceBuffer(1, 1); uint32_t texName; fixture->mRE->genTextures(1, &texName); fixture->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); - for (int32_t j = 0; j < buf->getHeight(); j++) { - uint8_t* iter = pixels + (buf->getStride() * j) * 4; - for (int32_t i = 0; i < buf->getWidth(); i++) { + for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) { + uint8_t* iter = pixels + (buf->getBuffer()->getStride() * j) * 4; + for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) { iter[0] = uint8_t(r * 255); iter[1] = uint8_t(g * 255); iter[2] = uint8_t(b * 255); @@ -586,7 +597,7 @@ struct BufferSourceVariant { } } - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1012,14 +1023,14 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; // Here will allocate a checker board texture, but transform texture // coordinates so that only the upper left is applied. - sp buf = allocateSourceBuffer(2, 2); + const auto buf = allocateSourceBuffer(2, 2); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); // Red top left, Green top right, Blue bottom left, Black bottom right pixels[0] = 255; pixels[1] = 0; @@ -1033,7 +1044,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { pixels[9] = 0; pixels[10] = 255; pixels[11] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1061,19 +1072,19 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - sp buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1100,19 +1111,19 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - sp buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1233,8 +1244,7 @@ TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) { } TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { - const auto& renderEngineFactory = GetParam(); - mRE = renderEngineFactory->createRenderEngine(); + initializeRenderEngine(); renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1295,7 +1305,6 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputFence) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr); - mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1323,9 +1332,8 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr); - mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); - ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); + ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1574,98 +1582,6 @@ TEST_P(RenderEngineTest, drawLayers_clearRegion) { clearRegion(); } -TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - renderengine::DisplaySettings settings; - settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - settings.physicalDisplay = fullscreenRect(); - settings.clip = fullscreenRect(); - - std::vector layers; - - renderengine::LayerSettings layer; - layer.geometry.boundaries = fullscreenRect().toFloatRect(); - BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - - layers.push_back(&layer); - invokeDraw(settings, layers); - uint64_t bufferId = layer.source.buffer.buffer->getId(); - EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); - std::shared_ptr barrier = - mGLESRE->unbindExternalTextureBufferForTesting(bufferId); - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); - EXPECT_EQ(NO_ERROR, barrier->result); -} - -TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - std::shared_ptr barrier = - mGLESRE->cacheExternalTextureBufferForTesting(nullptr); - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_TRUE(barrier->isOpen); - EXPECT_EQ(BAD_VALUE, barrier->result); -} - -TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - sp buf = allocateSourceBuffer(1, 1); - uint64_t bufferId = buf->getId(); - std::shared_ptr barrier = - mGLESRE->cacheExternalTextureBufferForTesting(buf); - { - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_EQ(NO_ERROR, barrier->result); - } - EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); - barrier = mGLESRE->unbindExternalTextureBufferForTesting(bufferId); - { - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_EQ(NO_ERROR, barrier->result); - } - EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); -} - TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) { initializeRenderEngine(); @@ -1858,7 +1774,7 @@ TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory sync_wait(fd, -1); } - uint64_t bufferId = layer.source.buffer.buffer->getId(); + uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId(); uint32_t texName = layer.source.buffer.textureName; EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName)); @@ -1966,16 +1882,16 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { // The next layer will overwrite redLayer with a GraphicBuffer that is green // applied with a translucent alpha. - auto buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); { uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 0; pixels[1] = 255; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); } const renderengine::LayerSettings greenLayer{ diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index b093e88d4f..e3917cce09 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -162,15 +162,18 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; std::vector layers; - sp buffer = new GraphicBuffer(); + std::shared_ptr buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); base::unique_fd bufferFence; base::unique_fd drawFence; EXPECT_CALL(*mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings&, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { return NO_ERROR; }); + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 194c7da1c7..c9f6296b49 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -157,27 +157,28 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { resultFuture.wait(); } -void RenderEngineThreaded::cacheExternalTextureBuffer(const sp& buffer) { +void RenderEngineThreaded::mapExternalTextureBuffer(const sp& buffer, + bool isRenderable) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::cacheExternalTextureBuffer"); - instance.cacheExternalTextureBuffer(buffer); + ATRACE_NAME("REThreaded::mapExternalTextureBuffer"); + instance.mapExternalTextureBuffer(buffer, isRenderable); }); } mCondition.notify_one(); } -void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { +void RenderEngineThreaded::unmapExternalTextureBuffer(const sp& buffer) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::unbindExternalTextureBuffer"); - instance.unbindExternalTextureBuffer(bufferId); + ATRACE_NAME("REThreaded::unmapExternalTextureBuffer"); + instance.unmapExternalTextureBuffer(buffer); }); } mCondition.notify_one(); @@ -239,7 +240,7 @@ bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, + const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 61ae9b8cf8..eb6098ed8d 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -48,8 +48,6 @@ public: void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; - void cacheExternalTextureBuffer(const sp& buffer) override; - void unbindExternalTextureBuffer(uint64_t bufferId) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -60,14 +58,19 @@ public: status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; void cleanFramebufferCache() override; int getContextPriority() override; bool supportsBackgroundBlur() override; void onPrimaryDisplaySizeChanged(ui::Size size) override; +protected: + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; + void unmapExternalTextureBuffer(const sp& buffer) override; + private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index be9bce0795..13ac7c3563 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -188,7 +188,7 @@ std::optional BufferLayer::prepareCli const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const bool bufferCanBeUsedAsHwTexture = - mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; + mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; compositionengine::LayerFE::LayerSettings& layer = *result; if (blackOutLayer || !bufferCanBeUsedAsHwTexture) { ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable", @@ -213,7 +213,7 @@ std::optional BufferLayer::prepareCli ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel : defaultMaxContentLuminance; layer.frameNumber = mCurrentFrameNumber; - layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0; + layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0; const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering(); @@ -314,7 +314,7 @@ void BufferLayer::preparePerFrameCompositionState() { : Hwc2::IComposerClient::Composition::DEVICE; } - compositionState->buffer = mBufferInfo.mBuffer; + compositionState->buffer = mBufferInfo.mBuffer->getBuffer(); compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mBufferInfo.mBufferSlot; @@ -442,7 +442,7 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, void BufferLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = - !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format; mBufferInfo.mFrameLatencyNeeded = true; } @@ -544,10 +544,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, } 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)) { + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); + if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) || + bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) { recomputeVisibleRegions = true; } } @@ -612,8 +612,8 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - const sp& buffer(mBufferInfo.mBuffer); - return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); + return (mBufferInfo.mBuffer != nullptr) && + (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED); } // h/w composer set-up @@ -727,8 +727,8 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect::INVALID_RECT; } - uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -759,8 +759,8 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return parentBounds; } - uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -802,7 +802,7 @@ Rect BufferLayer::getBufferCrop() const { return mBufferInfo.mCrop; } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mBufferInfo.mBuffer->getBounds(); + return mBufferInfo.mBuffer->getBuffer()->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -847,12 +847,14 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { } sp BufferLayer::getBuffer() const { - return mBufferInfo.mBuffer; + return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr; } void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { - GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, - mBufferInfo.mTransform, filteringEnabled); + GLConsumer::computeTransformMatrix(outMatrix, + mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() + : nullptr, + mBufferInfo.mCrop, mBufferInfo.mTransform, filteringEnabled); } void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b8d3f12322..855324710e 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -134,7 +134,7 @@ protected: PixelFormat mPixelFormat{PIXEL_FORMAT_NONE}; bool mTransformToDisplayInverse{false}; - sp mBuffer; + std::shared_ptr mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; bool mFrameLatencyNeeded{false}; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 69d2d11a4d..96b22478ab 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -167,7 +166,7 @@ void BufferLayerConsumer::setReleaseFence(const sp& fence) { } auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer - : mCurrentTextureBuffer->graphicBuffer(); + : mCurrentTextureBuffer->getBuffer(); auto err = addReleaseFence(slot, buffer, fence); if (err != OK) { BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); @@ -206,9 +205,11 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres // before, so we need to clean up old references. if (item->mGraphicBuffer != nullptr) { std::lock_guard lock(mImagesMutex); - if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr || - mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) { - mImages[item->mSlot] = std::make_shared(item->mGraphicBuffer, mRE); + if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr || + mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) { + mImages[item->mSlot] = std::make_shared< + renderengine::ExternalTexture>(item->mGraphicBuffer, mRE, + renderengine::ExternalTexture::Usage::READABLE); } } @@ -222,8 +223,8 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, int slot = item.mSlot; BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, - (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr) - ? mCurrentTextureBuffer->graphicBuffer()->handle + (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr) + ? mCurrentTextureBuffer->getBuffer()->handle : 0, slot, mSlots[slot].mGraphicBuffer->handle); @@ -231,7 +232,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same. - std::shared_ptr nextTextureBuffer; + std::shared_ptr nextTextureBuffer; { std::lock_guard lock(mImagesMutex); nextTextureBuffer = mImages[slot]; @@ -241,7 +242,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (pendingRelease == nullptr) { status_t status = - releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer()); + releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer()); if (status < NO_ERROR) { BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); @@ -250,7 +251,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } } else { pendingRelease->currentTexture = mCurrentTexture; - pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer(); + pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer(); pendingRelease->isPending = true; } } @@ -301,14 +302,14 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) { void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { BLC_LOGV("computeCurrentTransformMatrixLocked"); - if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->graphicBuffer() == nullptr) { + if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->getBuffer() == nullptr) { BLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureBuffer is nullptr"); } GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer == nullptr ? nullptr - : mCurrentTextureBuffer->graphicBuffer(), + : mCurrentTextureBuffer->getBuffer(), getCurrentCropLocked(), mCurrentTransform, mFilteringEnabled); } @@ -360,7 +361,8 @@ int BufferLayerConsumer::getCurrentApi() const { return mCurrentApi; } -sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* outFence) const { +std::shared_ptr BufferLayerConsumer::getCurrentBuffer( + int* outSlot, sp* outFence) const { Mutex::Autolock lock(mMutex); if (outSlot != nullptr) { @@ -371,7 +373,7 @@ sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* *outFence = mCurrentFence; } - return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer(); + return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer; } Rect BufferLayerConsumer::getCurrentCrop() const { @@ -456,10 +458,12 @@ void BufferLayerConsumer::onSidebandStreamChanged() { void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) { std::lock_guard lock(mImagesMutex); - const std::shared_ptr& oldImage = mImages[item.mSlot]; - if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr || - oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) { - mImages[item.mSlot] = std::make_shared(item.mGraphicBuffer, mRE); + const std::shared_ptr& oldImage = mImages[item.mSlot]; + if (oldImage == nullptr || oldImage->getBuffer() == nullptr || + oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) { + mImages[item.mSlot] = std::make_shared< + renderengine::ExternalTexture>(item.mGraphicBuffer, mRE, + renderengine::ExternalTexture::Usage::READABLE); } } } @@ -499,22 +503,6 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } - -BufferLayerConsumer::Image::Image(const sp& graphicBuffer, - renderengine::RenderEngine& engine) - : mGraphicBuffer(graphicBuffer), mRE(engine) { - if (graphicBuffer != nullptr && (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED)) { - return; - } - mRE.cacheExternalTextureBuffer(mGraphicBuffer); -} - -BufferLayerConsumer::Image::~Image() { - if (mGraphicBuffer != nullptr) { - ALOGV("Destroying buffer: %" PRId64, mGraphicBuffer->getId()); - mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId()); - } -} }; // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index dd39214aff..9ed80b46bd 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -21,12 +21,11 @@ #include #include #include - +#include #include #include #include #include - #include #include #include @@ -39,7 +38,6 @@ class String8; namespace renderengine { class RenderEngine; -class Image; } // namespace renderengine /* @@ -153,7 +151,8 @@ public: // When outSlot is not nullptr, the current buffer slot index is also // returned. Simiarly, when outFence is not nullptr, the current output // fence is returned. - sp getCurrentBuffer(int* outSlot = nullptr, sp* outFence = nullptr) const; + std::shared_ptr getCurrentBuffer( + int* outSlot = nullptr, sp* outFence = nullptr) const; // getCurrentCrop returns the cropping rectangle of the current buffer. Rect getCurrentCrop() const; @@ -258,7 +257,7 @@ private: // mCurrentTextureBuffer is the buffer containing the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. - std::shared_ptr mCurrentTextureBuffer; + std::shared_ptr mCurrentTextureBuffer; // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set each time updateTexImage is called. @@ -337,7 +336,8 @@ private: int mCurrentTexture; // Shadow buffer cache for cleaning up renderengine references. - std::shared_ptr mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); + std::shared_ptr + mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); // Separate mutex guarding the shadow buffer cache. // mImagesMutex can be manipulated with binder threads (e.g. onBuffersAllocated) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ed826a0100..c533969a5c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -71,14 +71,8 @@ BufferStateLayer::~BufferStateLayer() { // 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. - auto& engine(mFlinger->getRenderEngine()); - const uint64_t bufferId = mBufferInfo.mBuffer->getId(); - engine.unbindExternalTextureBuffer(bufferId); - callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, - mBufferInfo.mFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence); } } @@ -363,8 +357,9 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, - nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, +bool BufferStateLayer::setBuffer(const std::shared_ptr& buffer, + const sp& acquireFence, nsecs_t postTime, + nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& releaseBufferListener) { @@ -372,12 +367,14 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spgetBuffer() != mDrawingState.buffer->getBuffer()) { // If mCurrentState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mCurrentState.releaseBufferListener, mCurrentState.buffer, + callReleaseBufferCallback(mCurrentState.releaseBufferListener, + mCurrentState.buffer->getBuffer(), mCurrentState.acquireFence); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { @@ -415,8 +412,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spgetId(); + if (buffer && dequeueTime && *dequeueTime != 0) { + const uint64_t bufferId = buffer->getBuffer()->getId(); mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime, FrameTracer::FrameEvent::DEQUEUE); @@ -424,8 +421,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spwidth; - mCurrentState.height = mCurrentState.buffer->height; + mCurrentState.width = mCurrentState.buffer->getBuffer()->getWidth(); + mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight(); return true; } @@ -674,7 +671,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const int32_t layerId = getSequence(); - const uint64_t bufferId = mDrawingState.buffer->getId(); + const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId(); const uint64_t frameNumber = mDrawingState.frameNumber; const auto acquireFence = std::make_shared(mDrawingState.acquireFence); mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence); @@ -708,7 +705,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (s.buffer != mBufferInfo.mBuffer) { + if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { decrementPendingBufferCount(); } @@ -827,13 +824,13 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBounds(); + return s.buffer->getBuffer()->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(); + uint32_t bufferWidth = s.buffer->getBuffer()->getWidth(); + uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); if (bufferHeight <= std::numeric_limits::max() && bufferWidth <= std::numeric_limits::max()) { crop.right = std::min(crop.right, static_cast(bufferWidth)); @@ -841,7 +838,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer - return s.buffer->getBounds(); + return s.buffer->getBuffer()->getBounds(); } return crop; } @@ -863,8 +860,8 @@ bool BufferStateLayer::bufferNeedsFiltering() const { return false; } - uint32_t bufferWidth = s.buffer->width; - uint32_t bufferHeight = s.buffer->height; + uint32_t bufferWidth = s.buffer->getBuffer()->width; + uint32_t bufferHeight = s.buffer->getBuffer()->height; // Undo any transformations on the buffer and return the result. if (s.bufferTransform & ui::Transform::ROT_90) { @@ -891,14 +888,16 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) { ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } -void BufferStateLayer::bufferMayChange(sp& newBuffer) { - if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && - newBuffer != mDrawingState.buffer) { +void BufferStateLayer::bufferMayChange(const sp& newBuffer) { + if (mDrawingState.buffer != nullptr && + (!mBufferInfo.mBuffer || + mDrawingState.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) && + newBuffer != mDrawingState.buffer->getBuffer()) { // If we are about to update mDrawingState.buffer but it has not yet latched // then we will drop a buffer and should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, - mDrawingState.acquireFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence); decrementPendingBufferCount(); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 8ce3e1f55b..a69d07f634 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,9 +66,9 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber, + bool setBuffer(const std::shared_ptr& buffer, + const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, + bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& transactionListener) override; bool setAcquireFence(const sp& fence) override; @@ -108,7 +108,7 @@ public: // See mPendingBufferTransactions void decrementPendingBufferCount(); - void bufferMayChange(sp& newBuffer) override; + void bufferMayChange(const sp& newBuffer) override; std::atomic* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index 44b33ef43d..f310738423 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -102,7 +102,12 @@ bool ClientCache::add(const client_cache_t& cacheId, const sp& bu return false; } - processBuffers[id].buffer = buffer; + LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, + "Attempted to build the ClientCache before a RenderEngine instance was " + "ready!"); + processBuffers[id].buffer = std::make_shared< + renderengine::ExternalTexture>(buffer, *mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE); return true; } @@ -132,7 +137,7 @@ void ClientCache::erase(const client_cache_t& cacheId) { } } -sp ClientCache::get(const client_cache_t& cacheId) { +std::shared_ptr ClientCache::get(const client_cache_t& cacheId) { std::lock_guard lock(mMutex); ClientCacheBuffer* buf = nullptr; @@ -213,8 +218,8 @@ void ClientCache::dump(std::string& result) { auto &buffers = i.second.second; for (auto& [id, clientCacheBuffer] : buffers) { StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id, - (int)clientCacheBuffer.buffer->getWidth(), - (int)clientCacheBuffer.buffer->getHeight()); + (int)clientCacheBuffer.buffer->getBuffer()->getWidth(), + (int)clientCacheBuffer.buffer->getBuffer()->getHeight()); } } } diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h index 0d597c8e05..a9b8177d70 100644 --- a/services/surfaceflinger/ClientCache.h +++ b/services/surfaceflinger/ClientCache.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,11 @@ public: bool add(const client_cache_t& cacheId, const sp& buffer); void erase(const client_cache_t& cacheId); - sp get(const client_cache_t& cacheId); + std::shared_ptr get(const client_cache_t& cacheId); + + // Always called immediately after setup. Will be set to non-null, and then should never be + // called again. + void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; } void removeProcess(const wp& processToken); @@ -59,7 +64,7 @@ private: std::mutex mMutex; struct ClientCacheBuffer { - sp buffer; + std::shared_ptr buffer; std::set> recipients; }; std::map /*caching process*/, @@ -73,6 +78,7 @@ private: }; sp mDeathRecipient; + renderengine::RenderEngine* mRenderEngine = nullptr; bool getBuffer(const client_cache_t& cacheId, ClientCacheBuffer** outClientCacheBuffer) REQUIRES(mMutex); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index f680460242..daee83bd2c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -16,15 +16,16 @@ #pragma once -#include -#include - +#include #include #include #include #include #include +#include +#include + namespace android { class GraphicBuffer; @@ -80,7 +81,8 @@ public: virtual void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) = 0; // Allocates a buffer as scratch space for GPU composition - virtual sp dequeueBuffer(base::unique_fd* bufferFence) = 0; + virtual std::shared_ptr dequeueBuffer( + base::unique_fd* bufferFence) = 0; // Queues the drawn buffer for consumption by HWC. readyFence is the fence // which will fire when the buffer is ready for consumption. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h index a1230b3c4d..a8d372c562 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h @@ -45,6 +45,8 @@ struct RenderSurfaceCreationArgs { // The DisplaySurface for this surface sp displaySurface; + + size_t maxTextureCacheSize; }; /** @@ -81,6 +83,11 @@ public: return *this; } + RenderSurfaceCreationArgsBuilder& setMaxTextureCacheSize(size_t maxTextureCacheSize) { + mArgs.maxTextureCacheSize = maxTextureCacheSize; + return *this; + } + private: RenderSurfaceCreationArgs mArgs; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 48a54d6c66..c61ec5991b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ struct OutputLayerCompositionState { // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { - sp buffer = nullptr; + std::shared_ptr buffer = nullptr; sp acquireFence = nullptr; Rect displayFrame = {}; ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index 5127a6f314..a8a538003e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -16,12 +16,16 @@ #pragma once -#include - #include #include #include +#include +#include + +#include "renderengine/ExternalTexture.h" +#include "renderengine/RenderEngine.h" + struct ANativeWindow; namespace android { @@ -54,7 +58,8 @@ public: void setProtected(bool useProtected) override; status_t beginFrame(bool mustRecompose) override; void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override; - sp dequeueBuffer(base::unique_fd* bufferFence) override; + std::shared_ptr dequeueBuffer( + base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; @@ -66,7 +71,7 @@ public: // Testing void setPageFlipCountForTest(std::uint32_t); void setSizeForTest(const ui::Size&); - sp& mutableGraphicBufferForTest(); + std::shared_ptr& mutableTextureForTest(); base::unique_fd& mutableBufferReadyForTest(); private: @@ -75,10 +80,13 @@ private: // ANativeWindow being rendered into const sp mNativeWindow; - // Current buffer being rendered into - sp mGraphicBuffer; + + std::vector> mTextureCache; + // Current texture being rendered into + std::shared_ptr mTexture; const sp mDisplaySurface; ui::Size mSize; + const size_t mMaxTextureCacheSize; bool mProtected{false}; std::uint32_t mPageFlipCount{0}; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index c5d03a7218..53f4a30fb8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -66,7 +66,7 @@ public: const Rect& getBounds() const { return mBounds; } const Region& getVisibleRegion() const { return mVisibleRegion; } size_t getAge() const { return mAge; } - const sp& getBuffer() const { return mTexture.getBuffer(); } + const std::shared_ptr& getBuffer() const { return mTexture; } const sp& getDrawFence() const { return mDrawFence; } const ProjectionSpace& getOutputSpace() const { return mOutputSpace; } ui::Dataspace getOutputDataspace() const { return mOutputDataspace; } @@ -87,7 +87,7 @@ public: void setLastUpdate(std::chrono::steady_clock::time_point now) { mLastUpdate = now; } void append(const CachedSet& other) { - mTexture.setBuffer(nullptr, nullptr); + mTexture = nullptr; mOutputDataspace = ui::Dataspace::UNKNOWN; mDrawFence = nullptr; @@ -115,31 +115,7 @@ private: Region mVisibleRegion; size_t mAge = 0; - class Texture { - public: - ~Texture() { setBuffer(nullptr, nullptr); } - - void setBuffer(const sp& buffer, renderengine::RenderEngine* re) { - if (mRE && mBuffer) { - mRE->unbindExternalTextureBuffer(mBuffer->getId()); - } - - mBuffer = buffer; - mRE = re; - - if (mRE && mBuffer) { - mRE->cacheExternalTextureBuffer(mBuffer); - } - } - - const sp& getBuffer() const { return mBuffer; } - - private: - sp mBuffer = nullptr; - renderengine::RenderEngine* mRE = nullptr; - }; - - Texture mTexture; + std::shared_ptr mTexture; sp mDrawFence; ProjectionSpace mOutputSpace; ui::Dataspace mOutputDataspace; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index a0cae6fcbb..fe858c2817 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -39,7 +39,7 @@ public: MOCK_METHOD1(setBufferPixelFormat, void(ui::PixelFormat)); MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); MOCK_METHOD2(prepareFrame, void(bool, bool)); - MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); + MOCK_METHOD1(dequeueBuffer, std::shared_ptr(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd)); MOCK_METHOD0(onPresentDisplayCompleted, void()); MOCK_METHOD0(flip, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 3ac5433457..3468b204fc 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,8 +14,7 @@ * limitations under the License. */ -#include - +#include #include #include #include @@ -29,7 +28,9 @@ #include #include -#include +#include + +#include "renderengine/ExternalTexture.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -715,11 +716,11 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr bool skipLayer = false; if (layer->getState().overrideInfo.buffer != nullptr) { if (previousOverride != nullptr && - layer->getState().overrideInfo.buffer == previousOverride) { + layer->getState().overrideInfo.buffer->getBuffer() == previousOverride) { ALOGV("Skipping redundant buffer"); skipLayer = true; } - previousOverride = layer->getState().overrideInfo.buffer; + previousOverride = layer->getState().overrideInfo.buffer->getBuffer(); } const bool includeGeometry = refreshArgs.updatingGeometryThisFrame; @@ -978,14 +979,15 @@ std::optional Output::composeSurfaces( } base::unique_fd fd; - sp buf; + + std::shared_ptr tex; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { - buf = mRenderSurface->dequeueBuffer(&fd); - if (buf == nullptr) { + tex = mRenderSurface->dequeueBuffer(&fd); + if (tex == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); @@ -1030,13 +1032,14 @@ std::optional Output::composeSurfaces( // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { - if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay, + if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), + clientCompositionDisplay, clientCompositionLayers)) { outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return readyFence; } - mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay, + mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1069,12 +1072,12 @@ std::optional Output::composeSurfaces( // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerStackInternal; status_t status = - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf, + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, useFramebufferCache, std::move(fd), &readyFence); if (status != NO_ERROR && mClientCompositionRequestCache) { // If rendering was not successful, remove the request from the cache. - mClientCompositionRequestCache->remove(buf->getId()); + mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); } auto& timeStats = getCompositionEngine().getTimeStats(); @@ -1151,9 +1154,9 @@ std::vector Output::generateClientCompositionRequests( std::vector results; if (layer->getState().overrideInfo.buffer != nullptr) { - if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) { + if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) { results = layer->getOverrideCompositionList(); - previousOverrideBuffer = layer->getState().overrideInfo.buffer; + previousOverrideBuffer = layer->getState().overrideInfo.buffer->getBuffer(); ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); } else { ALOGV("Skipping redundant override buffer for [%s] in RE", diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index f640f85bca..9ca8914deb 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -537,7 +537,7 @@ void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, sp buffer = outputIndependentState.buffer; sp acquireFence = outputIndependentState.acquireFence; if (getState().overrideInfo.buffer != nullptr) { - buffer = getState().overrideInfo.buffer; + buffer = getState().overrideInfo.buffer->getBuffer(); acquireFence = getState().overrideInfo.acquireFence; } @@ -699,7 +699,7 @@ std::vector OutputLayer::getOverrideCompositionList() co settings.geometry = renderengine::Geometry{ .boundaries = boundaries.toFloatRect(), }; - settings.bufferId = getState().overrideInfo.buffer->getId(); + settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId(); settings.source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = getState().overrideInfo.buffer, diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 3bef77dde1..ef50870615 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -25,8 +25,8 @@ #include #include #include - #include +#include #include #include #include @@ -63,7 +63,8 @@ RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display mDisplay(display), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), - mSize(args.displayWidth, args.displayHeight) { + mSize(args.displayWidth, args.displayHeight), + mMaxTextureCacheSize(args.maxTextureCacheSize) { LOG_ALWAYS_FATAL_IF(!mNativeWindow); } @@ -146,7 +147,8 @@ void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComp } } -sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { +std::shared_ptr RenderSurface::dequeueBuffer( + base::unique_fd* bufferFence) { ATRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; @@ -158,16 +160,41 @@ sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { mDisplay.getName().c_str(), result); // Return fast here as we can't do much more - any rendering we do // now will just be wrong. - return mGraphicBuffer; + return mTexture; + } + + ALOGW_IF(mTexture != nullptr, "Clobbering a non-null pointer to a buffer [%p].", + mTexture->getBuffer()->getNativeBuffer()->handle); + + sp newBuffer = GraphicBuffer::from(buffer); + + std::shared_ptr texture; + + for (auto it = mTextureCache.begin(); it != mTextureCache.end(); it++) { + const auto& cachedTexture = *it; + if (cachedTexture->getBuffer()->getId() == newBuffer->getId()) { + texture = cachedTexture; + mTextureCache.erase(it); + break; + } } - ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", - mGraphicBuffer->getNativeBuffer()->handle); - mGraphicBuffer = GraphicBuffer::from(buffer); + if (texture) { + mTexture = texture; + } else { + mTexture = std::make_shared< + renderengine::ExternalTexture>(GraphicBuffer::from(buffer), + mCompositionEngine.getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); + } + mTextureCache.push_back(mTexture); + if (mTextureCache.size() > mMaxTextureCacheSize) { + mTextureCache.erase(mTextureCache.begin()); + } *bufferFence = base::unique_fd(fd); - return mGraphicBuffer; + return mTexture; } void RenderSurface::queueBuffer(base::unique_fd readyFence) { @@ -177,24 +204,24 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { // hasFlipClientTargetRequest could return true even if we haven't // dequeued a buffer before. Try dequeueing one if we don't have a // buffer ready. - if (mGraphicBuffer == nullptr) { + if (mTexture == nullptr) { ALOGI("Attempting to queue a client composited buffer without one " "previously dequeued for display [%s]. Attempting to dequeue " "a scratch buffer now", mDisplay.getName().c_str()); - // We shouldn't deadlock here, since mGraphicBuffer == nullptr only + // We shouldn't deadlock here, since mTexture == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. base::unique_fd unused; dequeueBuffer(&unused); } - if (mGraphicBuffer == nullptr) { + if (mTexture == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { - status_t result = - mNativeWindow->queueBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), dup(readyFence)); + status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), + mTexture->getBuffer()->getNativeBuffer(), + dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); @@ -204,11 +231,12 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), dup(readyFence)); + mTexture->getBuffer()->getNativeBuffer(), + dup(readyFence)); } } - mGraphicBuffer = nullptr; + mTexture = nullptr; } } @@ -256,8 +284,8 @@ void RenderSurface::setSizeForTest(const ui::Size& size) { mSize = size; } -sp& RenderSurface::mutableGraphicBufferForTest() { - return mGraphicBuffer; +std::shared_ptr& RenderSurface::mutableTextureForTest() { + return mTexture; } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index dcb75556e3..53557bbb9f 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -130,7 +130,7 @@ bool CachedSet::hasBufferUpdate() const { } bool CachedSet::hasReadyBuffer() const { - return mTexture.getBuffer() != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; + return mTexture != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; } std::vector CachedSet::decompose() const { @@ -217,21 +217,27 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, sp buffer = new GraphicBuffer(static_cast(mBounds.getWidth()), static_cast(mBounds.getHeight()), HAL_PIXEL_FORMAT_RGBA_8888, 1, usageFlags); + const auto texture = std::make_shared< + renderengine::ExternalTexture>(buffer, renderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); LOG_ALWAYS_FATAL_IF(buffer->initCheck() != OK); base::unique_fd drawFence; - status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, buffer, false, - base::unique_fd(), &drawFence); + status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, mTexture, + false, base::unique_fd(), &drawFence); if (result == NO_ERROR) { - mTexture.setBuffer(buffer, &renderEngine); mDrawFence = new Fence(drawFence.release()); mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(), outputState.framebufferSpace.bounds.getHeight()), mBounds); + mTexture = std::move(texture); mOutputSpace.orientation = outputState.framebufferSpace.orientation; mOutputDataspace = outputDataspace; mOrientation = orientation; + } else { + mTexture = nullptr; } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index ad7555730d..3a2534b847 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -111,7 +111,12 @@ void Planner::reportFinalPlan( const GraphicBuffer* currentOverrideBuffer = nullptr; bool hasSkippedLayers = false; for (auto layer : layers) { - const GraphicBuffer* overrideBuffer = layer->getState().overrideInfo.buffer.get(); + if (!layer->getState().overrideInfo.buffer) { + continue; + } + + const GraphicBuffer* overrideBuffer = + layer->getState().overrideInfo.buffer->getBuffer().get(); if (overrideBuffer != nullptr && overrideBuffer == currentOverrideBuffer) { // Skip this layer since it is part of a previous cached set hasSkippedLayers = true; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 8a4d161289..4c3f4940cc 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -26,6 +26,7 @@ #include "MockHWC2.h" #include "MockHWComposer.h" #include "RegionMatcher.h" +#include "renderengine/mock/RenderEngine.h" namespace android::compositionengine { namespace { @@ -715,7 +716,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const HdrMetadata kHdrMetadata; static native_handle_t* kSidebandStreamHandle; static const sp kBuffer; - static const sp kOverrideBuffer; + std::shared_ptr kOverrideBuffer; static const sp kFence; static const sp kOverrideFence; static const std::string kLayerGenericMetadata1Key; @@ -724,6 +725,11 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const std::vector kLayerGenericMetadata2Value; OutputLayerWriteStateToHWCTest() { + kOverrideBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage:: + WRITEABLE); auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); @@ -839,6 +845,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { std::shared_ptr mHwcLayer{std::make_shared>()}; StrictMock mDisplayColorProfile; + renderengine::mock::RenderEngine mRenderEngine; }; const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, @@ -858,7 +865,6 @@ const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattena native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle = reinterpret_cast(1031); const sp OutputLayerWriteStateToHWCTest::kBuffer; -const sp OutputLayerWriteStateToHWCTest::kOverrideBuffer = new GraphicBuffer(); const sp OutputLayerWriteStateToHWCTest::kFence; const sp OutputLayerWriteStateToHWCTest::kOverrideFence = new Fence(); const std::string OutputLayerWriteStateToHWCTest::kLayerGenericMetadata1Key = @@ -1023,7 +1029,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { kOverrideBufferTransform, kOverrideBlendMode, kOverrideAlpha); expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion, kOverrideSurfaceDamage); - expectSetHdrMetadataAndBufferCalls(kOverrideBuffer, kOverrideFence); + expectSetHdrMetadataAndBufferCalls(kOverrideBuffer->getBuffer(), kOverrideFence); expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 5f0b0eea15..e80100cc6e 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#include - #include #include #include @@ -31,9 +29,12 @@ #include #include +#include + #include "CallOrderStateMachineHelper.h" #include "MockHWC2.h" #include "RegionMatcher.h" +#include "renderengine/ExternalTexture.h" namespace android::compositionengine { namespace { @@ -2960,7 +2961,10 @@ struct OutputComposeSurfacesTest : public testing::Test { mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); mock::RenderSurface* mRenderSurface = new StrictMock(); StrictMock mOutput; - sp mOutputBuffer = new GraphicBuffer(); + std::shared_ptr mOutputBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); std::optional mReadyFence; }; @@ -3173,7 +3177,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); - sp otherOutputBuffer = new GraphicBuffer(); + const auto otherOutputBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 5ef5d7b5cb..9aeb290eb5 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -15,6 +15,8 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues +#include "renderengine/ExternalTexture.h" +#include "ui/GraphicBuffer.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra" @@ -239,9 +241,9 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); base::unique_fd fence; - EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get()); + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence)->getBuffer().get()); - EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest()->getBuffer().get()); } /* @@ -249,8 +251,11 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { */ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; @@ -261,43 +266,45 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; state.flipClientTarget = false; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; state.flipClientTarget = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) { @@ -317,27 +324,28 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferY mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(INVALID_OPERATION)); EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true)); - EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index f01fe27b38..283c69270f 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -305,8 +305,8 @@ TEST_F(CachedSetTest, render) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector& layers, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> size_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> size_t { EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), @@ -321,7 +321,6 @@ TEST_F(CachedSetTest, render) { EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); - EXPECT_CALL(mRenderEngine, cacheExternalTextureBuffer(_)); cachedSet.render(mRenderEngine, mOutputState); expectReadyBuffer(cachedSet); @@ -331,7 +330,6 @@ TEST_F(CachedSetTest, render) { cachedSet.getOutputSpace().bounds); // Now check that appending a new cached set properly cleans up RenderEngine resources. - EXPECT_CALL(mRenderEngine, unbindExternalTextureBuffer(_)); CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index b7b2cc691b..8692ee60dc 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,11 +70,13 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( - compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth( - args.nativeWindow.get()), - ANativeWindow_getHeight( - args.nativeWindow.get()), - args.nativeWindow, args.displaySurface}); + compositionengine:: + RenderSurfaceCreationArgs{ANativeWindow_getWidth(args.nativeWindow.get()), + ANativeWindow_getHeight(args.nativeWindow.get()), + args.nativeWindow, args.displaySurface, + static_cast( + SurfaceFlinger:: + maxFrameBufferAcquiredBuffers)}); if (!mFlinger->mDisableClientCompositionCache && SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 829b91676b..b12e3fb626 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1050,7 +1050,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { } // Allow BufferStateLayer to release any unlatched buffers in drawing state. - bufferMayChange(c.buffer); + bufferMayChange(c.buffer->getBuffer()); // Commit the transaction commitTransaction(c); @@ -1062,7 +1062,11 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(State& stateToCommit) { if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; - mDrawingState.buffer != stateToCommit.buffer && bufferSurfaceFrame != nullptr && + ((mDrawingState.buffer && stateToCommit.buffer && + mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) || + (mDrawingState.buffer && !stateToCommit.buffer) || + (!mDrawingState.buffer && stateToCommit.buffer)) && + bufferSurfaceFrame != nullptr && bufferSurfaceFrame->getPresentState() != PresentState::Presented) { // If the previous buffer was committed but not latched (refreshPending - happens during // back to back invalidates), it gets silently dropped here. Mark the corresponding diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 64986afd61..8e51e4139b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -208,7 +208,7 @@ public: Region transparentRegionHint; - sp buffer; + std::shared_ptr buffer; client_cache_t clientCacheId; sp acquireFence; std::shared_ptr acquireFenceTime; @@ -412,10 +412,11 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, - nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, - uint64_t /* frameNumber */, std::optional /* dequeueTime */, + virtual bool setBuffer(const std::shared_ptr& /*buffer*/, + const sp& /*acquireFence*/, nsecs_t /*postTime*/, + nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, + const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, + std::optional /* dequeueTime */, const FrameTimelineInfo& /*info*/, const sp& /* releaseBufferListener */) { return false; @@ -726,7 +727,7 @@ public: * Called before updating the drawing state buffer. Used by BufferStateLayer to release any * unlatched buffers in the drawing state. */ - virtual void bufferMayChange(sp& /* newBuffer */){}; + virtual void bufferMayChange(const sp& /* newBuffer */){}; /* * Remove relative z for the layer if its relative parent is not part of the diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 7a3e433660..a9fd16cb75 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -208,7 +208,8 @@ bool RefreshRateOverlay::createLayer() { return true; } -const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { +const std::vector>& +RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { if (mBufferCache.find(fps) == mBufferCache.end()) { // Ensure the range is > 0, so we don't divide by 0. const auto rangeLength = std::max(1u, mHighFps - mLowFps); @@ -222,7 +223,17 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); + auto buffers = SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner); + std::vector> textures; + std::transform(buffers.begin(), buffers.end(), std::back_inserter(textures), + [&](const auto& buffer) -> std::shared_ptr { + return std::make_shared< + renderengine::ExternalTexture>(buffer, + mFlinger.getRenderEngine(), + renderengine::ExternalTexture:: + Usage::READABLE); + }); + mBufferCache.emplace(fps, textures); } return mBufferCache[fps]; diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index c16cfa07a4..aa8329c46a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -16,13 +16,14 @@ #pragma once -#include - #include +#include #include #include #include +#include + #include "Fps.h" namespace android { @@ -70,7 +71,8 @@ private: }; bool createLayer(); - const std::vector>& getOrCreateBuffers(uint32_t fps); + const std::vector>& getOrCreateBuffers( + uint32_t fps); SurfaceFlinger& mFlinger; const sp mClient; @@ -78,7 +80,8 @@ private: sp mIBinder; sp mGbp; - std::unordered_map>> mBufferCache; + std::unordered_map>> + mBufferCache; std::optional mCurrentFps; int mFrame = 0; static constexpr float ALPHA = 0.8f; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index d0032ac7fd..00090d948a 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -438,18 +438,22 @@ void RegionSamplingThread::captureSample() { mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); }; - sp buffer = nullptr; - if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && - mCachedBuffer->getHeight() == sampledBounds.getHeight()) { + std::shared_ptr buffer = nullptr; + if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && + mCachedBuffer->getBuffer()->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), - PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); - const status_t bufferStatus = buffer->initCheck(); + sp graphicBuffer = + new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), + PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); + const status_t bufferStatus = graphicBuffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d", bufferStatus); + buffer = std::make_shared< + renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); } const sp captureListener = new SyncScreenCaptureListener(); @@ -465,8 +469,8 @@ void RegionSamplingThread::captureSample() { } ALOGV("Sampling %zu descriptors", activeDescriptors.size()); - std::vector lumas = - sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); + std::vector lumas = sampleBuffer(buffer->getBuffer(), sampledBounds.leftTop(), + activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); @@ -477,16 +481,6 @@ void RegionSamplingThread::captureSample() { activeDescriptors[d].listener->onSampleCollected(lumas[d]); } - // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that: - // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer - // happens in this thread, as opposed to the main thread. - // 2) The listener(s) receive their notifications prior to freeing the buffer. - if (mCachedBuffer != nullptr && mCachedBuffer != buffer) { - if (mFlinger.getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { - mFlinger.getRenderEngine().unbindExternalTextureBuffer(mCachedBuffer->getId()); - } - } mCachedBuffer = buffer; ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index 0defdb3fcb..86632db490 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -16,17 +16,19 @@ #pragma once +#include +#include +#include +#include +#include +#include + #include #include #include #include #include -#include -#include -#include -#include -#include #include "Scheduler/OneShotTimer.h" namespace android { @@ -122,7 +124,8 @@ private: std::mutex mSamplingMutex; std::unordered_map, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); - sp mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; + std::shared_ptr mCachedBuffer GUARDED_BY(mSamplingMutex) = + nullptr; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 02579c6bde..e66f65b71e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -735,6 +735,7 @@ void SurfaceFlinger::init() { mCompositionEngine->setTimeStats(mTimeStats); mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName)); mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId); + ClientCache::getInstance().setRenderEngine(&getRenderEngine()); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); @@ -3707,7 +3708,6 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin if (uncacheBuffer.isValid()) { ClientCache::getInstance().erase(uncacheBuffer); - getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -4083,23 +4083,16 @@ uint32_t SurfaceFlinger::setClientStateLocked( } bool bufferChanged = what & layer_state_t::eBufferChanged; bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; - sp buffer; + std::shared_ptr buffer; if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - buffer = s.buffer; - bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - if (success) { - getRenderEngine().cacheExternalTextureBuffer(s.buffer); - success = ClientCache::getInstance() - .registerErasedRecipient(s.cachedBuffer, - wp(this)); - if (!success) { - getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId()); - } - } + ClientCache::getInstance().add(s.cachedBuffer, s.buffer); + buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (cacheIdChanged) { buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (bufferChanged) { - buffer = s.buffer; + buffer = std::make_shared< + renderengine::ExternalTexture>(s.buffer, getRenderEngine(), + renderengine::ExternalTexture::Usage::READABLE); } if (buffer) { const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; @@ -6003,15 +5996,17 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d", bufferStatus); - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + const auto texture = std::make_shared< + renderengine::ExternalTexture>(buffer, getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - TraverseLayersFunction traverseLayers, - sp& buffer, bool regionSampling, - bool grayscale, - const sp& captureListener) { +status_t SurfaceFlinger::captureScreenCommon( + RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, + const std::shared_ptr& buffer, bool regionSampling, + bool grayscale, const sp& captureListener) { ATRACE_CALL(); if (captureListener == nullptr) { @@ -6044,15 +6039,6 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, regionSampling, grayscale, captureResults); }); - // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine - // Only do this when we're not doing region sampling, to allow the region sampling thread to - // manage buffer lifecycle itself. - if (!regionSampling && - getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { - getRenderEngine().unbindExternalTextureBuffer(buffer->getId()); - } - captureResults.result = result; captureListener->onScreenCaptureCompleted(captureResults); })); @@ -6060,11 +6046,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, return NO_ERROR; } -status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, - TraverseLayersFunction traverseLayers, - const sp& buffer, bool forSystem, - bool regionSampling, bool grayscale, - ScreenCaptureResults& captureResults) { +status_t SurfaceFlinger::renderScreenImplLocked( + const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + const std::shared_ptr& buffer, bool forSystem, + bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -6072,7 +6057,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); - const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; + const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place @@ -6082,7 +6067,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, return PERMISSION_DENIED; } - captureResults.buffer = buffer; + captureResults.buffer = buffer->getBuffer(); captureResults.capturedDataspace = renderArea.getReqDataSpace(); const auto reqWidth = renderArea.getReqWidth(); @@ -6173,11 +6158,9 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, base::unique_fd drawFence; getRenderEngine().useProtectedContext(useProtected); - // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine - const bool useFramebufferCache = getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED; + const constexpr bool kUseFramebufferCache = false; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - useFramebufferCache, std::move(bufferFence), &drawFence); + kUseFramebufferCache, std::move(bufferFence), &drawFence); if (drawFence >= 0) { sp releaseFence = new Fence(dup(drawFence)); @@ -6442,10 +6425,6 @@ void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) { mOffscreenLayers.erase(layer); } -void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { - getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); -} - status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b3da61e810..a242d8a876 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -184,7 +184,6 @@ public: class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, - public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ISchedulerCallback { @@ -332,9 +331,6 @@ public: wp fromHandle(const sp& handle); wp fromHandleLocked(const sp& handle) const REQUIRES(mStateLock); - // Inherit from ClientCache::ErasedRecipient - void bufferErased(const client_cache_t& clientCacheId) override; - // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; @@ -907,12 +903,14 @@ private: status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp&, + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, bool regionSampling, bool grayscale, const sp&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const sp&, bool forSystem, bool regionSampling, - bool grayscale, ScreenCaptureResults&); + const std::shared_ptr&, + bool forSystem, bool regionSampling, bool grayscale, + ScreenCaptureResults&); sp getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp getDisplayById(DisplayId displayId) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 4e1c0c77ea..3042450f29 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -15,6 +15,7 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues +#include "renderengine/ExternalTexture.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" @@ -194,7 +195,7 @@ public: sp mClientTargetAcquireFence = Fence::NO_FENCE; - sp mCaptureScreenBuffer; + std::shared_ptr mCaptureScreenBuffer; }; template @@ -243,11 +244,15 @@ void CompositionTest::captureScreenComposition() { // TODO: Eliminate expensive/real allocation if possible. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - mCaptureScreenBuffer = new GraphicBuffer(renderArea->getReqWidth(), renderArea->getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); + mCaptureScreenBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(), + renderArea->getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, + "screenshot"), + *mRenderEngine, true); status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(), + mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, forSystem, regionSampling); EXPECT_EQ(NO_ERROR, result); @@ -340,8 +345,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, + const bool, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -389,8 +394,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, + const bool, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -625,8 +630,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -674,8 +679,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -751,8 +756,8 @@ struct CommonSecureLayerProperties : public BaseLayerProperties EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 63baf7dee2..d004b9d9eb 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -352,8 +352,8 @@ public: auto renderScreenImplLocked(const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, - const sp& buffer, bool forSystem, - bool regionSampling) { + const std::shared_ptr& buffer, + bool forSystem, bool regionSampling) { ScreenCaptureResults captureResults; return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem, regionSampling, false /* grayscale */, diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index b5ef0a1334..690a7fd757 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include "TestableSurfaceFlinger.h" @@ -102,6 +104,7 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; + renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -109,9 +112,12 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getId(); + uint64_t bufferId = buffer->getBuffer()->getId(); uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index c75538f476..6ff6e908fa 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include "TestableSurfaceFlinger.h" @@ -104,6 +106,7 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; + renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -124,7 +127,10 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -149,7 +155,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -158,7 +167,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); nsecs_t start = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -196,8 +208,10 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -222,8 +236,10 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -252,8 +268,10 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -351,7 +369,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -359,7 +380,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); @@ -386,7 +410,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -395,7 +422,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); auto dropStartTime1 = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, @@ -407,7 +437,10 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - sp buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer3 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); auto dropStartTime2 = systemTime(); layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -447,7 +480,11 @@ public: std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence1(new Fence()); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); -- cgit v1.2.3-59-g8ed1b From 617752fa9590d39930f7bcf46abaea8f2e1e1032 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Thu, 15 Apr 2021 16:27:01 +0000 Subject: Revert "Add ExternalTexture class into RenderEngine interface" Revert submission 14086921-renderengine-external-tex Reason for revert: Potential culprit for b/185361988 Reverted Changes: I7796764e2:Update WaylandRenderSurface to accomodate interfac... I13904eec4:Update Readback VTS to align with RenderEngine int... I222c71e6e:Add ExternalTexture class into RenderEngine interf... Change-Id: I1501890f4861a3df7ce273f1fe2ccdb275e2632c --- libs/renderengine/Android.bp | 1 - libs/renderengine/ExternalTexture.cpp | 43 ---- libs/renderengine/gl/GLESRenderEngine.cpp | 30 ++- libs/renderengine/gl/GLESRenderEngine.h | 11 +- .../include/renderengine/ExternalTexture.h | 61 ------ .../include/renderengine/LayerSettings.h | 8 +- .../include/renderengine/RenderEngine.h | 57 +++--- .../include/renderengine/mock/RenderEngine.h | 9 +- libs/renderengine/skia/AutoBackendTexture.h | 15 +- libs/renderengine/skia/Cache.cpp | 47 ++--- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 110 +++++----- libs/renderengine/skia/SkiaGLRenderEngine.h | 16 +- libs/renderengine/skia/SkiaRenderEngine.h | 10 +- libs/renderengine/tests/RenderEngineTest.cpp | 228 ++++++++++++++------- .../tests/RenderEngineThreadedTest.cpp | 9 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 15 +- libs/renderengine/threaded/RenderEngineThreaded.h | 11 +- services/surfaceflinger/BufferLayer.cpp | 38 ++-- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 56 +++-- services/surfaceflinger/BufferLayerConsumer.h | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 57 +++--- services/surfaceflinger/BufferStateLayer.h | 8 +- services/surfaceflinger/ClientCache.cpp | 13 +- services/surfaceflinger/ClientCache.h | 10 +- .../include/compositionengine/RenderSurface.h | 10 +- .../compositionengine/RenderSurfaceCreationArgs.h | 7 - .../impl/OutputLayerCompositionState.h | 4 +- .../include/compositionengine/impl/RenderSurface.h | 20 +- .../compositionengine/impl/planner/CachedSet.h | 30 ++- .../include/compositionengine/mock/RenderSurface.h | 2 +- .../CompositionEngine/src/Output.cpp | 31 ++- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/src/RenderSurface.cpp | 64 ++---- .../CompositionEngine/src/planner/CachedSet.cpp | 14 +- .../CompositionEngine/src/planner/Planner.cpp | 7 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 12 +- .../CompositionEngine/tests/OutputTest.cpp | 15 +- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 46 ++--- .../tests/planner/CachedSetTest.cpp | 6 +- services/surfaceflinger/DisplayDevice.cpp | 12 +- services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/Layer.h | 13 +- services/surfaceflinger/RefreshRateOverlay.cpp | 15 +- services/surfaceflinger/RefreshRateOverlay.h | 11 +- services/surfaceflinger/RegionSamplingThread.cpp | 30 +-- services/surfaceflinger/RegionSamplingThread.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 67 +++--- services/surfaceflinger/SurfaceFlinger.h | 12 +- .../tests/unittests/CompositionTest.cpp | 33 ++- .../tests/unittests/TestableSurfaceFlinger.h | 4 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 10 +- .../unittests/TransactionSurfaceFrameTest.cpp | 67 ++---- 53 files changed, 643 insertions(+), 803 deletions(-) delete mode 100644 libs/renderengine/ExternalTexture.cpp delete mode 100644 libs/renderengine/include/renderengine/ExternalTexture.h (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index f395ab43d8..ec39137e24 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -48,7 +48,6 @@ filegroup { name: "librenderengine_sources", srcs: [ "Description.cpp", - "ExternalTexture.cpp", "Mesh.cpp", "RenderEngine.cpp", "Texture.cpp", diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp deleted file mode 100644 index eabff58eba..0000000000 --- a/libs/renderengine/ExternalTexture.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2021 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 - -#include "log/log_main.h" - -namespace android::renderengine { - -ExternalTexture::ExternalTexture(const sp& buffer, RenderEngine& renderEngine, - uint32_t usage) - : mBuffer(buffer), mRenderEngine(renderEngine) { - LOG_ALWAYS_FATAL_IF(buffer == nullptr, - "Attempted to bind a null buffer to an external texture!"); - // GLESRenderEngine has a separate texture cache for output buffers, - if (usage == Usage::WRITEABLE && - (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES || - mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) { - return; - } - mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE); -} - -ExternalTexture::~ExternalTexture() { - mRenderEngine.unmapExternalTextureBuffer(mBuffer); -} - -} // namespace android::renderengine diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index d87315fdc2..a2963a7c33 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -746,8 +746,7 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp& buffer, - bool /*isRenderable*/) { +void GLESRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { ATRACE_CALL(); mImageManager->cacheAsync(buffer, nullptr); } @@ -798,8 +797,8 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp& buffer) { - mImageManager->releaseAsync(buffer->getId(), nullptr); +void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { + mImageManager->releaseAsync(bufferId, nullptr); } std::shared_ptr GLESRenderEngine::unbindExternalTextureBufferForTesting( @@ -1103,7 +1102,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, + const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); @@ -1126,7 +1125,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer->getBuffer()); + validateOutputBufferUsage(buffer); std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an @@ -1143,13 +1142,11 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, if (blurLayersSize == 0) { fbo = std::make_unique(*this, - buffer->getBuffer() - .get() - ->getNativeBuffer(), + buffer.get()->getNativeBuffer(), useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors(); return fbo->getStatus(); } @@ -1160,7 +1157,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors(); return status; } @@ -1197,7 +1194,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't render first blur pass"); return status; } @@ -1206,7 +1203,6 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique(*this, buffer.get() - ->getBuffer() ->getNativeBuffer(), useFramebufferCache); status = fbo->getStatus(); @@ -1219,7 +1215,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't bind native framebuffer"); return status; } @@ -1227,7 +1223,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->getBuffer()->handle); + buffer->handle); checkErrors("Can't render blur filter"); return status; } @@ -1254,7 +1250,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, disableTexture = false; isOpaque = layer->source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer->getBuffer(); + sp gBuf = layer->source.buffer.buffer; validateInputBufferUsage(gBuf); bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); @@ -1278,7 +1274,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Do not cache protected EGLImage, protected memory is limited. if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) { - unmapExternalTextureBuffer(gBuf); + unbindExternalTextureBuffer(gBuf->getId()); } } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index e7ed9c01fa..cd7a86bb0e 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -60,14 +60,16 @@ public: void primeCache() override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; + void cacheExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); + void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); + bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; bool cleanupPostRender(CleanupMode mode) override; int getContextPriority() override; bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } @@ -103,9 +105,6 @@ protected: EXCLUDES(mFramebufferImageCacheMutex); size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) - EXCLUDES(mRenderingMutex); - void unmapExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); private: friend class BindNativeBufferAsFramebuffer; diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h deleted file mode 100644 index 07f0833d4a..0000000000 --- a/libs/renderengine/include/renderengine/ExternalTexture.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2021 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 - -namespace android::renderengine { - -class RenderEngine; - -/** - * Manages GPU image resources on behalf of clients using RenderEngine. - * - * Clients of RenderEngine are required to wrap their GraphicBuffer objects as an ExternalTexture, - * which is then mapped into GPU resources required by RenderEngine. When a client no longer needs - * to use the GraphicBuffer as input into RenderEngine::drawLayers, then the client should delete - * their ExternalTexture so that resources may be freed. - */ -class ExternalTexture { -public: - // Usage specifies the rendering intent for the buffer. - enum Usage : uint32_t { - // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a - // hint to load the buffer into a separate cache - READABLE = 1 << 0, - - // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an - // external texture - WRITEABLE = 1 << 1, - }; - // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given - // usage hint of type Usage. - ExternalTexture(const sp& buffer, RenderEngine& renderEngine, uint32_t usage); - - ~ExternalTexture(); - - // Retrieves the buffer that is bound to this texture. - const sp& getBuffer() const { return mBuffer; } - -private: - sp mBuffer; - RenderEngine& mRenderEngine; - DISALLOW_COPY_AND_ASSIGN(ExternalTexture); -}; - -} // namespace android::renderengine diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index c54c5ba047..7661233967 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -16,9 +16,11 @@ #pragma once +#include + #include #include -#include +#include #include #include #include @@ -29,8 +31,6 @@ #include #include -#include - namespace android { namespace renderengine { @@ -39,7 +39,7 @@ struct Buffer { // Buffer containing the image that we will render. // If buffer == nullptr, then the rest of the fields in this struct will be // ignored. - std::shared_ptr buffer = nullptr; + sp buffer = nullptr; // Fence that will fire when the buffer is ready to be bound. sp fence = nullptr; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index c8a0f0a034..8dd98c3ba3 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -17,20 +17,19 @@ #ifndef SF_RENDERENGINE_H_ #define SF_RENDERENGINE_H_ +#include +#include +#include + #include #include #include -#include #include #include #include -#include -#include #include #include -#include - /** * Allows to set RenderEngine backend to GLES (default) or SkiaGL (NOT yet supported). */ @@ -52,7 +51,6 @@ class Region; namespace renderengine { -class ExternalTexture; class Image; class Mesh; class Texture; @@ -106,6 +104,23 @@ public: virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; + // Caches Image resources for this buffer, but does not bind the buffer to + // a particular texture. + // Note that work is deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that cache/unbind calls + // are performed in a manner that's conflict serializable, i.e. unbinding + // a buffer should never occur before binding the buffer if the caller + // called {bind, cache}ExternalTextureBuffer before calling unbind. + virtual void cacheExternalTextureBuffer(const sp& buffer) = 0; + // Removes internal resources referenced by the bufferId. This method should be + // invoked when the caller will no longer hold a reference to a GraphicBuffer + // and needs to clean up its resources. + // Note that work is deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that cache/unbind calls + // are performed in a manner that's conflict serializable, i.e. unbinding + // a buffer should never occur before binding the buffer if the caller + // called {bind, cache}ExternalTextureBuffer before calling unbind. + virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0; enum class CleanupMode { CLEAN_OUTPUT_RESOURCES, @@ -176,9 +191,8 @@ public: // now, this always returns NO_ERROR. virtual status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) = 0; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; virtual void cleanFramebufferCache() = 0; // Returns the priority this context was actually created with. Note: this may not be // the same as specified at context creation time, due to implementation limits on the @@ -199,31 +213,6 @@ public: static void validateOutputBufferUsage(const sp&); protected: - // Maps GPU resources for this buffer. - // Note that work may be deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that map/unmap calls - // are performed in a manner that's conflict serializable, i.e. unmapping - // a buffer should never occur before binding the buffer if the caller - // called mapExternalTextureBuffer before calling unmap. - // Note also that if the buffer contains protected content, then mapping those GPU resources may - // be deferred until the buffer is really used for drawing. This is because typical SoCs that - // support protected memory only support a limited amount, so optimisitically mapping protected - // memory may be too burdensome. If a buffer contains protected content and the RenderEngine - // implementation supports protected context, then GPU resources may be mapped into both the - // protected and unprotected contexts. - // If the buffer may ever be written to by RenderEngine, then isRenderable must be true. - virtual void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) = 0; - // Unmaps GPU resources used by this buffer. This method should be - // invoked when the caller will no longer hold a reference to a GraphicBuffer - // and needs to clean up its resources. - // Note that if there are multiple callers holding onto the same buffer, then the buffer's - // resources may be internally ref-counted to guard against use-after-free errors. Note that - // work may be deferred to an additional thread, i.e. this call is expected to be made - // asynchronously, but the caller can expect that map/unmap calls are performed in a manner - // that's conflict serializable, i.e. unmap a buffer should never occur before binding the - // buffer if the caller called mapExternalTextureBuffer before calling unmap. - virtual void unmapExternalTextureBuffer(const sp& buffer) = 0; - friend class ExternalTexture; friend class threaded::RenderEngineThreaded; const RenderEngineType mRenderEngineType; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 27dbd1ecf3..228553d643 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -39,6 +39,8 @@ public: MOCK_METHOD1(dump, void(std::string&)); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); + MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); + MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); @@ -48,17 +50,12 @@ public: MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode)); MOCK_METHOD6(drawLayers, status_t(const DisplaySettings&, const std::vector&, - const std::shared_ptr&, const bool, base::unique_fd&&, + const sp&, const bool, base::unique_fd&&, base::unique_fd*)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size)); - -protected: - // mock renderengine still needs to implement these, but callers should never need to call them. - void mapExternalTextureBuffer(const sp&, bool) {} - void unmapExternalTextureBuffer(const sp&) {} }; } // namespace mock diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index 2d61cf854b..bb758780e1 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -21,9 +21,9 @@ #include #include #include -#include #include "android-base/macros.h" +#include "ui/GraphicTypes.h" namespace android { namespace renderengine { @@ -41,18 +41,13 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef(AutoBackendTexture* texture) { setTexture(texture); } + LocalRef() {} ~LocalRef() { // Destroying the texture is the same as setting it to null setTexture(nullptr); } - AutoBackendTexture* getTexture() const { return mTexture; } - - DISALLOW_COPY_AND_ASSIGN(LocalRef); - - private: // Sets the texture to locally ref-track. void setTexture(AutoBackendTexture* texture) { if (mTexture != nullptr) { @@ -64,6 +59,12 @@ public: mTexture->ref(); } } + + AutoBackendTexture* getTexture() const { return mTexture; } + + DISALLOW_COPY_AND_ASSIGN(LocalRef); + + private: AutoBackendTexture* mTexture = nullptr; }; diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 1c2b2fc3ca..1db20c0be0 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -46,7 +46,7 @@ constexpr auto kDestDataSpace = ui::Dataspace::SRGB; } // namespace static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { // Somewhat arbitrary dimensions, but on screen and slightly shorter, based // on actual use. FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30); @@ -73,7 +73,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin auto layers = std::vector{&layer}; // The identity matrix will generate the fast shader - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); // This matrix, which has different scales for x and y, will // generate the slower (more general case) version, which has variants for translucent @@ -86,14 +86,13 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin // clang-format on for (auto translucent : {false, true}) { layer.shadow.casterIsTranslucent = translucent; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture, - const std::shared_ptr& srcTexture) { + sp dstBuffer, sp srcBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -104,7 +103,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }, .source = PixelSource{.buffer = Buffer{ - .buffer = srcTexture, + .buffer = srcBuffer, .maxMasteringLuminance = 1000.f, .maxContentLuminance = 1000.f, }}, @@ -127,7 +126,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.source.buffer.isOpaque = isOpaque; for (auto alpha : {half(.23999f), half(1.0f)}) { layer.alpha = alpha; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -136,7 +135,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting } static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -144,11 +143,11 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting Geometry{ .boundaries = rect, }, + .alpha = 1, .source = PixelSource{ .solidColor = half3(0.1f, 0.2f, 0.3f), }, - .alpha = 1, }; auto layers = std::vector{&layer}; @@ -156,14 +155,14 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) { layer.geometry.roundedCornersRadius = roundedCornersRadius; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } } static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - const std::shared_ptr& dstTexture) { + sp dstBuffer) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -177,7 +176,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings auto layers = std::vector{&layer}; for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; - renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -215,9 +214,6 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp dstBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "primeShaderCache_dst"); - - const auto dstTexture = std::make_shared(dstBuffer, *renderengine, - ExternalTexture::Usage::WRITEABLE); // This buffer will be the source for the call to drawImageLayers. Draw // something to it as a placeholder for what an app draws. We should draw // something, but the details are not important. Make use of the shadow layer drawing step @@ -226,16 +222,11 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src"); - const auto srcTexture = - std::make_shared(srcBuffer, *renderengine, - ExternalTexture::Usage::READABLE | - ExternalTexture::Usage::WRITEABLE); - - drawSolidLayers(renderengine, display, dstTexture); - drawShadowLayers(renderengine, display, srcTexture); - drawBlurLayers(renderengine, display, dstTexture); + drawSolidLayers(renderengine, display, dstBuffer); + drawShadowLayers(renderengine, display, srcBuffer); + drawBlurLayers(renderengine, display, dstBuffer); // The majority of shaders are related to sampling images. - drawImageLayers(renderengine, display, dstTexture, srcTexture); + drawImageLayers(renderengine, display, dstBuffer, srcBuffer); // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; @@ -243,12 +234,12 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp externalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usageExternal, "primeShaderCache_external"); - const auto externalTexture = - std::make_shared(externalBuffer, *renderengine, - ExternalTexture::Usage::READABLE); // TODO(b/184665179) doubles number of image shader compilations, but only somewhere // between 6 and 8 will occur in real uses. - drawImageLayers(renderengine, display, dstTexture, externalTexture); + drawImageLayers(renderengine, display, dstBuffer, externalBuffer); + renderengine->unbindExternalTextureBuffer(externalBuffer->getId()); + + renderengine->unbindExternalTextureBuffer(srcBuffer->getId()); const nsecs_t timeAfter = systemTime(); const float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index e781584a9b..3b2c7e5f66 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -329,6 +329,8 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL } SkiaGLRenderEngine::~SkiaGLRenderEngine() { + cleanFramebufferCache(); + std::lock_guard lock(mRenderingMutex); if (mBlurFilter) { delete mBlurFilter; @@ -482,8 +484,7 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffer, - bool isRenderable) { +void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { // Only run this if RE is running on its own thread. This way the access to GL // operations is guaranteed to be happening on the same thread. if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) { @@ -504,41 +505,25 @@ void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffe auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; std::lock_guard lock(mRenderingMutex); - mGraphicBufferExternalRefs[buffer->getId()]++; - - if (const auto& iter = cache.find(buffer->getId()); iter == cache.end()) { + auto iter = cache.find(buffer->getId()); + if (iter != cache.end()) { + ALOGV("Texture already exists in cache."); + } else { std::shared_ptr imageTextureRef = - std::make_shared( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), - isRenderable)); + std::make_shared(); + imageTextureRef->setTexture( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), false)); cache.insert({buffer->getId(), imageTextureRef}); } // restore the original state of the protected context if necessary useProtectedContext(protectedContextState); } -void SkiaGLRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { +void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { ATRACE_CALL(); std::lock_guard lock(mRenderingMutex); - if (const auto& iter = mGraphicBufferExternalRefs.find(buffer->getId()); - iter != mGraphicBufferExternalRefs.end()) { - if (iter->second == 0) { - ALOGW("Attempted to unmap GraphicBuffer from RenderEngine texture, but the " - "ref count was already zero!", - buffer->getId()); - mGraphicBufferExternalRefs.erase(buffer->getId()); - return; - } - - iter->second--; - - if (iter->second == 0) { - mTextureCache.erase(buffer->getId()); - mProtectedTextureCache.erase(buffer->getId()); - mGraphicBufferExternalRefs.erase(buffer->getId()); - } - } + mTextureCache.erase(bufferId); + mProtectedTextureCache.erase(bufferId); } sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, @@ -636,8 +621,8 @@ private: status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool /*useFramebufferCache*/, + const sp& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -660,18 +645,32 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer->getBuffer()); + validateOutputBufferUsage(buffer); auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext; auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; + AHardwareBuffer_Desc bufferDesc; + AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); + + std::shared_ptr surfaceTextureRef = nullptr; + if (useFramebufferCache) { + auto iter = cache.find(buffer->getId()); + if (iter != cache.end()) { + ALOGV("Cache hit!"); + ATRACE_NAME("Cache hit"); + surfaceTextureRef = iter->second; + } + } - std::shared_ptr surfaceTextureRef; - if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) { - surfaceTextureRef = it->second; - } else { - surfaceTextureRef = std::make_shared( - new AutoBackendTexture(grContext.get(), buffer->getBuffer()->toAHardwareBuffer(), - true)); + if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) { + ATRACE_NAME("Cache miss"); + surfaceTextureRef = std::make_shared(); + surfaceTextureRef->setTexture( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true)); + if (useFramebufferCache) { + ALOGD("Adding to cache"); + cache.insert({buffer->getId(), surfaceTextureRef}); + } } const ui::Dataspace dstDataspace = @@ -877,22 +876,18 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); + validateInputBufferUsage(layer->source.buffer.buffer); const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; - - if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); - iter != cache.end()) { + auto iter = cache.find(item.buffer->getId()); + if (iter != cache.end()) { imageTextureRef = iter->second; } else { - // If we didn't find the image in the cache, then create a local ref but don't cache - // it. If we're using skia, we're guaranteed to run on a dedicated GPU thread so if - // we didn't find anything in the cache then we intentionally did not cache this - // buffer's resources. - imageTextureRef = std::make_shared( - new AutoBackendTexture(grContext.get(), - item.buffer->getBuffer()->toAHardwareBuffer(), - false)); + imageTextureRef = std::make_shared(); + imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(), + item.buffer->toAHardwareBuffer(), + false)); + cache.insert({item.buffer->getId(), imageTextureRef}); } sk_sp image = @@ -1205,6 +1200,15 @@ EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay dis return eglCreatePbufferSurface(display, placeholderConfig, attributes.data()); } +void SkiaGLRenderEngine::cleanFramebufferCache() { + // TODO(b/180767535) Remove this method and use b/180767535 instead, which would allow + // SF to control texture lifecycle more tightly rather than through custom hooks into RE. + std::lock_guard lock(mRenderingMutex); + mRuntimeEffects.clear(); + mProtectedTextureCache.clear(); + mTextureCache.clear(); +} + int SkiaGLRenderEngine::getContextPriority() { int value; eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value); @@ -1277,12 +1281,6 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "Skia's Wrapped Objects:\n"); gpuReporter.logOutput(result, true); - StringAppendF(&result, "RenderEngine tracked buffers: %zu\n", - mGraphicBufferExternalRefs.size()); - StringAppendF(&result, "Dumping buffer ids...\n"); - for (const auto& [id, refCounts] : mGraphicBufferExternalRefs) { - StringAppendF(&result, "- 0x%" PRIx64 " - %d refs \n", id, refCounts); - } StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n", mTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index e71c560a1f..8e77c16b40 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -53,12 +52,13 @@ public: ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex); void primeCache() override; + void cacheExternalTextureBuffer(const sp& buffer) override; + void unbindExternalTextureBuffer(uint64_t bufferId) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; - void cleanFramebufferCache() override {} + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + void cleanFramebufferCache() override; int getContextPriority() override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -72,8 +72,6 @@ protected: void dump(std::string& result) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; - void unmapExternalTextureBuffer(const sp& buffer) override; private: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); @@ -116,9 +114,7 @@ private: const PixelFormat mDefaultPixelFormat; const bool mUseColorManagement; - // Number of external holders of ExternalTexture references, per GraphicBuffer ID. - std::unordered_map mGraphicBufferExternalRefs GUARDED_BY(mRenderingMutex); - // Cache of GL textures that we'll store per GraphicBuffer ID, sliced by GPU context. + // Cache of GL textures that we'll store per GraphicBuffer ID std::unordered_map> mTextureCache GUARDED_BY(mRenderingMutex); std::unordered_map> diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 308c5ffa9f..51ef088a25 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -42,12 +42,15 @@ public: virtual void primeCache() override{}; virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; + virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; + virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; + virtual bool isProtected() const override { return false; } // mInProtectedContext; } virtual bool supportsProtectedContent() const override { return false; }; virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; }; virtual status_t drawLayers(const DisplaySettings& /*display*/, const std::vector& /*layers*/, - const std::shared_ptr& /*buffer*/, + const sp& /*buffer*/, const bool /*useFramebufferCache*/, base::unique_fd&& /*bufferFence*/, base::unique_fd* /*drawFence*/) override { @@ -57,11 +60,6 @@ public: virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} virtual int reportShadersCompiled() { return 0; } - -protected: - virtual void mapExternalTextureBuffer(const sp& /*buffer*/, - bool /*isRenderable*/) override; - virtual void unmapExternalTextureBuffer(const sp& /*buffer*/) override; }; } // namespace skia diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index d63c88bc02..7846156383 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -161,42 +160,27 @@ public: class RenderEngineTest : public ::testing::TestWithParam> { public: - std::shared_ptr allocateDefaultBuffer() { - return std::make_shared< - renderengine:: - ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, - DEFAULT_DISPLAY_HEIGHT, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | - GRALLOC_USAGE_HW_TEXTURE, - "output"), - *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + static sp allocateDefaultBuffer() { + return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, + "output"); } // Allocates a 1x1 buffer to fill with a solid color - std::shared_ptr allocateSourceBuffer(uint32_t width, - uint32_t height) { - return std::make_shared< - renderengine:: - ExternalTexture>(new GraphicBuffer(width, height, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_TEXTURE, - "input"), - *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + static sp allocateSourceBuffer(uint32_t width, uint32_t height) { + return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE, + "input"); } RenderEngineTest() { 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()); + mBuffer = allocateDefaultBuffer(); } ~RenderEngineTest() { @@ -227,21 +211,20 @@ public: } uint8_t* pixels; - mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); file << "P6\n"; - file << mBuffer->getBuffer()->getWidth() << "\n"; - file << mBuffer->getBuffer()->getHeight() << "\n"; + file << mBuffer->getWidth() << "\n"; + file << mBuffer->getHeight() << "\n"; file << 255 << "\n"; - std::vector outBuffer(mBuffer->getBuffer()->getWidth() * - mBuffer->getBuffer()->getHeight() * 3); + std::vector outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3); auto outPtr = reinterpret_cast(outBuffer.data()); - for (int32_t j = 0; j < mBuffer->getBuffer()->getHeight(); j++) { - const uint8_t* src = pixels + (mBuffer->getBuffer()->getStride() * j) * 4; - for (int32_t i = 0; i < mBuffer->getBuffer()->getWidth(); i++) { + for (int32_t j = 0; j < mBuffer->getHeight(); j++) { + const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4; + for (int32_t i = 0; i < mBuffer->getWidth(); i++) { // Only copy R, G and B components outPtr[0] = src[0]; outPtr[1] = src[1]; @@ -252,7 +235,7 @@ public: } } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); - mBuffer->getBuffer()->unlock(); + mBuffer->unlock(); } void expectBufferColor(const Region& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -279,13 +262,13 @@ public: void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, std::function colorCompare) { uint8_t* pixels; - mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); int32_t maxFails = 10; int32_t fails = 0; for (int32_t j = 0; j < region.getHeight(); j++) { - const uint8_t* src = pixels + - (mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4; + const uint8_t* src = + pixels + (mBuffer->getStride() * (region.top + j) + region.left) * 4; for (int32_t i = 0; i < region.getWidth(); i++) { const uint8_t expected[4] = {r, g, b, a}; bool equal = colorCompare(src, expected); @@ -306,7 +289,7 @@ public: break; } } - mBuffer->getBuffer()->unlock(); + mBuffer->unlock(); } void expectAlpha(const Rect& rect, uint8_t a) { @@ -404,6 +387,7 @@ public: base::unique_fd fence; status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence); + mCurrentBuffer = mBuffer; int fd = fence.release(); if (fd >= 0) { @@ -413,7 +397,7 @@ public: ASSERT_EQ(NO_ERROR, status); if (layers.size() > 0 && mGLESRE != nullptr) { - ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); + ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); } } @@ -519,11 +503,17 @@ public: void initializeRenderEngine(); std::unique_ptr mRE; - std::shared_ptr mBuffer; // GLESRenderEngine for testing GLES-specific behavior. // Owened by mRE, but this is downcasted. renderengine::gl::GLESRenderEngine* mGLESRE = nullptr; + // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to + // be freed *after* RenderEngine is destroyed, so that the EGL image is + // destroyed first. + sp mCurrentBuffer; + + sp mBuffer; + std::vector mTexNames; }; @@ -540,7 +530,6 @@ void RenderEngineTest::initializeRenderEngine() { } else { mRE = renderEngineFactory->createRenderEngine(); } - mBuffer = allocateDefaultBuffer(); } struct ColorSourceVariant { @@ -577,18 +566,18 @@ template struct BufferSourceVariant { static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b, RenderEngineTest* fixture) { - const auto buf = fixture->allocateSourceBuffer(1, 1); + sp buf = RenderEngineTest::allocateSourceBuffer(1, 1); uint32_t texName; fixture->mRE->genTextures(1, &texName); fixture->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); - for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) { - uint8_t* iter = pixels + (buf->getBuffer()->getStride() * j) * 4; - for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) { + for (int32_t j = 0; j < buf->getHeight(); j++) { + uint8_t* iter = pixels + (buf->getStride() * j) * 4; + for (int32_t i = 0; i < buf->getWidth(); i++) { iter[0] = uint8_t(r * 255); iter[1] = uint8_t(g * 255); iter[2] = uint8_t(b * 255); @@ -597,7 +586,7 @@ struct BufferSourceVariant { } } - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1023,14 +1012,14 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; // Here will allocate a checker board texture, but transform texture // coordinates so that only the upper left is applied. - const auto buf = allocateSourceBuffer(2, 2); + sp buf = allocateSourceBuffer(2, 2); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); // Red top left, Green top right, Blue bottom left, Black bottom right pixels[0] = 255; pixels[1] = 0; @@ -1044,7 +1033,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { pixels[9] = 0; pixels[10] = 255; pixels[11] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1072,19 +1061,19 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - const auto buf = allocateSourceBuffer(1, 1); + sp buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1111,19 +1100,19 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - const auto buf = allocateSourceBuffer(1, 1); + sp buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1244,7 +1233,8 @@ TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) { } TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { - initializeRenderEngine(); + const auto& renderEngineFactory = GetParam(); + mRE = renderEngineFactory->createRenderEngine(); renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1305,6 +1295,7 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputFence) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr); + mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1332,8 +1323,9 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr); + mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); - ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); + ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1582,6 +1574,98 @@ TEST_P(RenderEngineTest, drawLayers_clearRegion) { clearRegion(); } +TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + renderengine::DisplaySettings settings; + settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; + settings.physicalDisplay = fullscreenRect(); + settings.clip = fullscreenRect(); + + std::vector layers; + + renderengine::LayerSettings layer; + layer.geometry.boundaries = fullscreenRect().toFloatRect(); + BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); + + layers.push_back(&layer); + invokeDraw(settings, layers); + uint64_t bufferId = layer.source.buffer.buffer->getId(); + EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); + std::shared_ptr barrier = + mGLESRE->unbindExternalTextureBufferForTesting(bufferId); + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); + EXPECT_EQ(NO_ERROR, barrier->result); +} + +TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + std::shared_ptr barrier = + mGLESRE->cacheExternalTextureBufferForTesting(nullptr); + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_TRUE(barrier->isOpen); + EXPECT_EQ(BAD_VALUE, barrier->result); +} + +TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) { + const auto& renderEngineFactory = GetParam(); + + if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { + // GLES-specific test + return; + } + + initializeRenderEngine(); + + sp buf = allocateSourceBuffer(1, 1); + uint64_t bufferId = buf->getId(); + std::shared_ptr barrier = + mGLESRE->cacheExternalTextureBufferForTesting(buf); + { + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_EQ(NO_ERROR, barrier->result); + } + EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); + barrier = mGLESRE->unbindExternalTextureBufferForTesting(bufferId); + { + std::lock_guard lock(barrier->mutex); + ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), + [&]() REQUIRES(barrier->mutex) { + return barrier->isOpen; + })); + EXPECT_EQ(NO_ERROR, barrier->result); + } + EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); +} + TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) { initializeRenderEngine(); @@ -1774,7 +1858,7 @@ TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory sync_wait(fd, -1); } - uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId(); + uint64_t bufferId = layer.source.buffer.buffer->getId(); uint32_t texName = layer.source.buffer.textureName; EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName)); @@ -1882,16 +1966,16 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { // The next layer will overwrite redLayer with a GraphicBuffer that is green // applied with a translucent alpha. - const auto buf = allocateSourceBuffer(1, 1); + auto buf = allocateSourceBuffer(1, 1); { uint8_t* pixels; - buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 0; pixels[1] = 255; pixels[2] = 0; pixels[3] = 255; - buf->getBuffer()->unlock(); + buf->unlock(); } const renderengine::LayerSettings greenLayer{ diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index e3917cce09..b093e88d4f 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -162,18 +162,15 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; std::vector layers; - std::shared_ptr buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp buffer = new GraphicBuffer(); base::unique_fd bufferFence; base::unique_fd drawFence; EXPECT_CALL(*mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings&, const std::vector&, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index c9f6296b49..194c7da1c7 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -157,28 +157,27 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { resultFuture.wait(); } -void RenderEngineThreaded::mapExternalTextureBuffer(const sp& buffer, - bool isRenderable) { +void RenderEngineThreaded::cacheExternalTextureBuffer(const sp& buffer) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::mapExternalTextureBuffer"); - instance.mapExternalTextureBuffer(buffer, isRenderable); + ATRACE_NAME("REThreaded::cacheExternalTextureBuffer"); + instance.cacheExternalTextureBuffer(buffer); }); } mCondition.notify_one(); } -void RenderEngineThreaded::unmapExternalTextureBuffer(const sp& buffer) { +void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::unmapExternalTextureBuffer"); - instance.unmapExternalTextureBuffer(buffer); + ATRACE_NAME("REThreaded::unbindExternalTextureBuffer"); + instance.unbindExternalTextureBuffer(bufferId); }); } mCondition.notify_one(); @@ -240,7 +239,7 @@ bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, + const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index eb6098ed8d..61ae9b8cf8 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -48,6 +48,8 @@ public: void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; + void cacheExternalTextureBuffer(const sp& buffer) override; + void unbindExternalTextureBuffer(uint64_t bufferId) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -58,19 +60,14 @@ public: status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const std::shared_ptr& buffer, - const bool useFramebufferCache, base::unique_fd&& bufferFence, - base::unique_fd* drawFence) override; + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; void cleanFramebufferCache() override; int getContextPriority() override; bool supportsBackgroundBlur() override; void onPrimaryDisplaySizeChanged(ui::Size size) override; -protected: - void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; - void unmapExternalTextureBuffer(const sp& buffer) override; - private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 13ac7c3563..be9bce0795 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -188,7 +188,7 @@ std::optional BufferLayer::prepareCli const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const bool bufferCanBeUsedAsHwTexture = - mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; + mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; compositionengine::LayerFE::LayerSettings& layer = *result; if (blackOutLayer || !bufferCanBeUsedAsHwTexture) { ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable", @@ -213,7 +213,7 @@ std::optional BufferLayer::prepareCli ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel : defaultMaxContentLuminance; layer.frameNumber = mCurrentFrameNumber; - layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0; + layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0; const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering(); @@ -314,7 +314,7 @@ void BufferLayer::preparePerFrameCompositionState() { : Hwc2::IComposerClient::Composition::DEVICE; } - compositionState->buffer = mBufferInfo.mBuffer->getBuffer(); + compositionState->buffer = mBufferInfo.mBuffer; compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mBufferInfo.mBufferSlot; @@ -442,7 +442,7 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, void BufferLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = - !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format; + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mFrameLatencyNeeded = true; } @@ -544,10 +544,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, } if (oldBufferInfo.mBuffer != nullptr) { - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); - if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) || - bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) { + 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; } } @@ -612,8 +612,8 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - return (mBufferInfo.mBuffer != nullptr) && - (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED); + const sp& buffer(mBufferInfo.mBuffer); + return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } // h/w composer set-up @@ -727,8 +727,8 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect::INVALID_RECT; } - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->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) { @@ -759,8 +759,8 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return parentBounds; } - uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->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) { @@ -802,7 +802,7 @@ Rect BufferLayer::getBufferCrop() const { return mBufferInfo.mCrop; } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mBufferInfo.mBuffer->getBuffer()->getBounds(); + return mBufferInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -847,14 +847,12 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { } sp BufferLayer::getBuffer() const { - return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr; + return mBufferInfo.mBuffer; } void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { - GLConsumer::computeTransformMatrix(outMatrix, - mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() - : nullptr, - mBufferInfo.mCrop, mBufferInfo.mTransform, filteringEnabled); + GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, filteringEnabled); } void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 855324710e..b8d3f12322 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -134,7 +134,7 @@ protected: PixelFormat mPixelFormat{PIXEL_FORMAT_NONE}; bool mTransformToDisplayInverse{false}; - std::shared_ptr mBuffer; + sp mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; bool mFrameLatencyNeeded{false}; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 96b22478ab..69d2d11a4d 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -166,7 +167,7 @@ void BufferLayerConsumer::setReleaseFence(const sp& fence) { } auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer - : mCurrentTextureBuffer->getBuffer(); + : mCurrentTextureBuffer->graphicBuffer(); auto err = addReleaseFence(slot, buffer, fence); if (err != OK) { BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); @@ -205,11 +206,9 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres // before, so we need to clean up old references. if (item->mGraphicBuffer != nullptr) { std::lock_guard lock(mImagesMutex); - if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr || - mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) { - mImages[item->mSlot] = std::make_shared< - renderengine::ExternalTexture>(item->mGraphicBuffer, mRE, - renderengine::ExternalTexture::Usage::READABLE); + if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr || + mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) { + mImages[item->mSlot] = std::make_shared(item->mGraphicBuffer, mRE); } } @@ -223,8 +222,8 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, int slot = item.mSlot; BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, - (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr) - ? mCurrentTextureBuffer->getBuffer()->handle + (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr) + ? mCurrentTextureBuffer->graphicBuffer()->handle : 0, slot, mSlots[slot].mGraphicBuffer->handle); @@ -232,7 +231,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same. - std::shared_ptr nextTextureBuffer; + std::shared_ptr nextTextureBuffer; { std::lock_guard lock(mImagesMutex); nextTextureBuffer = mImages[slot]; @@ -242,7 +241,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (pendingRelease == nullptr) { status_t status = - releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer()); + releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer()); if (status < NO_ERROR) { BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); @@ -251,7 +250,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } } else { pendingRelease->currentTexture = mCurrentTexture; - pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer(); + pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer(); pendingRelease->isPending = true; } } @@ -302,14 +301,14 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) { void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { BLC_LOGV("computeCurrentTransformMatrixLocked"); - if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->getBuffer() == nullptr) { + if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->graphicBuffer() == nullptr) { BLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureBuffer is nullptr"); } GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer == nullptr ? nullptr - : mCurrentTextureBuffer->getBuffer(), + : mCurrentTextureBuffer->graphicBuffer(), getCurrentCropLocked(), mCurrentTransform, mFilteringEnabled); } @@ -361,8 +360,7 @@ int BufferLayerConsumer::getCurrentApi() const { return mCurrentApi; } -std::shared_ptr BufferLayerConsumer::getCurrentBuffer( - int* outSlot, sp* outFence) const { +sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* outFence) const { Mutex::Autolock lock(mMutex); if (outSlot != nullptr) { @@ -373,7 +371,7 @@ std::shared_ptr BufferLayerConsumer::getCurrentBu *outFence = mCurrentFence; } - return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer; + return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer(); } Rect BufferLayerConsumer::getCurrentCrop() const { @@ -458,12 +456,10 @@ void BufferLayerConsumer::onSidebandStreamChanged() { void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) { std::lock_guard lock(mImagesMutex); - const std::shared_ptr& oldImage = mImages[item.mSlot]; - if (oldImage == nullptr || oldImage->getBuffer() == nullptr || - oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) { - mImages[item.mSlot] = std::make_shared< - renderengine::ExternalTexture>(item.mGraphicBuffer, mRE, - renderengine::ExternalTexture::Usage::READABLE); + const std::shared_ptr& oldImage = mImages[item.mSlot]; + if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr || + oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) { + mImages[item.mSlot] = std::make_shared(item.mGraphicBuffer, mRE); } } } @@ -503,6 +499,22 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } + +BufferLayerConsumer::Image::Image(const sp& graphicBuffer, + renderengine::RenderEngine& engine) + : mGraphicBuffer(graphicBuffer), mRE(engine) { + if (graphicBuffer != nullptr && (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED)) { + return; + } + mRE.cacheExternalTextureBuffer(mGraphicBuffer); +} + +BufferLayerConsumer::Image::~Image() { + if (mGraphicBuffer != nullptr) { + ALOGV("Destroying buffer: %" PRId64, mGraphicBuffer->getId()); + mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId()); + } +} }; // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index 9ed80b46bd..dd39214aff 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -21,11 +21,12 @@ #include #include #include -#include + #include #include #include #include + #include #include #include @@ -38,6 +39,7 @@ class String8; namespace renderengine { class RenderEngine; +class Image; } // namespace renderengine /* @@ -151,8 +153,7 @@ public: // When outSlot is not nullptr, the current buffer slot index is also // returned. Simiarly, when outFence is not nullptr, the current output // fence is returned. - std::shared_ptr getCurrentBuffer( - int* outSlot = nullptr, sp* outFence = nullptr) const; + sp getCurrentBuffer(int* outSlot = nullptr, sp* outFence = nullptr) const; // getCurrentCrop returns the cropping rectangle of the current buffer. Rect getCurrentCrop() const; @@ -257,7 +258,7 @@ private: // mCurrentTextureBuffer is the buffer containing the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. - std::shared_ptr mCurrentTextureBuffer; + std::shared_ptr mCurrentTextureBuffer; // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set each time updateTexImage is called. @@ -336,8 +337,7 @@ private: int mCurrentTexture; // Shadow buffer cache for cleaning up renderengine references. - std::shared_ptr - mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); + std::shared_ptr mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); // Separate mutex guarding the shadow buffer cache. // mImagesMutex can be manipulated with binder threads (e.g. onBuffersAllocated) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c533969a5c..ed826a0100 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -71,8 +71,14 @@ BufferStateLayer::~BufferStateLayer() { // 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()) { - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence); + // 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()); + const uint64_t bufferId = mBufferInfo.mBuffer->getId(); + engine.unbindExternalTextureBuffer(bufferId); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, + mBufferInfo.mFence); } } @@ -357,9 +363,8 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -bool BufferStateLayer::setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, bool isAutoTimestamp, +bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, + nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& releaseBufferListener) { @@ -367,14 +372,12 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer() != mDrawingState.buffer->getBuffer()) { + if (mCurrentState.buffer != mDrawingState.buffer) { // If mCurrentState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mCurrentState.releaseBufferListener, - mCurrentState.buffer->getBuffer(), + callReleaseBufferCallback(mCurrentState.releaseBufferListener, mCurrentState.buffer, mCurrentState.acquireFence); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { @@ -412,8 +415,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getId(); + if (dequeueTime && *dequeueTime != 0) { + const uint64_t bufferId = buffer->getId(); mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime, FrameTracer::FrameEvent::DEQUEUE); @@ -421,8 +424,8 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getWidth(); - mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight(); + mCurrentState.width = mCurrentState.buffer->width; + mCurrentState.height = mCurrentState.buffer->height; return true; } @@ -671,7 +674,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const int32_t layerId = getSequence(); - const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId(); + const uint64_t bufferId = mDrawingState.buffer->getId(); const uint64_t frameNumber = mDrawingState.frameNumber; const auto acquireFence = std::make_shared(mDrawingState.acquireFence); mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence); @@ -705,7 +708,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { + if (s.buffer != mBufferInfo.mBuffer) { decrementPendingBufferCount(); } @@ -824,13 +827,13 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBuffer()->getBounds(); + 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->getBuffer()->getWidth(); - uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); + 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)); @@ -838,7 +841,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer - return s.buffer->getBuffer()->getBounds(); + return s.buffer->getBounds(); } return crop; } @@ -860,8 +863,8 @@ bool BufferStateLayer::bufferNeedsFiltering() const { return false; } - uint32_t bufferWidth = s.buffer->getBuffer()->width; - uint32_t bufferHeight = s.buffer->getBuffer()->height; + uint32_t bufferWidth = s.buffer->width; + uint32_t bufferHeight = s.buffer->height; // Undo any transformations on the buffer and return the result. if (s.bufferTransform & ui::Transform::ROT_90) { @@ -888,16 +891,14 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) { ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } -void BufferStateLayer::bufferMayChange(const sp& newBuffer) { - if (mDrawingState.buffer != nullptr && - (!mBufferInfo.mBuffer || - mDrawingState.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) && - newBuffer != mDrawingState.buffer->getBuffer()) { +void BufferStateLayer::bufferMayChange(sp& newBuffer) { + if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && + newBuffer != mDrawingState.buffer) { // If we are about to update mDrawingState.buffer but it has not yet latched // then we will drop a buffer and should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mDrawingState.releaseBufferListener, - mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, + mDrawingState.acquireFence); decrementPendingBufferCount(); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index a69d07f634..8ce3e1f55b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -66,9 +66,9 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const std::shared_ptr& buffer, - const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, - bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, + bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, + nsecs_t desiredPresentTime, bool isAutoTimestamp, + const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& transactionListener) override; bool setAcquireFence(const sp& fence) override; @@ -108,7 +108,7 @@ public: // See mPendingBufferTransactions void decrementPendingBufferCount(); - void bufferMayChange(const sp& newBuffer) override; + void bufferMayChange(sp& newBuffer) override; std::atomic* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index f310738423..44b33ef43d 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -102,12 +102,7 @@ bool ClientCache::add(const client_cache_t& cacheId, const sp& bu return false; } - LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, - "Attempted to build the ClientCache before a RenderEngine instance was " - "ready!"); - processBuffers[id].buffer = std::make_shared< - renderengine::ExternalTexture>(buffer, *mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); + processBuffers[id].buffer = buffer; return true; } @@ -137,7 +132,7 @@ void ClientCache::erase(const client_cache_t& cacheId) { } } -std::shared_ptr ClientCache::get(const client_cache_t& cacheId) { +sp ClientCache::get(const client_cache_t& cacheId) { std::lock_guard lock(mMutex); ClientCacheBuffer* buf = nullptr; @@ -218,8 +213,8 @@ void ClientCache::dump(std::string& result) { auto &buffers = i.second.second; for (auto& [id, clientCacheBuffer] : buffers) { StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id, - (int)clientCacheBuffer.buffer->getBuffer()->getWidth(), - (int)clientCacheBuffer.buffer->getBuffer()->getHeight()); + (int)clientCacheBuffer.buffer->getWidth(), + (int)clientCacheBuffer.buffer->getHeight()); } } } diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h index a9b8177d70..0d597c8e05 100644 --- a/services/surfaceflinger/ClientCache.h +++ b/services/surfaceflinger/ClientCache.h @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -40,11 +39,7 @@ public: bool add(const client_cache_t& cacheId, const sp& buffer); void erase(const client_cache_t& cacheId); - std::shared_ptr get(const client_cache_t& cacheId); - - // Always called immediately after setup. Will be set to non-null, and then should never be - // called again. - void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; } + sp get(const client_cache_t& cacheId); void removeProcess(const wp& processToken); @@ -64,7 +59,7 @@ private: std::mutex mMutex; struct ClientCacheBuffer { - std::shared_ptr buffer; + sp buffer; std::set> recipients; }; std::map /*caching process*/, @@ -78,7 +73,6 @@ private: }; sp mDeathRecipient; - renderengine::RenderEngine* mRenderEngine = nullptr; bool getBuffer(const client_cache_t& cacheId, ClientCacheBuffer** outClientCacheBuffer) REQUIRES(mMutex); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index daee83bd2c..f680460242 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -16,16 +16,15 @@ #pragma once -#include +#include +#include + #include #include #include #include #include -#include -#include - namespace android { class GraphicBuffer; @@ -81,8 +80,7 @@ public: virtual void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) = 0; // Allocates a buffer as scratch space for GPU composition - virtual std::shared_ptr dequeueBuffer( - base::unique_fd* bufferFence) = 0; + virtual sp dequeueBuffer(base::unique_fd* bufferFence) = 0; // Queues the drawn buffer for consumption by HWC. readyFence is the fence // which will fire when the buffer is ready for consumption. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h index a8d372c562..a1230b3c4d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h @@ -45,8 +45,6 @@ struct RenderSurfaceCreationArgs { // The DisplaySurface for this surface sp displaySurface; - - size_t maxTextureCacheSize; }; /** @@ -83,11 +81,6 @@ public: return *this; } - RenderSurfaceCreationArgsBuilder& setMaxTextureCacheSize(size_t maxTextureCacheSize) { - mArgs.maxTextureCacheSize = maxTextureCacheSize; - return *this; - } - private: RenderSurfaceCreationArgs mArgs; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index c61ec5991b..48a54d6c66 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ struct OutputLayerCompositionState { // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { - std::shared_ptr buffer = nullptr; + sp buffer = nullptr; sp acquireFence = nullptr; Rect displayFrame = {}; ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index a8a538003e..5127a6f314 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -16,16 +16,12 @@ #pragma once +#include + #include #include #include -#include -#include - -#include "renderengine/ExternalTexture.h" -#include "renderengine/RenderEngine.h" - struct ANativeWindow; namespace android { @@ -58,8 +54,7 @@ public: void setProtected(bool useProtected) override; status_t beginFrame(bool mustRecompose) override; void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override; - std::shared_ptr dequeueBuffer( - base::unique_fd* bufferFence) override; + sp dequeueBuffer(base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; @@ -71,7 +66,7 @@ public: // Testing void setPageFlipCountForTest(std::uint32_t); void setSizeForTest(const ui::Size&); - std::shared_ptr& mutableTextureForTest(); + sp& mutableGraphicBufferForTest(); base::unique_fd& mutableBufferReadyForTest(); private: @@ -80,13 +75,10 @@ private: // ANativeWindow being rendered into const sp mNativeWindow; - - std::vector> mTextureCache; - // Current texture being rendered into - std::shared_ptr mTexture; + // Current buffer being rendered into + sp mGraphicBuffer; const sp mDisplaySurface; ui::Size mSize; - const size_t mMaxTextureCacheSize; bool mProtected{false}; std::uint32_t mPageFlipCount{0}; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 53f4a30fb8..c5d03a7218 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -66,7 +66,7 @@ public: const Rect& getBounds() const { return mBounds; } const Region& getVisibleRegion() const { return mVisibleRegion; } size_t getAge() const { return mAge; } - const std::shared_ptr& getBuffer() const { return mTexture; } + const sp& getBuffer() const { return mTexture.getBuffer(); } const sp& getDrawFence() const { return mDrawFence; } const ProjectionSpace& getOutputSpace() const { return mOutputSpace; } ui::Dataspace getOutputDataspace() const { return mOutputDataspace; } @@ -87,7 +87,7 @@ public: void setLastUpdate(std::chrono::steady_clock::time_point now) { mLastUpdate = now; } void append(const CachedSet& other) { - mTexture = nullptr; + mTexture.setBuffer(nullptr, nullptr); mOutputDataspace = ui::Dataspace::UNKNOWN; mDrawFence = nullptr; @@ -115,7 +115,31 @@ private: Region mVisibleRegion; size_t mAge = 0; - std::shared_ptr mTexture; + class Texture { + public: + ~Texture() { setBuffer(nullptr, nullptr); } + + void setBuffer(const sp& buffer, renderengine::RenderEngine* re) { + if (mRE && mBuffer) { + mRE->unbindExternalTextureBuffer(mBuffer->getId()); + } + + mBuffer = buffer; + mRE = re; + + if (mRE && mBuffer) { + mRE->cacheExternalTextureBuffer(mBuffer); + } + } + + const sp& getBuffer() const { return mBuffer; } + + private: + sp mBuffer = nullptr; + renderengine::RenderEngine* mRE = nullptr; + }; + + Texture mTexture; sp mDrawFence; ProjectionSpace mOutputSpace; ui::Dataspace mOutputDataspace; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index fe858c2817..a0cae6fcbb 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -39,7 +39,7 @@ public: MOCK_METHOD1(setBufferPixelFormat, void(ui::PixelFormat)); MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); MOCK_METHOD2(prepareFrame, void(bool, bool)); - MOCK_METHOD1(dequeueBuffer, std::shared_ptr(base::unique_fd*)); + MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd)); MOCK_METHOD0(onPresentDisplayCompleted, void()); MOCK_METHOD0(flip, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 3468b204fc..3ac5433457 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +#include + #include #include #include @@ -28,9 +29,7 @@ #include #include -#include - -#include "renderengine/ExternalTexture.h" +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -716,11 +715,11 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr bool skipLayer = false; if (layer->getState().overrideInfo.buffer != nullptr) { if (previousOverride != nullptr && - layer->getState().overrideInfo.buffer->getBuffer() == previousOverride) { + layer->getState().overrideInfo.buffer == previousOverride) { ALOGV("Skipping redundant buffer"); skipLayer = true; } - previousOverride = layer->getState().overrideInfo.buffer->getBuffer(); + previousOverride = layer->getState().overrideInfo.buffer; } const bool includeGeometry = refreshArgs.updatingGeometryThisFrame; @@ -979,15 +978,14 @@ std::optional Output::composeSurfaces( } base::unique_fd fd; - - std::shared_ptr tex; + sp buf; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { - tex = mRenderSurface->dequeueBuffer(&fd); - if (tex == nullptr) { + 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()); @@ -1032,14 +1030,13 @@ std::optional Output::composeSurfaces( // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { - if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), - clientCompositionDisplay, + if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay, clientCompositionLayers)) { outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return readyFence; } - mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, + mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1072,12 +1069,12 @@ std::optional Output::composeSurfaces( // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerStackInternal; status_t status = - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf, useFramebufferCache, std::move(fd), &readyFence); if (status != NO_ERROR && mClientCompositionRequestCache) { // If rendering was not successful, remove the request from the cache. - mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); + mClientCompositionRequestCache->remove(buf->getId()); } auto& timeStats = getCompositionEngine().getTimeStats(); @@ -1154,9 +1151,9 @@ std::vector Output::generateClientCompositionRequests( std::vector results; if (layer->getState().overrideInfo.buffer != nullptr) { - if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) { + if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) { results = layer->getOverrideCompositionList(); - previousOverrideBuffer = layer->getState().overrideInfo.buffer->getBuffer(); + previousOverrideBuffer = layer->getState().overrideInfo.buffer; ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); } else { ALOGV("Skipping redundant override buffer for [%s] in RE", diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 9ca8914deb..f640f85bca 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -537,7 +537,7 @@ void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, sp buffer = outputIndependentState.buffer; sp acquireFence = outputIndependentState.acquireFence; if (getState().overrideInfo.buffer != nullptr) { - buffer = getState().overrideInfo.buffer->getBuffer(); + buffer = getState().overrideInfo.buffer; acquireFence = getState().overrideInfo.acquireFence; } @@ -699,7 +699,7 @@ std::vector OutputLayer::getOverrideCompositionList() co settings.geometry = renderengine::Geometry{ .boundaries = boundaries.toFloatRect(), }; - settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId(); + settings.bufferId = getState().overrideInfo.buffer->getId(); settings.source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = getState().overrideInfo.buffer, diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index ef50870615..3bef77dde1 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -25,8 +25,8 @@ #include #include #include + #include -#include #include #include #include @@ -63,8 +63,7 @@ RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display mDisplay(display), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), - mSize(args.displayWidth, args.displayHeight), - mMaxTextureCacheSize(args.maxTextureCacheSize) { + mSize(args.displayWidth, args.displayHeight) { LOG_ALWAYS_FATAL_IF(!mNativeWindow); } @@ -147,8 +146,7 @@ void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComp } } -std::shared_ptr RenderSurface::dequeueBuffer( - base::unique_fd* bufferFence) { +sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { ATRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; @@ -160,41 +158,16 @@ std::shared_ptr RenderSurface::dequeueBuffer( mDisplay.getName().c_str(), result); // Return fast here as we can't do much more - any rendering we do // now will just be wrong. - return mTexture; - } - - ALOGW_IF(mTexture != nullptr, "Clobbering a non-null pointer to a buffer [%p].", - mTexture->getBuffer()->getNativeBuffer()->handle); - - sp newBuffer = GraphicBuffer::from(buffer); - - std::shared_ptr texture; - - for (auto it = mTextureCache.begin(); it != mTextureCache.end(); it++) { - const auto& cachedTexture = *it; - if (cachedTexture->getBuffer()->getId() == newBuffer->getId()) { - texture = cachedTexture; - mTextureCache.erase(it); - break; - } + return mGraphicBuffer; } - if (texture) { - mTexture = texture; - } else { - mTexture = std::make_shared< - renderengine::ExternalTexture>(GraphicBuffer::from(buffer), - mCompositionEngine.getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); - } - mTextureCache.push_back(mTexture); - if (mTextureCache.size() > mMaxTextureCacheSize) { - mTextureCache.erase(mTextureCache.begin()); - } + ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", + mGraphicBuffer->getNativeBuffer()->handle); + mGraphicBuffer = GraphicBuffer::from(buffer); *bufferFence = base::unique_fd(fd); - return mTexture; + return mGraphicBuffer; } void RenderSurface::queueBuffer(base::unique_fd readyFence) { @@ -204,24 +177,24 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { // hasFlipClientTargetRequest could return true even if we haven't // dequeued a buffer before. Try dequeueing one if we don't have a // buffer ready. - if (mTexture == nullptr) { + if (mGraphicBuffer == nullptr) { ALOGI("Attempting to queue a client composited buffer without one " "previously dequeued for display [%s]. Attempting to dequeue " "a scratch buffer now", mDisplay.getName().c_str()); - // We shouldn't deadlock here, since mTexture == nullptr only + // We shouldn't deadlock here, since mGraphicBuffer == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. base::unique_fd unused; dequeueBuffer(&unused); } - if (mTexture == nullptr) { + if (mGraphicBuffer == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { - status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), - mTexture->getBuffer()->getNativeBuffer(), - dup(readyFence)); + status_t result = + mNativeWindow->queueBuffer(mNativeWindow.get(), + mGraphicBuffer->getNativeBuffer(), dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); @@ -231,12 +204,11 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), - mTexture->getBuffer()->getNativeBuffer(), - dup(readyFence)); + mGraphicBuffer->getNativeBuffer(), dup(readyFence)); } } - mTexture = nullptr; + mGraphicBuffer = nullptr; } } @@ -284,8 +256,8 @@ void RenderSurface::setSizeForTest(const ui::Size& size) { mSize = size; } -std::shared_ptr& RenderSurface::mutableTextureForTest() { - return mTexture; +sp& RenderSurface::mutableGraphicBufferForTest() { + return mGraphicBuffer; } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index 53557bbb9f..dcb75556e3 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -130,7 +130,7 @@ bool CachedSet::hasBufferUpdate() const { } bool CachedSet::hasReadyBuffer() const { - return mTexture != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; + return mTexture.getBuffer() != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; } std::vector CachedSet::decompose() const { @@ -217,27 +217,21 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, sp buffer = new GraphicBuffer(static_cast(mBounds.getWidth()), static_cast(mBounds.getHeight()), HAL_PIXEL_FORMAT_RGBA_8888, 1, usageFlags); - const auto texture = std::make_shared< - renderengine::ExternalTexture>(buffer, renderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); LOG_ALWAYS_FATAL_IF(buffer->initCheck() != OK); base::unique_fd drawFence; - status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, mTexture, - false, base::unique_fd(), &drawFence); + status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, buffer, false, + base::unique_fd(), &drawFence); if (result == NO_ERROR) { + mTexture.setBuffer(buffer, &renderEngine); mDrawFence = new Fence(drawFence.release()); mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(), outputState.framebufferSpace.bounds.getHeight()), mBounds); - mTexture = std::move(texture); mOutputSpace.orientation = outputState.framebufferSpace.orientation; mOutputDataspace = outputDataspace; mOrientation = orientation; - } else { - mTexture = nullptr; } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index 3a2534b847..ad7555730d 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -111,12 +111,7 @@ void Planner::reportFinalPlan( const GraphicBuffer* currentOverrideBuffer = nullptr; bool hasSkippedLayers = false; for (auto layer : layers) { - if (!layer->getState().overrideInfo.buffer) { - continue; - } - - const GraphicBuffer* overrideBuffer = - layer->getState().overrideInfo.buffer->getBuffer().get(); + const GraphicBuffer* overrideBuffer = layer->getState().overrideInfo.buffer.get(); if (overrideBuffer != nullptr && overrideBuffer == currentOverrideBuffer) { // Skip this layer since it is part of a previous cached set hasSkippedLayers = true; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 4c3f4940cc..8a4d161289 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -26,7 +26,6 @@ #include "MockHWC2.h" #include "MockHWComposer.h" #include "RegionMatcher.h" -#include "renderengine/mock/RenderEngine.h" namespace android::compositionengine { namespace { @@ -716,7 +715,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const HdrMetadata kHdrMetadata; static native_handle_t* kSidebandStreamHandle; static const sp kBuffer; - std::shared_ptr kOverrideBuffer; + static const sp kOverrideBuffer; static const sp kFence; static const sp kOverrideFence; static const std::string kLayerGenericMetadata1Key; @@ -725,11 +724,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const std::vector kLayerGenericMetadata2Value; OutputLayerWriteStateToHWCTest() { - kOverrideBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage:: - WRITEABLE); auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); @@ -845,7 +839,6 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { std::shared_ptr mHwcLayer{std::make_shared>()}; StrictMock mDisplayColorProfile; - renderengine::mock::RenderEngine mRenderEngine; }; const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, @@ -865,6 +858,7 @@ const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattena native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle = reinterpret_cast(1031); const sp OutputLayerWriteStateToHWCTest::kBuffer; +const sp OutputLayerWriteStateToHWCTest::kOverrideBuffer = new GraphicBuffer(); const sp OutputLayerWriteStateToHWCTest::kFence; const sp OutputLayerWriteStateToHWCTest::kOverrideFence = new Fence(); const std::string OutputLayerWriteStateToHWCTest::kLayerGenericMetadata1Key = @@ -1029,7 +1023,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { kOverrideBufferTransform, kOverrideBlendMode, kOverrideAlpha); expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion, kOverrideSurfaceDamage); - expectSetHdrMetadataAndBufferCalls(kOverrideBuffer->getBuffer(), kOverrideFence); + expectSetHdrMetadataAndBufferCalls(kOverrideBuffer, kOverrideFence); expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index e80100cc6e..5f0b0eea15 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include + #include #include #include @@ -29,12 +31,9 @@ #include #include -#include - #include "CallOrderStateMachineHelper.h" #include "MockHWC2.h" #include "RegionMatcher.h" -#include "renderengine/ExternalTexture.h" namespace android::compositionengine { namespace { @@ -2961,10 +2960,7 @@ struct OutputComposeSurfacesTest : public testing::Test { mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); mock::RenderSurface* mRenderSurface = new StrictMock(); StrictMock mOutput; - std::shared_ptr mOutputBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp mOutputBuffer = new GraphicBuffer(); std::optional mReadyFence; }; @@ -3177,10 +3173,7 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); - const auto otherOutputBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + sp otherOutputBuffer = new GraphicBuffer(); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 9aeb290eb5..5ef5d7b5cb 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -15,8 +15,6 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues -#include "renderengine/ExternalTexture.h" -#include "ui/GraphicBuffer.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra" @@ -241,9 +239,9 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); base::unique_fd fence; - EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence)->getBuffer().get()); + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get()); - EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest()->getBuffer().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); } /* @@ -251,11 +249,8 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { */ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; @@ -266,45 +261,43 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; state.flipClientTarget = false; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; state.flipClientTarget = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) { @@ -324,28 +317,27 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferY mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); - mSurface.mutableTextureForTest() = buffer; + sp buffer = new GraphicBuffer(); + mSurface.mutableGraphicBufferForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(INVALID_OPERATION)); EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true)); - EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 283c69270f..f01fe27b38 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -305,8 +305,8 @@ TEST_F(CachedSetTest, render) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector& layers, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> size_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> size_t { EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), @@ -321,6 +321,7 @@ TEST_F(CachedSetTest, render) { EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); + EXPECT_CALL(mRenderEngine, cacheExternalTextureBuffer(_)); cachedSet.render(mRenderEngine, mOutputState); expectReadyBuffer(cachedSet); @@ -330,6 +331,7 @@ TEST_F(CachedSetTest, render) { cachedSet.getOutputSpace().bounds); // Now check that appending a new cached set properly cleans up RenderEngine resources. + EXPECT_CALL(mRenderEngine, unbindExternalTextureBuffer(_)); CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 8692ee60dc..b7b2cc691b 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,13 +70,11 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( - compositionengine:: - RenderSurfaceCreationArgs{ANativeWindow_getWidth(args.nativeWindow.get()), - ANativeWindow_getHeight(args.nativeWindow.get()), - args.nativeWindow, args.displaySurface, - static_cast( - SurfaceFlinger:: - maxFrameBufferAcquiredBuffers)}); + compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth( + args.nativeWindow.get()), + ANativeWindow_getHeight( + args.nativeWindow.get()), + args.nativeWindow, args.displaySurface}); if (!mFlinger->mDisableClientCompositionCache && SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b12e3fb626..829b91676b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1050,7 +1050,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { } // Allow BufferStateLayer to release any unlatched buffers in drawing state. - bufferMayChange(c.buffer->getBuffer()); + bufferMayChange(c.buffer); // Commit the transaction commitTransaction(c); @@ -1062,11 +1062,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(State& stateToCommit) { if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; - ((mDrawingState.buffer && stateToCommit.buffer && - mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) || - (mDrawingState.buffer && !stateToCommit.buffer) || - (!mDrawingState.buffer && stateToCommit.buffer)) && - bufferSurfaceFrame != nullptr && + mDrawingState.buffer != stateToCommit.buffer && bufferSurfaceFrame != nullptr && bufferSurfaceFrame->getPresentState() != PresentState::Presented) { // If the previous buffer was committed but not latched (refreshPending - happens during // back to back invalidates), it gets silently dropped here. Mark the corresponding diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8e51e4139b..64986afd61 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -208,7 +208,7 @@ public: Region transparentRegionHint; - std::shared_ptr buffer; + sp buffer; client_cache_t clientCacheId; sp acquireFence; std::shared_ptr acquireFenceTime; @@ -412,11 +412,10 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setBuffer(const std::shared_ptr& /*buffer*/, - const sp& /*acquireFence*/, nsecs_t /*postTime*/, - nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, - const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, - std::optional /* dequeueTime */, + virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, + nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, + bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, + uint64_t /* frameNumber */, std::optional /* dequeueTime */, const FrameTimelineInfo& /*info*/, const sp& /* releaseBufferListener */) { return false; @@ -727,7 +726,7 @@ public: * Called before updating the drawing state buffer. Used by BufferStateLayer to release any * unlatched buffers in the drawing state. */ - virtual void bufferMayChange(const sp& /* newBuffer */){}; + virtual void bufferMayChange(sp& /* newBuffer */){}; /* * Remove relative z for the layer if its relative parent is not part of the diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index a9fd16cb75..7a3e433660 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -208,8 +208,7 @@ bool RefreshRateOverlay::createLayer() { return true; } -const std::vector>& -RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { +const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { if (mBufferCache.find(fps) == mBufferCache.end()) { // Ensure the range is > 0, so we don't divide by 0. const auto rangeLength = std::max(1u, mHighFps - mLowFps); @@ -223,17 +222,7 @@ RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - auto buffers = SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner); - std::vector> textures; - std::transform(buffers.begin(), buffers.end(), std::back_inserter(textures), - [&](const auto& buffer) -> std::shared_ptr { - return std::make_shared< - renderengine::ExternalTexture>(buffer, - mFlinger.getRenderEngine(), - renderengine::ExternalTexture:: - Usage::READABLE); - }); - mBufferCache.emplace(fps, textures); + mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); } return mBufferCache[fps]; diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index aa8329c46a..c16cfa07a4 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -16,14 +16,13 @@ #pragma once +#include + #include -#include #include #include #include -#include - #include "Fps.h" namespace android { @@ -71,8 +70,7 @@ private: }; bool createLayer(); - const std::vector>& getOrCreateBuffers( - uint32_t fps); + const std::vector>& getOrCreateBuffers(uint32_t fps); SurfaceFlinger& mFlinger; const sp mClient; @@ -80,8 +78,7 @@ private: sp mIBinder; sp mGbp; - std::unordered_map>> - mBufferCache; + std::unordered_map>> mBufferCache; std::optional mCurrentFps; int mFrame = 0; static constexpr float ALPHA = 0.8f; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 00090d948a..d0032ac7fd 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -438,22 +438,18 @@ void RegionSamplingThread::captureSample() { mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); }; - std::shared_ptr buffer = nullptr; - if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && - mCachedBuffer->getBuffer()->getHeight() == sampledBounds.getHeight()) { + sp buffer = nullptr; + if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && + mCachedBuffer->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - sp graphicBuffer = - new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), - PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); - const status_t bufferStatus = graphicBuffer->initCheck(); + buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), + PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); + const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d", bufferStatus); - buffer = std::make_shared< - renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); } const sp captureListener = new SyncScreenCaptureListener(); @@ -469,8 +465,8 @@ void RegionSamplingThread::captureSample() { } ALOGV("Sampling %zu descriptors", activeDescriptors.size()); - std::vector lumas = sampleBuffer(buffer->getBuffer(), sampledBounds.leftTop(), - activeDescriptors, orientation); + std::vector lumas = + sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); @@ -481,6 +477,16 @@ void RegionSamplingThread::captureSample() { activeDescriptors[d].listener->onSampleCollected(lumas[d]); } + // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that: + // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer + // happens in this thread, as opposed to the main thread. + // 2) The listener(s) receive their notifications prior to freeing the buffer. + if (mCachedBuffer != nullptr && mCachedBuffer != buffer) { + if (mFlinger.getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + mFlinger.getRenderEngine().unbindExternalTextureBuffer(mCachedBuffer->getId()); + } + } mCachedBuffer = buffer; ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index 86632db490..0defdb3fcb 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -16,19 +16,17 @@ #pragma once -#include -#include -#include -#include -#include -#include - #include #include #include #include #include +#include +#include +#include +#include +#include #include "Scheduler/OneShotTimer.h" namespace android { @@ -124,8 +122,7 @@ private: std::mutex mSamplingMutex; std::unordered_map, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); - std::shared_ptr mCachedBuffer GUARDED_BY(mSamplingMutex) = - nullptr; + sp mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e66f65b71e..02579c6bde 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -735,7 +735,6 @@ void SurfaceFlinger::init() { mCompositionEngine->setTimeStats(mTimeStats); mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName)); mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId); - ClientCache::getInstance().setRenderEngine(&getRenderEngine()); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); @@ -3708,6 +3707,7 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin if (uncacheBuffer.isValid()) { ClientCache::getInstance().erase(uncacheBuffer); + getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -4083,16 +4083,23 @@ uint32_t SurfaceFlinger::setClientStateLocked( } bool bufferChanged = what & layer_state_t::eBufferChanged; bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; - std::shared_ptr buffer; + sp buffer; if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - buffer = ClientCache::getInstance().get(s.cachedBuffer); + buffer = s.buffer; + bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer); + if (success) { + getRenderEngine().cacheExternalTextureBuffer(s.buffer); + success = ClientCache::getInstance() + .registerErasedRecipient(s.cachedBuffer, + wp(this)); + if (!success) { + getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId()); + } + } } else if (cacheIdChanged) { buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (bufferChanged) { - buffer = std::make_shared< - renderengine::ExternalTexture>(s.buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::READABLE); + buffer = s.buffer; } if (buffer) { const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; @@ -5996,17 +6003,15 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d", bufferStatus); - const auto texture = std::make_shared< - renderengine::ExternalTexture>(buffer, getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon( - RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, bool regionSampling, - bool grayscale, const sp& captureListener) { +status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, + TraverseLayersFunction traverseLayers, + sp& buffer, bool regionSampling, + bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (captureListener == nullptr) { @@ -6039,6 +6044,15 @@ status_t SurfaceFlinger::captureScreenCommon( regionSampling, grayscale, captureResults); }); + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + // Only do this when we're not doing region sampling, to allow the region sampling thread to + // manage buffer lifecycle itself. + if (!regionSampling && + getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + getRenderEngine().unbindExternalTextureBuffer(buffer->getId()); + } + captureResults.result = result; captureListener->onScreenCaptureCompleted(captureResults); })); @@ -6046,10 +6060,11 @@ status_t SurfaceFlinger::captureScreenCommon( return NO_ERROR; } -status_t SurfaceFlinger::renderScreenImplLocked( - const RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, bool forSystem, - bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { +status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, + TraverseLayersFunction traverseLayers, + const sp& buffer, bool forSystem, + bool regionSampling, bool grayscale, + ScreenCaptureResults& captureResults) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -6057,7 +6072,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); - const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED; + const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place @@ -6067,7 +6082,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( return PERMISSION_DENIED; } - captureResults.buffer = buffer->getBuffer(); + captureResults.buffer = buffer; captureResults.capturedDataspace = renderArea.getReqDataSpace(); const auto reqWidth = renderArea.getReqWidth(); @@ -6158,9 +6173,11 @@ status_t SurfaceFlinger::renderScreenImplLocked( base::unique_fd drawFence; getRenderEngine().useProtectedContext(useProtected); - const constexpr bool kUseFramebufferCache = false; + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + const bool useFramebufferCache = getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - kUseFramebufferCache, std::move(bufferFence), &drawFence); + useFramebufferCache, std::move(bufferFence), &drawFence); if (drawFence >= 0) { sp releaseFence = new Fence(dup(drawFence)); @@ -6425,6 +6442,10 @@ void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) { mOffscreenLayers.erase(layer); } +void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { + getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); +} + status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index a242d8a876..b3da61e810 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -184,6 +184,7 @@ public: class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, + public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ISchedulerCallback { @@ -331,6 +332,9 @@ public: wp fromHandle(const sp& handle); wp fromHandleLocked(const sp& handle) const REQUIRES(mStateLock); + // Inherit from ClientCache::ErasedRecipient + void bufferErased(const client_cache_t& clientCacheId) override; + // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; @@ -903,14 +907,12 @@ private: status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, - const std::shared_ptr&, + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp&, bool regionSampling, bool grayscale, const sp&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, - bool forSystem, bool regionSampling, bool grayscale, - ScreenCaptureResults&); + const sp&, bool forSystem, bool regionSampling, + bool grayscale, ScreenCaptureResults&); sp getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp getDisplayById(DisplayId displayId) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 3042450f29..4e1c0c77ea 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -15,7 +15,6 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues -#include "renderengine/ExternalTexture.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" @@ -195,7 +194,7 @@ public: sp mClientTargetAcquireFence = Fence::NO_FENCE; - std::shared_ptr mCaptureScreenBuffer; + sp mCaptureScreenBuffer; }; template @@ -244,15 +243,11 @@ void CompositionTest::captureScreenComposition() { // TODO: Eliminate expensive/real allocation if possible. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - mCaptureScreenBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(), - renderArea->getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, - "screenshot"), - *mRenderEngine, true); + mCaptureScreenBuffer = new GraphicBuffer(renderArea->getReqWidth(), renderArea->getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(), forSystem, regionSampling); EXPECT_EQ(NO_ERROR, result); @@ -345,8 +340,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const std::shared_ptr&, - const bool, base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -394,8 +389,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const std::shared_ptr&, - const bool, base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -630,8 +625,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -679,8 +674,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -756,8 +751,8 @@ struct CommonSecureLayerProperties : public BaseLayerProperties EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const std::shared_ptr&, const bool, - base::unique_fd&&, base::unique_fd*) -> status_t { + const sp&, const bool, base::unique_fd&&, + base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d004b9d9eb..63baf7dee2 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -352,8 +352,8 @@ public: auto renderScreenImplLocked(const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, - const std::shared_ptr& buffer, - bool forSystem, bool regionSampling) { + const sp& buffer, bool forSystem, + bool regionSampling) { ScreenCaptureResults captureResults; return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem, regionSampling, false /* grayscale */, diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 690a7fd757..b5ef0a1334 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include "TestableSurfaceFlinger.h" @@ -104,7 +102,6 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; - renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -112,12 +109,9 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getBuffer()->getId(); + uint64_t bufferId = buffer->getId(); uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 6ff6e908fa..c75538f476 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -21,8 +21,6 @@ #include #include #include -#include -#include #include #include "TestableSurfaceFlinger.h" @@ -106,7 +104,6 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; - renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -127,10 +124,7 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -155,10 +149,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -167,10 +158,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; nsecs_t start = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -208,10 +196,8 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -236,10 +222,8 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -268,10 +252,8 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -369,10 +351,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -380,10 +359,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); @@ -410,10 +386,7 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -422,10 +395,7 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime1 = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, @@ -437,10 +407,7 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - const auto buffer3 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, - 1, 0), - mRenderEngine, false); + sp buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; auto dropStartTime2 = systemTime(); layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -480,11 +447,7 @@ public: std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence1(new Fence()); - const auto buffer1 = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(1, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - 0), - mRenderEngine, false); + sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); -- cgit v1.2.3-59-g8ed1b From a90a570e5b35c72bc90bf20572dd989084c4db39 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Fri, 16 Apr 2021 16:36:21 +0000 Subject: Revert "Revert "Add ExternalTexture class into RenderEngine inte..." Revert submission 14199598-revert-14086921-renderengine-external-tex-QJNBWQMQEU Reason for revert: Prepare for relanding Reverted Changes: I01e65a7f4:Revert "Update WaylandRenderSurface to accomodate ... I7d58118c1:Revert "Update Readback VTS to align with RenderEn... I1501890f4:Revert "Add ExternalTexture class into RenderEngin... Added the following fixes: 1. CachedSet renders to intermediate texture variable rather than mTexture directly, since mTexture is not guaranteed to be nonnull. 2. Add null check when setting new buffer in BLAST. Bug: 185524947 Bug: 180767535 Test: builds, boots Test: librenderengine_test Change-Id: I52ea82e24336b496d996bbe3e445db0affe1abb8 --- libs/renderengine/Android.bp | 1 + libs/renderengine/ExternalTexture.cpp | 43 ++++ libs/renderengine/gl/GLESRenderEngine.cpp | 30 +-- libs/renderengine/gl/GLESRenderEngine.h | 11 +- .../include/renderengine/ExternalTexture.h | 61 ++++++ .../include/renderengine/LayerSettings.h | 8 +- .../include/renderengine/RenderEngine.h | 57 +++--- .../include/renderengine/mock/RenderEngine.h | 9 +- libs/renderengine/skia/AutoBackendTexture.h | 15 +- libs/renderengine/skia/Cache.cpp | 47 +++-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 110 +++++----- libs/renderengine/skia/SkiaGLRenderEngine.h | 16 +- libs/renderengine/skia/SkiaRenderEngine.h | 10 +- libs/renderengine/tests/RenderEngineTest.cpp | 228 +++++++-------------- .../tests/RenderEngineThreadedTest.cpp | 9 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 15 +- libs/renderengine/threaded/RenderEngineThreaded.h | 11 +- services/surfaceflinger/BufferLayer.cpp | 38 ++-- services/surfaceflinger/BufferLayer.h | 2 +- services/surfaceflinger/BufferLayerConsumer.cpp | 56 ++--- services/surfaceflinger/BufferLayerConsumer.h | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 57 +++--- services/surfaceflinger/BufferStateLayer.h | 8 +- services/surfaceflinger/ClientCache.cpp | 13 +- services/surfaceflinger/ClientCache.h | 10 +- .../include/compositionengine/RenderSurface.h | 10 +- .../compositionengine/RenderSurfaceCreationArgs.h | 7 + .../impl/OutputLayerCompositionState.h | 4 +- .../include/compositionengine/impl/RenderSurface.h | 20 +- .../compositionengine/impl/planner/CachedSet.h | 30 +-- .../include/compositionengine/mock/RenderSurface.h | 2 +- .../CompositionEngine/src/Output.cpp | 31 +-- .../CompositionEngine/src/OutputLayer.cpp | 4 +- .../CompositionEngine/src/RenderSurface.cpp | 64 ++++-- .../CompositionEngine/src/planner/CachedSet.cpp | 14 +- .../CompositionEngine/src/planner/Planner.cpp | 7 +- .../CompositionEngine/tests/OutputLayerTest.cpp | 12 +- .../CompositionEngine/tests/OutputTest.cpp | 15 +- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 46 +++-- .../tests/planner/CachedSetTest.cpp | 6 +- services/surfaceflinger/DisplayDevice.cpp | 12 +- services/surfaceflinger/Layer.cpp | 8 +- services/surfaceflinger/Layer.h | 13 +- services/surfaceflinger/RefreshRateOverlay.cpp | 15 +- services/surfaceflinger/RefreshRateOverlay.h | 11 +- services/surfaceflinger/RegionSamplingThread.cpp | 30 ++- services/surfaceflinger/RegionSamplingThread.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 69 +++---- services/surfaceflinger/SurfaceFlinger.h | 12 +- .../tests/unittests/CompositionTest.cpp | 33 +-- .../tests/unittests/TestableSurfaceFlinger.h | 4 +- .../tests/unittests/TransactionFrameTracerTest.cpp | 10 +- .../unittests/TransactionSurfaceFrameTest.cpp | 67 ++++-- 53 files changed, 804 insertions(+), 644 deletions(-) create mode 100644 libs/renderengine/ExternalTexture.cpp create mode 100644 libs/renderengine/include/renderengine/ExternalTexture.h (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index ec39137e24..f395ab43d8 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -48,6 +48,7 @@ filegroup { name: "librenderengine_sources", srcs: [ "Description.cpp", + "ExternalTexture.cpp", "Mesh.cpp", "RenderEngine.cpp", "Texture.cpp", diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp new file mode 100644 index 0000000000..eabff58eba --- /dev/null +++ b/libs/renderengine/ExternalTexture.cpp @@ -0,0 +1,43 @@ +/* + * Copyright 2021 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 + +#include "log/log_main.h" + +namespace android::renderengine { + +ExternalTexture::ExternalTexture(const sp& buffer, RenderEngine& renderEngine, + uint32_t usage) + : mBuffer(buffer), mRenderEngine(renderEngine) { + LOG_ALWAYS_FATAL_IF(buffer == nullptr, + "Attempted to bind a null buffer to an external texture!"); + // GLESRenderEngine has a separate texture cache for output buffers, + if (usage == Usage::WRITEABLE && + (mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::GLES || + mRenderEngine.getRenderEngineType() == RenderEngine::RenderEngineType::THREADED)) { + return; + } + mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE); +} + +ExternalTexture::~ExternalTexture() { + mRenderEngine.unmapExternalTextureBuffer(mBuffer); +} + +} // namespace android::renderengine diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index a2963a7c33..d87315fdc2 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -746,7 +746,8 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp& buffer) { +void GLESRenderEngine::mapExternalTextureBuffer(const sp& buffer, + bool /*isRenderable*/) { ATRACE_CALL(); mImageManager->cacheAsync(buffer, nullptr); } @@ -797,8 +798,8 @@ status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const spreleaseAsync(bufferId, nullptr); +void GLESRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { + mImageManager->releaseAsync(buffer->getId(), nullptr); } std::shared_ptr GLESRenderEngine::unbindExternalTextureBufferForTesting( @@ -1102,7 +1103,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, + const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_CALL(); @@ -1125,7 +1126,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer); + validateOutputBufferUsage(buffer->getBuffer()); std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an @@ -1142,11 +1143,13 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, if (blurLayersSize == 0) { fbo = std::make_unique(*this, - buffer.get()->getNativeBuffer(), + buffer->getBuffer() + .get() + ->getNativeBuffer(), useFramebufferCache); if (fbo->getStatus() != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors(); return fbo->getStatus(); } @@ -1157,7 +1160,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); if (status != NO_ERROR) { ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors(); return status; } @@ -1194,7 +1197,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, auto status = mBlurFilter->prepare(); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't render first blur pass"); return status; } @@ -1203,6 +1206,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Done blurring, time to bind the native FBO and render our blur onto it. fbo = std::make_unique(*this, buffer.get() + ->getBuffer() ->getNativeBuffer(), useFramebufferCache); status = fbo->getStatus(); @@ -1215,7 +1219,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't bind native framebuffer"); return status; } @@ -1223,7 +1227,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, status = mBlurFilter->render(blurLayersSize > 1); if (status != NO_ERROR) { ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).", - buffer->handle); + buffer->getBuffer()->handle); checkErrors("Can't render blur filter"); return status; } @@ -1250,7 +1254,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, disableTexture = false; isOpaque = layer->source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer; + sp gBuf = layer->source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); @@ -1274,7 +1278,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, // Do not cache protected EGLImage, protected memory is limited. if (gBuf->getUsage() & GRALLOC_USAGE_PROTECTED) { - unbindExternalTextureBuffer(gBuf->getId()); + unmapExternalTextureBuffer(gBuf); } } diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index cd7a86bb0e..e7ed9c01fa 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -60,16 +60,14 @@ public: void primeCache() override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; - void cacheExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); - void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); - bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; bool useProtectedContext(bool useProtectedContext) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; bool cleanupPostRender(CleanupMode mode) override; int getContextPriority() override; bool supportsBackgroundBlur() override { return mBlurFilter != nullptr; } @@ -105,6 +103,9 @@ protected: EXCLUDES(mFramebufferImageCacheMutex); size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) + EXCLUDES(mRenderingMutex); + void unmapExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); private: friend class BindNativeBufferAsFramebuffer; diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h new file mode 100644 index 0000000000..07f0833d4a --- /dev/null +++ b/libs/renderengine/include/renderengine/ExternalTexture.h @@ -0,0 +1,61 @@ +/* + * Copyright 2021 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 + +namespace android::renderengine { + +class RenderEngine; + +/** + * Manages GPU image resources on behalf of clients using RenderEngine. + * + * Clients of RenderEngine are required to wrap their GraphicBuffer objects as an ExternalTexture, + * which is then mapped into GPU resources required by RenderEngine. When a client no longer needs + * to use the GraphicBuffer as input into RenderEngine::drawLayers, then the client should delete + * their ExternalTexture so that resources may be freed. + */ +class ExternalTexture { +public: + // Usage specifies the rendering intent for the buffer. + enum Usage : uint32_t { + // When a buffer is not READABLE but is WRITEABLE, then GLESRenderEngine will use that as a + // hint to load the buffer into a separate cache + READABLE = 1 << 0, + + // The buffer needs to be mapped as a 2D texture if set, otherwise must be mapped as an + // external texture + WRITEABLE = 1 << 1, + }; + // Creates an ExternalTexture for the provided buffer and RenderEngine instance, with the given + // usage hint of type Usage. + ExternalTexture(const sp& buffer, RenderEngine& renderEngine, uint32_t usage); + + ~ExternalTexture(); + + // Retrieves the buffer that is bound to this texture. + const sp& getBuffer() const { return mBuffer; } + +private: + sp mBuffer; + RenderEngine& mRenderEngine; + DISALLOW_COPY_AND_ASSIGN(ExternalTexture); +}; + +} // namespace android::renderengine diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h index 7661233967..c54c5ba047 100644 --- a/libs/renderengine/include/renderengine/LayerSettings.h +++ b/libs/renderengine/include/renderengine/LayerSettings.h @@ -16,11 +16,9 @@ #pragma once -#include - #include #include -#include +#include #include #include #include @@ -31,6 +29,8 @@ #include #include +#include + namespace android { namespace renderengine { @@ -39,7 +39,7 @@ struct Buffer { // Buffer containing the image that we will render. // If buffer == nullptr, then the rest of the fields in this struct will be // ignored. - sp buffer = nullptr; + std::shared_ptr buffer = nullptr; // Fence that will fire when the buffer is ready to be bound. sp fence = nullptr; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 8dd98c3ba3..c8a0f0a034 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -17,19 +17,20 @@ #ifndef SF_RENDERENGINE_H_ #define SF_RENDERENGINE_H_ -#include -#include -#include - #include #include #include +#include #include #include #include +#include +#include #include #include +#include + /** * Allows to set RenderEngine backend to GLES (default) or SkiaGL (NOT yet supported). */ @@ -51,6 +52,7 @@ class Region; namespace renderengine { +class ExternalTexture; class Image; class Mesh; class Texture; @@ -104,23 +106,6 @@ public: virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - // Caches Image resources for this buffer, but does not bind the buffer to - // a particular texture. - // Note that work is deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that cache/unbind calls - // are performed in a manner that's conflict serializable, i.e. unbinding - // a buffer should never occur before binding the buffer if the caller - // called {bind, cache}ExternalTextureBuffer before calling unbind. - virtual void cacheExternalTextureBuffer(const sp& buffer) = 0; - // Removes internal resources referenced by the bufferId. This method should be - // invoked when the caller will no longer hold a reference to a GraphicBuffer - // and needs to clean up its resources. - // Note that work is deferred to an additional thread, i.e. this call - // is made asynchronously, but the caller can expect that cache/unbind calls - // are performed in a manner that's conflict serializable, i.e. unbinding - // a buffer should never occur before binding the buffer if the caller - // called {bind, cache}ExternalTextureBuffer before calling unbind. - virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0; enum class CleanupMode { CLEAN_OUTPUT_RESOURCES, @@ -191,8 +176,9 @@ public: // now, this always returns NO_ERROR. virtual status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) = 0; virtual void cleanFramebufferCache() = 0; // Returns the priority this context was actually created with. Note: this may not be // the same as specified at context creation time, due to implementation limits on the @@ -213,6 +199,31 @@ public: static void validateOutputBufferUsage(const sp&); protected: + // Maps GPU resources for this buffer. + // Note that work may be deferred to an additional thread, i.e. this call + // is made asynchronously, but the caller can expect that map/unmap calls + // are performed in a manner that's conflict serializable, i.e. unmapping + // a buffer should never occur before binding the buffer if the caller + // called mapExternalTextureBuffer before calling unmap. + // Note also that if the buffer contains protected content, then mapping those GPU resources may + // be deferred until the buffer is really used for drawing. This is because typical SoCs that + // support protected memory only support a limited amount, so optimisitically mapping protected + // memory may be too burdensome. If a buffer contains protected content and the RenderEngine + // implementation supports protected context, then GPU resources may be mapped into both the + // protected and unprotected contexts. + // If the buffer may ever be written to by RenderEngine, then isRenderable must be true. + virtual void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) = 0; + // Unmaps GPU resources used by this buffer. This method should be + // invoked when the caller will no longer hold a reference to a GraphicBuffer + // and needs to clean up its resources. + // Note that if there are multiple callers holding onto the same buffer, then the buffer's + // resources may be internally ref-counted to guard against use-after-free errors. Note that + // work may be deferred to an additional thread, i.e. this call is expected to be made + // asynchronously, but the caller can expect that map/unmap calls are performed in a manner + // that's conflict serializable, i.e. unmap a buffer should never occur before binding the + // buffer if the caller called mapExternalTextureBuffer before calling unmap. + virtual void unmapExternalTextureBuffer(const sp& buffer) = 0; + friend class ExternalTexture; friend class threaded::RenderEngineThreaded; const RenderEngineType mRenderEngineType; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 228553d643..27dbd1ecf3 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -39,8 +39,6 @@ public: MOCK_METHOD1(dump, void(std::string&)); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); - MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); - MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); @@ -50,12 +48,17 @@ public: MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode)); MOCK_METHOD6(drawLayers, status_t(const DisplaySettings&, const std::vector&, - const sp&, const bool, base::unique_fd&&, + const std::shared_ptr&, const bool, base::unique_fd&&, base::unique_fd*)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); MOCK_METHOD0(supportsBackgroundBlur, bool()); MOCK_METHOD1(onPrimaryDisplaySizeChanged, void(ui::Size)); + +protected: + // mock renderengine still needs to implement these, but callers should never need to call them. + void mapExternalTextureBuffer(const sp&, bool) {} + void unmapExternalTextureBuffer(const sp&) {} }; } // namespace mock diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index bb758780e1..2d61cf854b 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -21,9 +21,9 @@ #include #include #include +#include #include "android-base/macros.h" -#include "ui/GraphicTypes.h" namespace android { namespace renderengine { @@ -41,13 +41,18 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef() {} + LocalRef(AutoBackendTexture* texture) { setTexture(texture); } ~LocalRef() { // Destroying the texture is the same as setting it to null setTexture(nullptr); } + AutoBackendTexture* getTexture() const { return mTexture; } + + DISALLOW_COPY_AND_ASSIGN(LocalRef); + + private: // Sets the texture to locally ref-track. void setTexture(AutoBackendTexture* texture) { if (mTexture != nullptr) { @@ -59,12 +64,6 @@ public: mTexture->ref(); } } - - AutoBackendTexture* getTexture() const { return mTexture; } - - DISALLOW_COPY_AND_ASSIGN(LocalRef); - - private: AutoBackendTexture* mTexture = nullptr; }; diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index 1db20c0be0..1c2b2fc3ca 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -46,7 +46,7 @@ constexpr auto kDestDataSpace = ui::Dataspace::SRGB; } // namespace static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { // Somewhat arbitrary dimensions, but on screen and slightly shorter, based // on actual use. FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30); @@ -73,7 +73,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin auto layers = std::vector{&layer}; // The identity matrix will generate the fast shader - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(), + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); // This matrix, which has different scales for x and y, will // generate the slower (more general case) version, which has variants for translucent @@ -86,13 +86,14 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin // clang-format on for (auto translucent : {false, true}) { layer.shadow.casterIsTranslucent = translucent; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer, sp srcBuffer) { + const std::shared_ptr& dstTexture, + const std::shared_ptr& srcTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -103,7 +104,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }, .source = PixelSource{.buffer = Buffer{ - .buffer = srcBuffer, + .buffer = srcTexture, .maxMasteringLuminance = 1000.f, .maxContentLuminance = 1000.f, }}, @@ -126,7 +127,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.source.buffer.isOpaque = isOpaque; for (auto alpha : {half(.23999f), half(1.0f)}) { layer.alpha = alpha; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -135,7 +136,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting } static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -143,11 +144,11 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting Geometry{ .boundaries = rect, }, - .alpha = 1, .source = PixelSource{ .solidColor = half3(0.1f, 0.2f, 0.3f), }, + .alpha = 1, }; auto layers = std::vector{&layer}; @@ -155,14 +156,14 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) { layer.geometry.roundedCornersRadius = roundedCornersRadius; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } } static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display, - sp dstBuffer) { + const std::shared_ptr& dstTexture) { const Rect& displayRect = display.physicalDisplay; FloatRect rect(0, 0, displayRect.width(), displayRect.height()); LayerSettings layer{ @@ -176,7 +177,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings auto layers = std::vector{&layer}; for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; - renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, + renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(), nullptr); } } @@ -214,6 +215,9 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp dstBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "primeShaderCache_dst"); + + const auto dstTexture = std::make_shared(dstBuffer, *renderengine, + ExternalTexture::Usage::WRITEABLE); // This buffer will be the source for the call to drawImageLayers. Draw // something to it as a placeholder for what an app draws. We should draw // something, but the details are not important. Make use of the shadow layer drawing step @@ -222,11 +226,16 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src"); - drawSolidLayers(renderengine, display, dstBuffer); - drawShadowLayers(renderengine, display, srcBuffer); - drawBlurLayers(renderengine, display, dstBuffer); + const auto srcTexture = + std::make_shared(srcBuffer, *renderengine, + ExternalTexture::Usage::READABLE | + ExternalTexture::Usage::WRITEABLE); + + drawSolidLayers(renderengine, display, dstTexture); + drawShadowLayers(renderengine, display, srcTexture); + drawBlurLayers(renderengine, display, dstTexture); // The majority of shaders are related to sampling images. - drawImageLayers(renderengine, display, dstBuffer, srcBuffer); + drawImageLayers(renderengine, display, dstTexture, srcTexture); // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE; @@ -234,12 +243,12 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { sp externalBuffer = new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1, usageExternal, "primeShaderCache_external"); + const auto externalTexture = + std::make_shared(externalBuffer, *renderengine, + ExternalTexture::Usage::READABLE); // TODO(b/184665179) doubles number of image shader compilations, but only somewhere // between 6 and 8 will occur in real uses. - drawImageLayers(renderengine, display, dstBuffer, externalBuffer); - renderengine->unbindExternalTextureBuffer(externalBuffer->getId()); - - renderengine->unbindExternalTextureBuffer(srcBuffer->getId()); + drawImageLayers(renderengine, display, dstTexture, externalTexture); const nsecs_t timeAfter = systemTime(); const float compileTimeMs = static_cast(timeAfter - timeBefore) / 1.0E6; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index df40dd9c2d..37d98a3a8f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -329,8 +329,6 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL } SkiaGLRenderEngine::~SkiaGLRenderEngine() { - cleanFramebufferCache(); - std::lock_guard lock(mRenderingMutex); if (mBlurFilter) { delete mBlurFilter; @@ -484,7 +482,8 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { +void SkiaGLRenderEngine::mapExternalTextureBuffer(const sp& buffer, + bool isRenderable) { // Only run this if RE is running on its own thread. This way the access to GL // operations is guaranteed to be happening on the same thread. if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) { @@ -505,25 +504,41 @@ void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buf auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; std::lock_guard lock(mRenderingMutex); - auto iter = cache.find(buffer->getId()); - if (iter != cache.end()) { - ALOGV("Texture already exists in cache."); - } else { + mGraphicBufferExternalRefs[buffer->getId()]++; + + if (const auto& iter = cache.find(buffer->getId()); iter == cache.end()) { std::shared_ptr imageTextureRef = - std::make_shared(); - imageTextureRef->setTexture( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), false)); + std::make_shared( + new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), + isRenderable)); cache.insert({buffer->getId(), imageTextureRef}); } // restore the original state of the protected context if necessary useProtectedContext(protectedContextState); } -void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { +void SkiaGLRenderEngine::unmapExternalTextureBuffer(const sp& buffer) { ATRACE_CALL(); std::lock_guard lock(mRenderingMutex); - mTextureCache.erase(bufferId); - mProtectedTextureCache.erase(bufferId); + if (const auto& iter = mGraphicBufferExternalRefs.find(buffer->getId()); + iter != mGraphicBufferExternalRefs.end()) { + if (iter->second == 0) { + ALOGW("Attempted to unmap GraphicBuffer from RenderEngine texture, but the " + "ref count was already zero!", + buffer->getId()); + mGraphicBufferExternalRefs.erase(buffer->getId()); + return; + } + + iter->second--; + + if (iter->second == 0) { + mTextureCache.erase(buffer->getId()); + mProtectedTextureCache.erase(buffer->getId()); + mGraphicBufferExternalRefs.erase(buffer->getId()); + } + } } sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, @@ -621,8 +636,8 @@ private: status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, - const bool useFramebufferCache, + const std::shared_ptr& buffer, + const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -645,32 +660,18 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } - validateOutputBufferUsage(buffer); + validateOutputBufferUsage(buffer->getBuffer()); auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext; auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; - AHardwareBuffer_Desc bufferDesc; - AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); - - std::shared_ptr surfaceTextureRef = nullptr; - if (useFramebufferCache) { - auto iter = cache.find(buffer->getId()); - if (iter != cache.end()) { - ALOGV("Cache hit!"); - ATRACE_NAME("Cache hit"); - surfaceTextureRef = iter->second; - } - } - if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) { - ATRACE_NAME("Cache miss"); - surfaceTextureRef = std::make_shared(); - surfaceTextureRef->setTexture( - new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true)); - if (useFramebufferCache) { - ALOGD("Adding to cache"); - cache.insert({buffer->getId(), surfaceTextureRef}); - } + std::shared_ptr surfaceTextureRef; + if (const auto& it = cache.find(buffer->getBuffer()->getId()); it != cache.end()) { + surfaceTextureRef = it->second; + } else { + surfaceTextureRef = std::make_shared( + new AutoBackendTexture(grContext.get(), buffer->getBuffer()->toAHardwareBuffer(), + true)); } const ui::Dataspace dstDataspace = @@ -876,18 +877,22 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer); + validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; - auto iter = cache.find(item.buffer->getId()); - if (iter != cache.end()) { + + if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); + iter != cache.end()) { imageTextureRef = iter->second; } else { - imageTextureRef = std::make_shared(); - imageTextureRef->setTexture(new AutoBackendTexture(grContext.get(), - item.buffer->toAHardwareBuffer(), - false)); - cache.insert({item.buffer->getId(), imageTextureRef}); + // If we didn't find the image in the cache, then create a local ref but don't cache + // it. If we're using skia, we're guaranteed to run on a dedicated GPU thread so if + // we didn't find anything in the cache then we intentionally did not cache this + // buffer's resources. + imageTextureRef = std::make_shared( + new AutoBackendTexture(grContext.get(), + item.buffer->getBuffer()->toAHardwareBuffer(), + false)); } sk_sp image = @@ -1200,15 +1205,6 @@ EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay dis return eglCreatePbufferSurface(display, placeholderConfig, attributes.data()); } -void SkiaGLRenderEngine::cleanFramebufferCache() { - // TODO(b/180767535) Remove this method and use b/180767535 instead, which would allow - // SF to control texture lifecycle more tightly rather than through custom hooks into RE. - std::lock_guard lock(mRenderingMutex); - mRuntimeEffects.clear(); - mProtectedTextureCache.clear(); - mTextureCache.clear(); -} - int SkiaGLRenderEngine::getContextPriority() { int value; eglQueryContext(mEGLDisplay, mEGLContext, EGL_CONTEXT_PRIORITY_LEVEL_IMG, &value); @@ -1281,6 +1277,12 @@ void SkiaGLRenderEngine::dump(std::string& result) { StringAppendF(&result, "Skia's Wrapped Objects:\n"); gpuReporter.logOutput(result, true); + StringAppendF(&result, "RenderEngine tracked buffers: %zu\n", + mGraphicBufferExternalRefs.size()); + StringAppendF(&result, "Dumping buffer ids...\n"); + for (const auto& [id, refCounts] : mGraphicBufferExternalRefs) { + StringAppendF(&result, "- 0x%" PRIx64 " - %d refs \n", id, refCounts); + } StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n", mTextureCache.size()); StringAppendF(&result, "Dumping buffer ids...\n"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 8e77c16b40..e71c560a1f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -52,13 +53,12 @@ public: ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex); void primeCache() override; - void cacheExternalTextureBuffer(const sp& buffer) override; - void unbindExternalTextureBuffer(uint64_t bufferId) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; - void cleanFramebufferCache() override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; + void cleanFramebufferCache() override {} int getContextPriority() override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -72,6 +72,8 @@ protected: void dump(std::string& result) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; + void unmapExternalTextureBuffer(const sp& buffer) override; private: static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); @@ -114,7 +116,9 @@ private: const PixelFormat mDefaultPixelFormat; const bool mUseColorManagement; - // Cache of GL textures that we'll store per GraphicBuffer ID + // Number of external holders of ExternalTexture references, per GraphicBuffer ID. + std::unordered_map mGraphicBufferExternalRefs GUARDED_BY(mRenderingMutex); + // Cache of GL textures that we'll store per GraphicBuffer ID, sliced by GPU context. std::unordered_map> mTextureCache GUARDED_BY(mRenderingMutex); std::unordered_map> diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 51ef088a25..308c5ffa9f 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -42,15 +42,12 @@ public: virtual void primeCache() override{}; virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; - virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; - virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; - virtual bool isProtected() const override { return false; } // mInProtectedContext; } virtual bool supportsProtectedContent() const override { return false; }; virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; }; virtual status_t drawLayers(const DisplaySettings& /*display*/, const std::vector& /*layers*/, - const sp& /*buffer*/, + const std::shared_ptr& /*buffer*/, const bool /*useFramebufferCache*/, base::unique_fd&& /*bufferFence*/, base::unique_fd* /*drawFence*/) override { @@ -60,6 +57,11 @@ public: virtual int getContextPriority() override { return 0; } virtual void assertShadersCompiled(int numShaders) {} virtual int reportShadersCompiled() { return 0; } + +protected: + virtual void mapExternalTextureBuffer(const sp& /*buffer*/, + bool /*isRenderable*/) override; + virtual void unmapExternalTextureBuffer(const sp& /*buffer*/) override; }; } // namespace skia diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 7846156383..d63c88bc02 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -160,27 +161,42 @@ public: class RenderEngineTest : public ::testing::TestWithParam> { public: - static sp allocateDefaultBuffer() { - return new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, - "output"); + std::shared_ptr allocateDefaultBuffer() { + return std::make_shared< + renderengine:: + ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, + DEFAULT_DISPLAY_HEIGHT, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "output"), + *mRE, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); } // Allocates a 1x1 buffer to fill with a solid color - static sp allocateSourceBuffer(uint32_t width, uint32_t height) { - return new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_TEXTURE, - "input"); + std::shared_ptr allocateSourceBuffer(uint32_t width, + uint32_t height) { + return std::make_shared< + renderengine:: + ExternalTexture>(new GraphicBuffer(width, height, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_TEXTURE, + "input"), + *mRE, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); } RenderEngineTest() { 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()); - mBuffer = allocateDefaultBuffer(); } ~RenderEngineTest() { @@ -211,20 +227,21 @@ public: } uint8_t* pixels; - mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); file << "P6\n"; - file << mBuffer->getWidth() << "\n"; - file << mBuffer->getHeight() << "\n"; + file << mBuffer->getBuffer()->getWidth() << "\n"; + file << mBuffer->getBuffer()->getHeight() << "\n"; file << 255 << "\n"; - std::vector outBuffer(mBuffer->getWidth() * mBuffer->getHeight() * 3); + std::vector outBuffer(mBuffer->getBuffer()->getWidth() * + mBuffer->getBuffer()->getHeight() * 3); auto outPtr = reinterpret_cast(outBuffer.data()); - for (int32_t j = 0; j < mBuffer->getHeight(); j++) { - const uint8_t* src = pixels + (mBuffer->getStride() * j) * 4; - for (int32_t i = 0; i < mBuffer->getWidth(); i++) { + for (int32_t j = 0; j < mBuffer->getBuffer()->getHeight(); j++) { + const uint8_t* src = pixels + (mBuffer->getBuffer()->getStride() * j) * 4; + for (int32_t i = 0; i < mBuffer->getBuffer()->getWidth(); i++) { // Only copy R, G and B components outPtr[0] = src[0]; outPtr[1] = src[1]; @@ -235,7 +252,7 @@ public: } } file.write(reinterpret_cast(outBuffer.data()), outBuffer.size()); - mBuffer->unlock(); + mBuffer->getBuffer()->unlock(); } void expectBufferColor(const Region& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { @@ -262,13 +279,13 @@ public: void expectBufferColor(const Rect& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, std::function colorCompare) { uint8_t* pixels; - mBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + mBuffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); int32_t maxFails = 10; int32_t fails = 0; for (int32_t j = 0; j < region.getHeight(); j++) { - const uint8_t* src = - pixels + (mBuffer->getStride() * (region.top + j) + region.left) * 4; + const uint8_t* src = pixels + + (mBuffer->getBuffer()->getStride() * (region.top + j) + region.left) * 4; for (int32_t i = 0; i < region.getWidth(); i++) { const uint8_t expected[4] = {r, g, b, a}; bool equal = colorCompare(src, expected); @@ -289,7 +306,7 @@ public: break; } } - mBuffer->unlock(); + mBuffer->getBuffer()->unlock(); } void expectAlpha(const Rect& rect, uint8_t a) { @@ -387,7 +404,6 @@ public: base::unique_fd fence; status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), &fence); - mCurrentBuffer = mBuffer; int fd = fence.release(); if (fd >= 0) { @@ -397,7 +413,7 @@ public: ASSERT_EQ(NO_ERROR, status); if (layers.size() > 0 && mGLESRE != nullptr) { - ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); + ASSERT_TRUE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); } } @@ -503,17 +519,11 @@ public: void initializeRenderEngine(); std::unique_ptr mRE; + std::shared_ptr mBuffer; // GLESRenderEngine for testing GLES-specific behavior. // Owened by mRE, but this is downcasted. renderengine::gl::GLESRenderEngine* mGLESRE = nullptr; - // Dumb hack to avoid NPE in the EGL driver: the GraphicBuffer needs to - // be freed *after* RenderEngine is destroyed, so that the EGL image is - // destroyed first. - sp mCurrentBuffer; - - sp mBuffer; - std::vector mTexNames; }; @@ -530,6 +540,7 @@ void RenderEngineTest::initializeRenderEngine() { } else { mRE = renderEngineFactory->createRenderEngine(); } + mBuffer = allocateDefaultBuffer(); } struct ColorSourceVariant { @@ -566,18 +577,18 @@ template struct BufferSourceVariant { static void fillColor(renderengine::LayerSettings& layer, half r, half g, half b, RenderEngineTest* fixture) { - sp buf = RenderEngineTest::allocateSourceBuffer(1, 1); + const auto buf = fixture->allocateSourceBuffer(1, 1); uint32_t texName; fixture->mRE->genTextures(1, &texName); fixture->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); - for (int32_t j = 0; j < buf->getHeight(); j++) { - uint8_t* iter = pixels + (buf->getStride() * j) * 4; - for (int32_t i = 0; i < buf->getWidth(); i++) { + for (int32_t j = 0; j < buf->getBuffer()->getHeight(); j++) { + uint8_t* iter = pixels + (buf->getBuffer()->getStride() * j) * 4; + for (int32_t i = 0; i < buf->getBuffer()->getWidth(); i++) { iter[0] = uint8_t(r * 255); iter[1] = uint8_t(g * 255); iter[2] = uint8_t(b * 255); @@ -586,7 +597,7 @@ struct BufferSourceVariant { } } - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1012,14 +1023,14 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; // Here will allocate a checker board texture, but transform texture // coordinates so that only the upper left is applied. - sp buf = allocateSourceBuffer(2, 2); + const auto buf = allocateSourceBuffer(2, 2); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); // Red top left, Green top right, Blue bottom left, Black bottom right pixels[0] = 255; pixels[1] = 0; @@ -1033,7 +1044,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { pixels[9] = 0; pixels[10] = 255; pixels[11] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1061,19 +1072,19 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - sp buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1100,19 +1111,19 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { std::vector layers; renderengine::LayerSettings layer; - sp buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); uint32_t texName; RenderEngineTest::mRE->genTextures(1, &texName); this->mTexNames.push_back(texName); uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 255; pixels[1] = 0; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); layer.source.buffer.buffer = buf; layer.source.buffer.textureName = texName; @@ -1233,8 +1244,7 @@ TEST_P(RenderEngineTest, drawLayers_noLayersToDraw) { } TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { - const auto& renderEngineFactory = GetParam(); - mRE = renderEngineFactory->createRenderEngine(); + initializeRenderEngine(); renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1295,7 +1305,6 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputFence) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd(), nullptr); - mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1323,9 +1332,8 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { layers.push_back(&layer); status_t status = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd(), nullptr); - mCurrentBuffer = mBuffer; ASSERT_EQ(NO_ERROR, status); - ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getId())); + ASSERT_FALSE(mGLESRE->isFramebufferImageCachedForTesting(mBuffer->getBuffer()->getId())); expectBufferColor(fullscreenRect(), 255, 0, 0, 255); } @@ -1574,98 +1582,6 @@ TEST_P(RenderEngineTest, drawLayers_clearRegion) { clearRegion(); } -TEST_P(RenderEngineTest, drawLayers_fillsBufferAndCachesImages) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - renderengine::DisplaySettings settings; - settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - settings.physicalDisplay = fullscreenRect(); - settings.clip = fullscreenRect(); - - std::vector layers; - - renderengine::LayerSettings layer; - layer.geometry.boundaries = fullscreenRect().toFloatRect(); - BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); - - layers.push_back(&layer); - invokeDraw(settings, layers); - uint64_t bufferId = layer.source.buffer.buffer->getId(); - EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); - std::shared_ptr barrier = - mGLESRE->unbindExternalTextureBufferForTesting(bufferId); - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); - EXPECT_EQ(NO_ERROR, barrier->result); -} - -TEST_P(RenderEngineTest, cacheExternalBuffer_withNullBuffer) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - std::shared_ptr barrier = - mGLESRE->cacheExternalTextureBufferForTesting(nullptr); - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_TRUE(barrier->isOpen); - EXPECT_EQ(BAD_VALUE, barrier->result); -} - -TEST_P(RenderEngineTest, cacheExternalBuffer_cachesImages) { - const auto& renderEngineFactory = GetParam(); - - if (renderEngineFactory->type() != renderengine::RenderEngine::RenderEngineType::GLES) { - // GLES-specific test - return; - } - - initializeRenderEngine(); - - sp buf = allocateSourceBuffer(1, 1); - uint64_t bufferId = buf->getId(); - std::shared_ptr barrier = - mGLESRE->cacheExternalTextureBufferForTesting(buf); - { - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_EQ(NO_ERROR, barrier->result); - } - EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); - barrier = mGLESRE->unbindExternalTextureBufferForTesting(bufferId); - { - std::lock_guard lock(barrier->mutex); - ASSERT_TRUE(barrier->condition.wait_for(barrier->mutex, std::chrono::seconds(5), - [&]() REQUIRES(barrier->mutex) { - return barrier->isOpen; - })); - EXPECT_EQ(NO_ERROR, barrier->result); - } - EXPECT_FALSE(mGLESRE->isImageCachedForTesting(bufferId)); -} - TEST_P(RenderEngineTest, drawLayers_fillShadow_castsWithoutCasterLayer) { initializeRenderEngine(); @@ -1858,7 +1774,7 @@ TEST_P(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory sync_wait(fd, -1); } - uint64_t bufferId = layer.source.buffer.buffer->getId(); + uint64_t bufferId = layer.source.buffer.buffer->getBuffer()->getId(); uint32_t texName = layer.source.buffer.textureName; EXPECT_TRUE(mGLESRE->isImageCachedForTesting(bufferId)); EXPECT_EQ(bufferId, mGLESRE->getBufferIdForTextureNameForTesting(texName)); @@ -1966,16 +1882,16 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { // The next layer will overwrite redLayer with a GraphicBuffer that is green // applied with a translucent alpha. - auto buf = allocateSourceBuffer(1, 1); + const auto buf = allocateSourceBuffer(1, 1); { uint8_t* pixels; - buf->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - reinterpret_cast(&pixels)); + buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + reinterpret_cast(&pixels)); pixels[0] = 0; pixels[1] = 255; pixels[2] = 0; pixels[3] = 255; - buf->unlock(); + buf->getBuffer()->unlock(); } const renderengine::LayerSettings greenLayer{ diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index b093e88d4f..e3917cce09 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -162,15 +162,18 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; std::vector layers; - sp buffer = new GraphicBuffer(); + std::shared_ptr buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); base::unique_fd bufferFence; base::unique_fd drawFence; EXPECT_CALL(*mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings&, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { return NO_ERROR; }); + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 190662be16..c87a836de1 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -160,27 +160,28 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { resultFuture.wait(); } -void RenderEngineThreaded::cacheExternalTextureBuffer(const sp& buffer) { +void RenderEngineThreaded::mapExternalTextureBuffer(const sp& buffer, + bool isRenderable) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::cacheExternalTextureBuffer"); - instance.cacheExternalTextureBuffer(buffer); + ATRACE_NAME("REThreaded::mapExternalTextureBuffer"); + instance.mapExternalTextureBuffer(buffer, isRenderable); }); } mCondition.notify_one(); } -void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { +void RenderEngineThreaded::unmapExternalTextureBuffer(const sp& buffer) { // This function is designed so it can run asynchronously, so we do not need to wait // for the futures. { std::lock_guard lock(mThreadMutex); mFunctionCalls.push([=](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::unbindExternalTextureBuffer"); - instance.unbindExternalTextureBuffer(bufferId); + ATRACE_NAME("REThreaded::unmapExternalTextureBuffer"); + instance.unmapExternalTextureBuffer(buffer); }); } mCondition.notify_one(); @@ -242,7 +243,7 @@ bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, + const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) { diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 61ae9b8cf8..eb6098ed8d 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -48,8 +48,6 @@ public: void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; - void cacheExternalTextureBuffer(const sp& buffer) override; - void unbindExternalTextureBuffer(uint64_t bufferId) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -60,14 +58,19 @@ public: status_t drawLayers(const DisplaySettings& display, const std::vector& layers, - const sp& buffer, const bool useFramebufferCache, - base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + const std::shared_ptr& buffer, + const bool useFramebufferCache, base::unique_fd&& bufferFence, + base::unique_fd* drawFence) override; void cleanFramebufferCache() override; int getContextPriority() override; bool supportsBackgroundBlur() override; void onPrimaryDisplaySizeChanged(ui::Size size) override; +protected: + void mapExternalTextureBuffer(const sp& buffer, bool isRenderable) override; + void unmapExternalTextureBuffer(const sp& buffer) override; + private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 12f63dbbf1..d243989a34 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -188,7 +188,7 @@ std::optional BufferLayer::prepareCli const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const bool bufferCanBeUsedAsHwTexture = - mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; + mBufferInfo.mBuffer->getBuffer()->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE; compositionengine::LayerFE::LayerSettings& layer = *result; if (blackOutLayer || !bufferCanBeUsedAsHwTexture) { ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable", @@ -213,7 +213,7 @@ std::optional BufferLayer::prepareCli ? mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel : defaultMaxContentLuminance; layer.frameNumber = mCurrentFrameNumber; - layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0; + layer.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()->getId() : 0; const bool useFiltering = targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering(); @@ -314,7 +314,7 @@ void BufferLayer::preparePerFrameCompositionState() { : Hwc2::IComposerClient::Composition::DEVICE; } - compositionState->buffer = mBufferInfo.mBuffer; + compositionState->buffer = mBufferInfo.mBuffer->getBuffer(); compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mBufferInfo.mBufferSlot; @@ -442,7 +442,7 @@ bool BufferLayer::onPostComposition(const DisplayDevice* display, void BufferLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = - !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->getBuffer()->format; mBufferInfo.mFrameLatencyNeeded = true; } @@ -539,10 +539,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, } 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)) { + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); + if (bufWidth != uint32_t(oldBufferInfo.mBuffer->getBuffer()->width) || + bufHeight != uint32_t(oldBufferInfo.mBuffer->getBuffer()->height)) { recomputeVisibleRegions = true; } } @@ -563,8 +563,8 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - const sp& buffer(mBufferInfo.mBuffer); - return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); + return (mBufferInfo.mBuffer != nullptr) && + (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED); } // As documented in libhardware header, formats in the range @@ -651,8 +651,8 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect::INVALID_RECT; } - uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -683,8 +683,8 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return parentBounds; } - uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); - uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getBuffer()->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getBuffer()->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -726,7 +726,7 @@ Rect BufferLayer::getBufferCrop() const { return mBufferInfo.mCrop; } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mBufferInfo.mBuffer->getBounds(); + return mBufferInfo.mBuffer->getBuffer()->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -771,12 +771,14 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { } sp BufferLayer::getBuffer() const { - return mBufferInfo.mBuffer; + return mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() : nullptr; } void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { - GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, - mBufferInfo.mTransform, filteringEnabled); + GLConsumer::computeTransformMatrix(outMatrix, + mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer() + : nullptr, + mBufferInfo.mCrop, mBufferInfo.mTransform, filteringEnabled); } void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 0a5235aa08..cd3d80e809 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -132,7 +132,7 @@ protected: PixelFormat mPixelFormat{PIXEL_FORMAT_NONE}; bool mTransformToDisplayInverse{false}; - sp mBuffer; + std::shared_ptr mBuffer; int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; bool mFrameLatencyNeeded{false}; diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index 69d2d11a4d..96b22478ab 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -167,7 +166,7 @@ void BufferLayerConsumer::setReleaseFence(const sp& fence) { } auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer - : mCurrentTextureBuffer->graphicBuffer(); + : mCurrentTextureBuffer->getBuffer(); auto err = addReleaseFence(slot, buffer, fence); if (err != OK) { BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err); @@ -206,9 +205,11 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres // before, so we need to clean up old references. if (item->mGraphicBuffer != nullptr) { std::lock_guard lock(mImagesMutex); - if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->graphicBuffer() == nullptr || - mImages[item->mSlot]->graphicBuffer()->getId() != item->mGraphicBuffer->getId()) { - mImages[item->mSlot] = std::make_shared(item->mGraphicBuffer, mRE); + if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr || + mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) { + mImages[item->mSlot] = std::make_shared< + renderengine::ExternalTexture>(item->mGraphicBuffer, mRE, + renderengine::ExternalTexture::Usage::READABLE); } } @@ -222,8 +223,8 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, int slot = item.mSlot; BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture, - (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->graphicBuffer() != nullptr) - ? mCurrentTextureBuffer->graphicBuffer()->handle + (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr) + ? mCurrentTextureBuffer->getBuffer()->handle : 0, slot, mSlots[slot].mGraphicBuffer->handle); @@ -231,7 +232,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, // releaseBufferLocked() if we're in shared buffer mode and both buffers are // the same. - std::shared_ptr nextTextureBuffer; + std::shared_ptr nextTextureBuffer; { std::lock_guard lock(mImagesMutex); nextTextureBuffer = mImages[slot]; @@ -241,7 +242,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) { if (pendingRelease == nullptr) { status_t status = - releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->graphicBuffer()); + releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer()); if (status < NO_ERROR) { BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status), status); @@ -250,7 +251,7 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item, } } else { pendingRelease->currentTexture = mCurrentTexture; - pendingRelease->graphicBuffer = mCurrentTextureBuffer->graphicBuffer(); + pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer(); pendingRelease->isPending = true; } } @@ -301,14 +302,14 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) { void BufferLayerConsumer::computeCurrentTransformMatrixLocked() { BLC_LOGV("computeCurrentTransformMatrixLocked"); - if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->graphicBuffer() == nullptr) { + if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->getBuffer() == nullptr) { BLC_LOGD("computeCurrentTransformMatrixLocked: " "mCurrentTextureBuffer is nullptr"); } GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer == nullptr ? nullptr - : mCurrentTextureBuffer->graphicBuffer(), + : mCurrentTextureBuffer->getBuffer(), getCurrentCropLocked(), mCurrentTransform, mFilteringEnabled); } @@ -360,7 +361,8 @@ int BufferLayerConsumer::getCurrentApi() const { return mCurrentApi; } -sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* outFence) const { +std::shared_ptr BufferLayerConsumer::getCurrentBuffer( + int* outSlot, sp* outFence) const { Mutex::Autolock lock(mMutex); if (outSlot != nullptr) { @@ -371,7 +373,7 @@ sp BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp* *outFence = mCurrentFence; } - return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer->graphicBuffer(); + return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer; } Rect BufferLayerConsumer::getCurrentCrop() const { @@ -456,10 +458,12 @@ void BufferLayerConsumer::onSidebandStreamChanged() { void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) { std::lock_guard lock(mImagesMutex); - const std::shared_ptr& oldImage = mImages[item.mSlot]; - if (oldImage == nullptr || oldImage->graphicBuffer() == nullptr || - oldImage->graphicBuffer()->getId() != item.mGraphicBuffer->getId()) { - mImages[item.mSlot] = std::make_shared(item.mGraphicBuffer, mRE); + const std::shared_ptr& oldImage = mImages[item.mSlot]; + if (oldImage == nullptr || oldImage->getBuffer() == nullptr || + oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) { + mImages[item.mSlot] = std::make_shared< + renderengine::ExternalTexture>(item.mGraphicBuffer, mRE, + renderengine::ExternalTexture::Usage::READABLE); } } } @@ -499,22 +503,6 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const ConsumerBase::dumpLocked(result, prefix); } - -BufferLayerConsumer::Image::Image(const sp& graphicBuffer, - renderengine::RenderEngine& engine) - : mGraphicBuffer(graphicBuffer), mRE(engine) { - if (graphicBuffer != nullptr && (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED)) { - return; - } - mRE.cacheExternalTextureBuffer(mGraphicBuffer); -} - -BufferLayerConsumer::Image::~Image() { - if (mGraphicBuffer != nullptr) { - ALOGV("Destroying buffer: %" PRId64, mGraphicBuffer->getId()); - mRE.unbindExternalTextureBuffer(mGraphicBuffer->getId()); - } -} }; // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h index dd39214aff..9ed80b46bd 100644 --- a/services/surfaceflinger/BufferLayerConsumer.h +++ b/services/surfaceflinger/BufferLayerConsumer.h @@ -21,12 +21,11 @@ #include #include #include - +#include #include #include #include #include - #include #include #include @@ -39,7 +38,6 @@ class String8; namespace renderengine { class RenderEngine; -class Image; } // namespace renderengine /* @@ -153,7 +151,8 @@ public: // When outSlot is not nullptr, the current buffer slot index is also // returned. Simiarly, when outFence is not nullptr, the current output // fence is returned. - sp getCurrentBuffer(int* outSlot = nullptr, sp* outFence = nullptr) const; + std::shared_ptr getCurrentBuffer( + int* outSlot = nullptr, sp* outFence = nullptr) const; // getCurrentCrop returns the cropping rectangle of the current buffer. Rect getCurrentCrop() const; @@ -258,7 +257,7 @@ private: // mCurrentTextureBuffer is the buffer containing the current texture. It's // possible that this buffer is not associated with any buffer slot, so we // must track it separately in order to support the getCurrentBuffer method. - std::shared_ptr mCurrentTextureBuffer; + std::shared_ptr mCurrentTextureBuffer; // mCurrentCrop is the crop rectangle that applies to the current texture. // It gets set each time updateTexImage is called. @@ -337,7 +336,8 @@ private: int mCurrentTexture; // Shadow buffer cache for cleaning up renderengine references. - std::shared_ptr mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); + std::shared_ptr + mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex); // Separate mutex guarding the shadow buffer cache. // mImagesMutex can be manipulated with binder threads (e.g. onBuffersAllocated) diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fa9cecf787..ac2edbe717 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -71,14 +71,8 @@ BufferStateLayer::~BufferStateLayer() { // 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. - auto& engine(mFlinger->getRenderEngine()); - const uint64_t bufferId = mBufferInfo.mBuffer->getId(); - engine.unbindExternalTextureBuffer(bufferId); - callReleaseBufferCallback(mDrawingState.releaseBufferListener, mBufferInfo.mBuffer, - mBufferInfo.mFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mBufferInfo.mBuffer->getBuffer(), mBufferInfo.mFence); } } @@ -344,8 +338,9 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -bool BufferStateLayer::setBuffer(const sp& buffer, const sp& acquireFence, - nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, +bool BufferStateLayer::setBuffer(const std::shared_ptr& buffer, + const sp& acquireFence, nsecs_t postTime, + nsecs_t desiredPresentTime, bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& releaseBufferListener) { @@ -353,12 +348,14 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spgetBuffer() != mDrawingState.buffer->getBuffer()) { // If mCurrentState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mCurrentState.releaseBufferListener, mCurrentState.buffer, + callReleaseBufferCallback(mCurrentState.releaseBufferListener, + mCurrentState.buffer->getBuffer(), mCurrentState.acquireFence); decrementPendingBufferCount(); if (mCurrentState.bufferSurfaceFrameTX != nullptr) { @@ -396,8 +393,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spgetId(); + if (buffer && dequeueTime && *dequeueTime != 0) { + const uint64_t bufferId = buffer->getBuffer()->getId(); mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime, FrameTracer::FrameEvent::DEQUEUE); @@ -405,8 +402,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, const spwidth; - mCurrentState.height = mCurrentState.buffer->height; + mCurrentState.width = mCurrentState.buffer->getBuffer()->getWidth(); + mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight(); return true; } @@ -655,7 +652,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const int32_t layerId = getSequence(); - const uint64_t bufferId = mDrawingState.buffer->getId(); + const uint64_t bufferId = mDrawingState.buffer->getBuffer()->getId(); const uint64_t frameNumber = mDrawingState.frameNumber; const auto acquireFence = std::make_shared(mDrawingState.acquireFence); mFlinger->mTimeStats->setAcquireFence(layerId, frameNumber, acquireFence); @@ -689,7 +686,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (s.buffer != mBufferInfo.mBuffer) { + if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { decrementPendingBufferCount(); } @@ -808,13 +805,13 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { Rect BufferStateLayer::computeCrop(const State& s) { if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBounds(); + return s.buffer->getBuffer()->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(); + uint32_t bufferWidth = s.buffer->getBuffer()->getWidth(); + uint32_t bufferHeight = s.buffer->getBuffer()->getHeight(); if (bufferHeight <= std::numeric_limits::max() && bufferWidth <= std::numeric_limits::max()) { crop.right = std::min(crop.right, static_cast(bufferWidth)); @@ -822,7 +819,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } if (!crop.isValid()) { // Crop rect is out of bounds, return whole buffer - return s.buffer->getBounds(); + return s.buffer->getBuffer()->getBounds(); } return crop; } @@ -844,8 +841,8 @@ bool BufferStateLayer::bufferNeedsFiltering() const { return false; } - uint32_t bufferWidth = s.buffer->width; - uint32_t bufferHeight = s.buffer->height; + uint32_t bufferWidth = s.buffer->getBuffer()->width; + uint32_t bufferHeight = s.buffer->getBuffer()->height; // Undo any transformations on the buffer and return the result. if (s.bufferTransform & ui::Transform::ROT_90) { @@ -872,14 +869,16 @@ void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) { ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers); } -void BufferStateLayer::bufferMayChange(sp& newBuffer) { - if (mDrawingState.buffer != nullptr && mDrawingState.buffer != mBufferInfo.mBuffer && - newBuffer != mDrawingState.buffer) { +void BufferStateLayer::bufferMayChange(const sp& newBuffer) { + if (mDrawingState.buffer != nullptr && + (!mBufferInfo.mBuffer || + mDrawingState.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) && + newBuffer != mDrawingState.buffer->getBuffer()) { // If we are about to update mDrawingState.buffer but it has not yet latched // then we will drop a buffer and should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mDrawingState.releaseBufferListener, mDrawingState.buffer, - mDrawingState.acquireFence); + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence); decrementPendingBufferCount(); } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 24e0ad290f..4171092b58 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -62,9 +62,9 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const sp& buffer, const sp& acquireFence, nsecs_t postTime, - nsecs_t desiredPresentTime, bool isAutoTimestamp, - const client_cache_t& clientCacheId, uint64_t frameNumber, + bool setBuffer(const std::shared_ptr& buffer, + const sp& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime, + bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber, std::optional dequeueTime, const FrameTimelineInfo& info, const sp& transactionListener) override; bool setAcquireFence(const sp& fence) override; @@ -100,7 +100,7 @@ public: // See mPendingBufferTransactions void decrementPendingBufferCount(); - void bufferMayChange(sp& newBuffer) override; + void bufferMayChange(const sp& newBuffer) override; std::atomic* getPendingBufferCounter() override { return &mPendingBufferTransactions; } std::string getPendingBufferCounterName() override { return mBlastTransactionName; } diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index 44b33ef43d..f310738423 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -102,7 +102,12 @@ bool ClientCache::add(const client_cache_t& cacheId, const sp& bu return false; } - processBuffers[id].buffer = buffer; + LOG_ALWAYS_FATAL_IF(mRenderEngine == nullptr, + "Attempted to build the ClientCache before a RenderEngine instance was " + "ready!"); + processBuffers[id].buffer = std::make_shared< + renderengine::ExternalTexture>(buffer, *mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE); return true; } @@ -132,7 +137,7 @@ void ClientCache::erase(const client_cache_t& cacheId) { } } -sp ClientCache::get(const client_cache_t& cacheId) { +std::shared_ptr ClientCache::get(const client_cache_t& cacheId) { std::lock_guard lock(mMutex); ClientCacheBuffer* buf = nullptr; @@ -213,8 +218,8 @@ void ClientCache::dump(std::string& result) { auto &buffers = i.second.second; for (auto& [id, clientCacheBuffer] : buffers) { StringAppendF(&result, "\t ID: %d, Width/Height: %d,%d\n", (int)id, - (int)clientCacheBuffer.buffer->getWidth(), - (int)clientCacheBuffer.buffer->getHeight()); + (int)clientCacheBuffer.buffer->getBuffer()->getWidth(), + (int)clientCacheBuffer.buffer->getBuffer()->getHeight()); } } } diff --git a/services/surfaceflinger/ClientCache.h b/services/surfaceflinger/ClientCache.h index 0d597c8e05..a9b8177d70 100644 --- a/services/surfaceflinger/ClientCache.h +++ b/services/surfaceflinger/ClientCache.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,11 @@ public: bool add(const client_cache_t& cacheId, const sp& buffer); void erase(const client_cache_t& cacheId); - sp get(const client_cache_t& cacheId); + std::shared_ptr get(const client_cache_t& cacheId); + + // Always called immediately after setup. Will be set to non-null, and then should never be + // called again. + void setRenderEngine(renderengine::RenderEngine* renderEngine) { mRenderEngine = renderEngine; } void removeProcess(const wp& processToken); @@ -59,7 +64,7 @@ private: std::mutex mMutex; struct ClientCacheBuffer { - sp buffer; + std::shared_ptr buffer; std::set> recipients; }; std::map /*caching process*/, @@ -73,6 +78,7 @@ private: }; sp mDeathRecipient; + renderengine::RenderEngine* mRenderEngine = nullptr; bool getBuffer(const client_cache_t& cacheId, ClientCacheBuffer** outClientCacheBuffer) REQUIRES(mMutex); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h index f680460242..daee83bd2c 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h @@ -16,15 +16,16 @@ #pragma once -#include -#include - +#include #include #include #include #include #include +#include +#include + namespace android { class GraphicBuffer; @@ -80,7 +81,8 @@ public: virtual void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) = 0; // Allocates a buffer as scratch space for GPU composition - virtual sp dequeueBuffer(base::unique_fd* bufferFence) = 0; + virtual std::shared_ptr dequeueBuffer( + base::unique_fd* bufferFence) = 0; // Queues the drawn buffer for consumption by HWC. readyFence is the fence // which will fire when the buffer is ready for consumption. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h index a1230b3c4d..a8d372c562 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurfaceCreationArgs.h @@ -45,6 +45,8 @@ struct RenderSurfaceCreationArgs { // The DisplaySurface for this surface sp displaySurface; + + size_t maxTextureCacheSize; }; /** @@ -81,6 +83,11 @@ public: return *this; } + RenderSurfaceCreationArgsBuilder& setMaxTextureCacheSize(size_t maxTextureCacheSize) { + mArgs.maxTextureCacheSize = maxTextureCacheSize; + return *this; + } + private: RenderSurfaceCreationArgs mArgs; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 48a54d6c66..c61ec5991b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -89,7 +89,7 @@ struct OutputLayerCompositionState { // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { - sp buffer = nullptr; + std::shared_ptr buffer = nullptr; sp acquireFence = nullptr; Rect displayFrame = {}; ui::Dataspace dataspace{ui::Dataspace::UNKNOWN}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h index 5127a6f314..a8a538003e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h @@ -16,12 +16,16 @@ #pragma once -#include - #include #include #include +#include +#include + +#include "renderengine/ExternalTexture.h" +#include "renderengine/RenderEngine.h" + struct ANativeWindow; namespace android { @@ -54,7 +58,8 @@ public: void setProtected(bool useProtected) override; status_t beginFrame(bool mustRecompose) override; void prepareFrame(bool usesClientComposition, bool usesDeviceComposition) override; - sp dequeueBuffer(base::unique_fd* bufferFence) override; + std::shared_ptr dequeueBuffer( + base::unique_fd* bufferFence) override; void queueBuffer(base::unique_fd readyFence) override; void onPresentDisplayCompleted() override; void flip() override; @@ -66,7 +71,7 @@ public: // Testing void setPageFlipCountForTest(std::uint32_t); void setSizeForTest(const ui::Size&); - sp& mutableGraphicBufferForTest(); + std::shared_ptr& mutableTextureForTest(); base::unique_fd& mutableBufferReadyForTest(); private: @@ -75,10 +80,13 @@ private: // ANativeWindow being rendered into const sp mNativeWindow; - // Current buffer being rendered into - sp mGraphicBuffer; + + std::vector> mTextureCache; + // Current texture being rendered into + std::shared_ptr mTexture; const sp mDisplaySurface; ui::Size mSize; + const size_t mMaxTextureCacheSize; bool mProtected{false}; std::uint32_t mPageFlipCount{0}; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index c5d03a7218..53f4a30fb8 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -66,7 +66,7 @@ public: const Rect& getBounds() const { return mBounds; } const Region& getVisibleRegion() const { return mVisibleRegion; } size_t getAge() const { return mAge; } - const sp& getBuffer() const { return mTexture.getBuffer(); } + const std::shared_ptr& getBuffer() const { return mTexture; } const sp& getDrawFence() const { return mDrawFence; } const ProjectionSpace& getOutputSpace() const { return mOutputSpace; } ui::Dataspace getOutputDataspace() const { return mOutputDataspace; } @@ -87,7 +87,7 @@ public: void setLastUpdate(std::chrono::steady_clock::time_point now) { mLastUpdate = now; } void append(const CachedSet& other) { - mTexture.setBuffer(nullptr, nullptr); + mTexture = nullptr; mOutputDataspace = ui::Dataspace::UNKNOWN; mDrawFence = nullptr; @@ -115,31 +115,7 @@ private: Region mVisibleRegion; size_t mAge = 0; - class Texture { - public: - ~Texture() { setBuffer(nullptr, nullptr); } - - void setBuffer(const sp& buffer, renderengine::RenderEngine* re) { - if (mRE && mBuffer) { - mRE->unbindExternalTextureBuffer(mBuffer->getId()); - } - - mBuffer = buffer; - mRE = re; - - if (mRE && mBuffer) { - mRE->cacheExternalTextureBuffer(mBuffer); - } - } - - const sp& getBuffer() const { return mBuffer; } - - private: - sp mBuffer = nullptr; - renderengine::RenderEngine* mRE = nullptr; - }; - - Texture mTexture; + std::shared_ptr mTexture; sp mDrawFence; ProjectionSpace mOutputSpace; ui::Dataspace mOutputDataspace; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h index a0cae6fcbb..fe858c2817 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h @@ -39,7 +39,7 @@ public: MOCK_METHOD1(setBufferPixelFormat, void(ui::PixelFormat)); MOCK_METHOD1(beginFrame, status_t(bool mustRecompose)); MOCK_METHOD2(prepareFrame, void(bool, bool)); - MOCK_METHOD1(dequeueBuffer, sp(base::unique_fd*)); + MOCK_METHOD1(dequeueBuffer, std::shared_ptr(base::unique_fd*)); MOCK_METHOD1(queueBuffer, void(base::unique_fd)); MOCK_METHOD0(onPresentDisplayCompleted, void()); MOCK_METHOD0(flip, void()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 3ac5433457..3468b204fc 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,8 +14,7 @@ * limitations under the License. */ -#include - +#include #include #include #include @@ -29,7 +28,9 @@ #include #include -#include +#include + +#include "renderengine/ExternalTexture.h" // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -715,11 +716,11 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr bool skipLayer = false; if (layer->getState().overrideInfo.buffer != nullptr) { if (previousOverride != nullptr && - layer->getState().overrideInfo.buffer == previousOverride) { + layer->getState().overrideInfo.buffer->getBuffer() == previousOverride) { ALOGV("Skipping redundant buffer"); skipLayer = true; } - previousOverride = layer->getState().overrideInfo.buffer; + previousOverride = layer->getState().overrideInfo.buffer->getBuffer(); } const bool includeGeometry = refreshArgs.updatingGeometryThisFrame; @@ -978,14 +979,15 @@ std::optional Output::composeSurfaces( } base::unique_fd fd; - sp buf; + + std::shared_ptr tex; // If we aren't doing client composition on this output, but do have a // flipClientTarget request for this frame on this output, we still need to // dequeue a buffer. if (hasClientComposition || outputState.flipClientTarget) { - buf = mRenderSurface->dequeueBuffer(&fd); - if (buf == nullptr) { + tex = mRenderSurface->dequeueBuffer(&fd); + if (tex == nullptr) { ALOGW("Dequeuing buffer for display [%s] failed, bailing out of " "client composition for this frame", mName.c_str()); @@ -1030,13 +1032,14 @@ std::optional Output::composeSurfaces( // Check if the client composition requests were rendered into the provided graphic buffer. If // so, we can reuse the buffer and avoid client composition. if (mClientCompositionRequestCache) { - if (mClientCompositionRequestCache->exists(buf->getId(), clientCompositionDisplay, + if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(), + clientCompositionDisplay, clientCompositionLayers)) { outputCompositionState.reusedClientComposition = true; setExpensiveRenderingExpected(false); return readyFence; } - mClientCompositionRequestCache->add(buf->getId(), clientCompositionDisplay, + mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay, clientCompositionLayers); } @@ -1069,12 +1072,12 @@ std::optional Output::composeSurfaces( // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerStackInternal; status_t status = - renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf, + renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, useFramebufferCache, std::move(fd), &readyFence); if (status != NO_ERROR && mClientCompositionRequestCache) { // If rendering was not successful, remove the request from the cache. - mClientCompositionRequestCache->remove(buf->getId()); + mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); } auto& timeStats = getCompositionEngine().getTimeStats(); @@ -1151,9 +1154,9 @@ std::vector Output::generateClientCompositionRequests( std::vector results; if (layer->getState().overrideInfo.buffer != nullptr) { - if (layer->getState().overrideInfo.buffer != previousOverrideBuffer) { + if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) { results = layer->getOverrideCompositionList(); - previousOverrideBuffer = layer->getState().overrideInfo.buffer; + previousOverrideBuffer = layer->getState().overrideInfo.buffer->getBuffer(); ALOGV("Replacing [%s] with override in RE", layer->getLayerFE().getDebugName()); } else { ALOGV("Skipping redundant override buffer for [%s] in RE", diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index f640f85bca..9ca8914deb 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -537,7 +537,7 @@ void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, sp buffer = outputIndependentState.buffer; sp acquireFence = outputIndependentState.acquireFence; if (getState().overrideInfo.buffer != nullptr) { - buffer = getState().overrideInfo.buffer; + buffer = getState().overrideInfo.buffer->getBuffer(); acquireFence = getState().overrideInfo.acquireFence; } @@ -699,7 +699,7 @@ std::vector OutputLayer::getOverrideCompositionList() co settings.geometry = renderengine::Geometry{ .boundaries = boundaries.toFloatRect(), }; - settings.bufferId = getState().overrideInfo.buffer->getId(); + settings.bufferId = getState().overrideInfo.buffer->getBuffer()->getId(); settings.source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = getState().overrideInfo.buffer, diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 3bef77dde1..ef50870615 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -25,8 +25,8 @@ #include #include #include - #include +#include #include #include #include @@ -63,7 +63,8 @@ RenderSurface::RenderSurface(const CompositionEngine& compositionEngine, Display mDisplay(display), mNativeWindow(args.nativeWindow), mDisplaySurface(args.displaySurface), - mSize(args.displayWidth, args.displayHeight) { + mSize(args.displayWidth, args.displayHeight), + mMaxTextureCacheSize(args.maxTextureCacheSize) { LOG_ALWAYS_FATAL_IF(!mNativeWindow); } @@ -146,7 +147,8 @@ void RenderSurface::prepareFrame(bool usesClientComposition, bool usesDeviceComp } } -sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { +std::shared_ptr RenderSurface::dequeueBuffer( + base::unique_fd* bufferFence) { ATRACE_CALL(); int fd = -1; ANativeWindowBuffer* buffer = nullptr; @@ -158,16 +160,41 @@ sp RenderSurface::dequeueBuffer(base::unique_fd* bufferFence) { mDisplay.getName().c_str(), result); // Return fast here as we can't do much more - any rendering we do // now will just be wrong. - return mGraphicBuffer; + return mTexture; + } + + ALOGW_IF(mTexture != nullptr, "Clobbering a non-null pointer to a buffer [%p].", + mTexture->getBuffer()->getNativeBuffer()->handle); + + sp newBuffer = GraphicBuffer::from(buffer); + + std::shared_ptr texture; + + for (auto it = mTextureCache.begin(); it != mTextureCache.end(); it++) { + const auto& cachedTexture = *it; + if (cachedTexture->getBuffer()->getId() == newBuffer->getId()) { + texture = cachedTexture; + mTextureCache.erase(it); + break; + } } - ALOGW_IF(mGraphicBuffer != nullptr, "Clobbering a non-null pointer to a buffer [%p].", - mGraphicBuffer->getNativeBuffer()->handle); - mGraphicBuffer = GraphicBuffer::from(buffer); + if (texture) { + mTexture = texture; + } else { + mTexture = std::make_shared< + renderengine::ExternalTexture>(GraphicBuffer::from(buffer), + mCompositionEngine.getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); + } + mTextureCache.push_back(mTexture); + if (mTextureCache.size() > mMaxTextureCacheSize) { + mTextureCache.erase(mTextureCache.begin()); + } *bufferFence = base::unique_fd(fd); - return mGraphicBuffer; + return mTexture; } void RenderSurface::queueBuffer(base::unique_fd readyFence) { @@ -177,24 +204,24 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { // hasFlipClientTargetRequest could return true even if we haven't // dequeued a buffer before. Try dequeueing one if we don't have a // buffer ready. - if (mGraphicBuffer == nullptr) { + if (mTexture == nullptr) { ALOGI("Attempting to queue a client composited buffer without one " "previously dequeued for display [%s]. Attempting to dequeue " "a scratch buffer now", mDisplay.getName().c_str()); - // We shouldn't deadlock here, since mGraphicBuffer == nullptr only + // We shouldn't deadlock here, since mTexture == nullptr only // after a successful call to queueBuffer, or if dequeueBuffer has // never been called. base::unique_fd unused; dequeueBuffer(&unused); } - if (mGraphicBuffer == nullptr) { + if (mTexture == nullptr) { ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str()); } else { - status_t result = - mNativeWindow->queueBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), dup(readyFence)); + status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(), + mTexture->getBuffer()->getNativeBuffer(), + dup(readyFence)); if (result != NO_ERROR) { ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(), result); @@ -204,11 +231,12 @@ void RenderSurface::queueBuffer(base::unique_fd readyFence) { LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result); } else { mNativeWindow->cancelBuffer(mNativeWindow.get(), - mGraphicBuffer->getNativeBuffer(), dup(readyFence)); + mTexture->getBuffer()->getNativeBuffer(), + dup(readyFence)); } } - mGraphicBuffer = nullptr; + mTexture = nullptr; } } @@ -256,8 +284,8 @@ void RenderSurface::setSizeForTest(const ui::Size& size) { mSize = size; } -sp& RenderSurface::mutableGraphicBufferForTest() { - return mGraphicBuffer; +std::shared_ptr& RenderSurface::mutableTextureForTest() { + return mTexture; } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index dcb75556e3..9955e29f4a 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -130,7 +130,7 @@ bool CachedSet::hasBufferUpdate() const { } bool CachedSet::hasReadyBuffer() const { - return mTexture.getBuffer() != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; + return mTexture != nullptr && mDrawFence->getStatus() == Fence::Status::Signaled; } std::vector CachedSet::decompose() const { @@ -217,21 +217,27 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, sp buffer = new GraphicBuffer(static_cast(mBounds.getWidth()), static_cast(mBounds.getHeight()), HAL_PIXEL_FORMAT_RGBA_8888, 1, usageFlags); + const auto texture = std::make_shared< + renderengine::ExternalTexture>(buffer, renderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); LOG_ALWAYS_FATAL_IF(buffer->initCheck() != OK); base::unique_fd drawFence; - status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, buffer, false, - base::unique_fd(), &drawFence); + status_t result = renderEngine.drawLayers(displaySettings, layerSettingsPointers, texture, + false, base::unique_fd(), &drawFence); if (result == NO_ERROR) { - mTexture.setBuffer(buffer, &renderEngine); mDrawFence = new Fence(drawFence.release()); mOutputSpace = ProjectionSpace(ui::Size(outputState.framebufferSpace.bounds.getWidth(), outputState.framebufferSpace.bounds.getHeight()), mBounds); + mTexture = std::move(texture); mOutputSpace.orientation = outputState.framebufferSpace.orientation; mOutputDataspace = outputDataspace; mOrientation = orientation; + } else { + mTexture = nullptr; } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp index ad7555730d..3a2534b847 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp @@ -111,7 +111,12 @@ void Planner::reportFinalPlan( const GraphicBuffer* currentOverrideBuffer = nullptr; bool hasSkippedLayers = false; for (auto layer : layers) { - const GraphicBuffer* overrideBuffer = layer->getState().overrideInfo.buffer.get(); + if (!layer->getState().overrideInfo.buffer) { + continue; + } + + const GraphicBuffer* overrideBuffer = + layer->getState().overrideInfo.buffer->getBuffer().get(); if (overrideBuffer != nullptr && overrideBuffer == currentOverrideBuffer) { // Skip this layer since it is part of a previous cached set hasSkippedLayers = true; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 8a4d161289..4c3f4940cc 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -26,6 +26,7 @@ #include "MockHWC2.h" #include "MockHWComposer.h" #include "RegionMatcher.h" +#include "renderengine/mock/RenderEngine.h" namespace android::compositionengine { namespace { @@ -715,7 +716,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const HdrMetadata kHdrMetadata; static native_handle_t* kSidebandStreamHandle; static const sp kBuffer; - static const sp kOverrideBuffer; + std::shared_ptr kOverrideBuffer; static const sp kFence; static const sp kOverrideFence; static const std::string kLayerGenericMetadata1Key; @@ -724,6 +725,11 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { static const std::vector kLayerGenericMetadata2Value; OutputLayerWriteStateToHWCTest() { + kOverrideBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage:: + WRITEABLE); auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); @@ -839,6 +845,7 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { std::shared_ptr mHwcLayer{std::make_shared>()}; StrictMock mDisplayColorProfile; + renderengine::mock::RenderEngine mRenderEngine; }; const half4 OutputLayerWriteStateToHWCTest::kColor{81.f / 255.f, 82.f / 255.f, 83.f / 255.f, @@ -858,7 +865,6 @@ const HdrMetadata OutputLayerWriteStateToHWCTest::kHdrMetadata{{/* LightFlattena native_handle_t* OutputLayerWriteStateToHWCTest::kSidebandStreamHandle = reinterpret_cast(1031); const sp OutputLayerWriteStateToHWCTest::kBuffer; -const sp OutputLayerWriteStateToHWCTest::kOverrideBuffer = new GraphicBuffer(); const sp OutputLayerWriteStateToHWCTest::kFence; const sp OutputLayerWriteStateToHWCTest::kOverrideFence = new Fence(); const std::string OutputLayerWriteStateToHWCTest::kLayerGenericMetadata1Key = @@ -1023,7 +1029,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, includesOverrideInfoIfPresent) { kOverrideBufferTransform, kOverrideBlendMode, kOverrideAlpha); expectPerFrameCommonCalls(SimulateUnsupported::None, kOverrideDataspace, kOverrideVisibleRegion, kOverrideSurfaceDamage); - expectSetHdrMetadataAndBufferCalls(kOverrideBuffer, kOverrideFence); + expectSetHdrMetadataAndBufferCalls(kOverrideBuffer->getBuffer(), kOverrideFence); expectSetCompositionTypeCall(Hwc2::IComposerClient::Composition::DEVICE); mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 5f0b0eea15..e80100cc6e 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,8 +14,6 @@ * limitations under the License. */ -#include - #include #include #include @@ -31,9 +29,12 @@ #include #include +#include + #include "CallOrderStateMachineHelper.h" #include "MockHWC2.h" #include "RegionMatcher.h" +#include "renderengine/ExternalTexture.h" namespace android::compositionengine { namespace { @@ -2960,7 +2961,10 @@ struct OutputComposeSurfacesTest : public testing::Test { mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock(); mock::RenderSurface* mRenderSurface = new StrictMock(); StrictMock mOutput; - sp mOutputBuffer = new GraphicBuffer(); + std::shared_ptr mOutputBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); std::optional mReadyFence; }; @@ -3173,7 +3177,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _)) .WillRepeatedly(Return()); - sp otherOutputBuffer = new GraphicBuffer(); + const auto otherOutputBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index 5ef5d7b5cb..9aeb290eb5 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -15,6 +15,8 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues +#include "renderengine/ExternalTexture.h" +#include "ui/GraphicBuffer.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wextra" @@ -239,9 +241,9 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { DoAll(SetArgPointee<0>(buffer.get()), SetArgPointee<1>(-1), Return(NO_ERROR))); base::unique_fd fence; - EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence).get()); + EXPECT_EQ(buffer.get(), mSurface.dequeueBuffer(&fence)->getBuffer().get()); - EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest()->getBuffer().get()); } /* @@ -249,8 +251,11 @@ TEST_F(RenderSurfaceTest, dequeueBufferObtainsABuffer) { */ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE | + renderengine::ExternalTexture::Usage::WRITEABLE); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; @@ -261,43 +266,45 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(buffer.get(), mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; state.flipClientTarget = false; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = false; state.flipClientTarget = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferYetDequeued) { @@ -317,27 +324,28 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferY mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { - sp buffer = new GraphicBuffer(); - mSurface.mutableGraphicBufferForTest() = buffer; + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); + mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; state.usesClientComposition = true; EXPECT_CALL(mDisplay, getState()).WillOnce(ReturnRef(state)); - EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, queueBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(INVALID_OPERATION)); EXPECT_CALL(mDisplay, isVirtual()).WillOnce(Return(true)); - EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getNativeBuffer(), -1)) + EXPECT_CALL(*mNativeWindow, cancelBuffer(buffer->getBuffer()->getNativeBuffer(), -1)) .WillOnce(Return(NO_ERROR)); EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1); mSurface.queueBuffer(base::unique_fd()); - EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get()); + EXPECT_EQ(nullptr, mSurface.mutableTextureForTest().get()); } /* diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index f01fe27b38..283c69270f 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -305,8 +305,8 @@ TEST_F(CachedSetTest, render) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector& layers, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> size_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> size_t { EXPECT_EQ(Rect(0, 0, 2, 2), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), @@ -321,7 +321,6 @@ TEST_F(CachedSetTest, render) { EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); - EXPECT_CALL(mRenderEngine, cacheExternalTextureBuffer(_)); cachedSet.render(mRenderEngine, mOutputState); expectReadyBuffer(cachedSet); @@ -331,7 +330,6 @@ TEST_F(CachedSetTest, render) { cachedSet.getOutputSpace().bounds); // Now check that appending a new cached set properly cleans up RenderEngine resources. - EXPECT_CALL(mRenderEngine, unbindExternalTextureBuffer(_)); CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index b7b2cc691b..8692ee60dc 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -70,11 +70,13 @@ DisplayDevice::DisplayDevice(DisplayDeviceCreationArgs& args) mIsPrimary(args.isPrimary) { mCompositionDisplay->editState().isSecure = args.isSecure; mCompositionDisplay->createRenderSurface( - compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth( - args.nativeWindow.get()), - ANativeWindow_getHeight( - args.nativeWindow.get()), - args.nativeWindow, args.displaySurface}); + compositionengine:: + RenderSurfaceCreationArgs{ANativeWindow_getWidth(args.nativeWindow.get()), + ANativeWindow_getHeight(args.nativeWindow.get()), + args.nativeWindow, args.displaySurface, + static_cast( + SurfaceFlinger:: + maxFrameBufferAcquiredBuffers)}); if (!mFlinger->mDisableClientCompositionCache && SurfaceFlinger::maxFrameBufferAcquiredBuffers > 0) { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b45f2bcd92..cf215adba2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -880,7 +880,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { } // Allow BufferStateLayer to release any unlatched buffers in drawing state. - bufferMayChange(c.buffer); + bufferMayChange(c.buffer->getBuffer()); // Commit the transaction commitTransaction(c); @@ -891,7 +891,11 @@ uint32_t Layer::doTransaction(uint32_t flags) { void Layer::commitTransaction(State& stateToCommit) { if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; - mDrawingState.buffer != stateToCommit.buffer && bufferSurfaceFrame != nullptr && + ((mDrawingState.buffer && stateToCommit.buffer && + mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) || + (mDrawingState.buffer && !stateToCommit.buffer) || + (!mDrawingState.buffer && stateToCommit.buffer)) && + bufferSurfaceFrame != nullptr && bufferSurfaceFrame->getPresentState() != PresentState::Presented) { // If the previous buffer was committed but not latched (refreshPending - happens during // back to back invalidates), it gets silently dropped here. Mark the corresponding diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5379d7490d..9f3ea9ab39 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -203,7 +203,7 @@ public: Region transparentRegionHint; - sp buffer; + std::shared_ptr buffer; client_cache_t clientCacheId; sp acquireFence; std::shared_ptr acquireFenceTime; @@ -404,10 +404,11 @@ public: // Used only to set BufferStateLayer state virtual bool setTransform(uint32_t /*transform*/) { return false; }; virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; }; - virtual bool setBuffer(const sp& /*buffer*/, const sp& /*acquireFence*/, - nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/, - uint64_t /* frameNumber */, std::optional /* dequeueTime */, + virtual bool setBuffer(const std::shared_ptr& /*buffer*/, + const sp& /*acquireFence*/, nsecs_t /*postTime*/, + nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, + const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */, + std::optional /* dequeueTime */, const FrameTimelineInfo& /*info*/, const sp& /* releaseBufferListener */) { return false; @@ -709,7 +710,7 @@ public: * Called before updating the drawing state buffer. Used by BufferStateLayer to release any * unlatched buffers in the drawing state. */ - virtual void bufferMayChange(sp& /* newBuffer */){}; + virtual void bufferMayChange(const sp& /* newBuffer */){}; /* * Remove relative z for the layer if its relative parent is not part of the diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 7a3e433660..a9fd16cb75 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -208,7 +208,8 @@ bool RefreshRateOverlay::createLayer() { return true; } -const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { +const std::vector>& +RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) { if (mBufferCache.find(fps) == mBufferCache.end()) { // Ensure the range is > 0, so we don't divide by 0. const auto rangeLength = std::max(1u, mHighFps - mLowFps); @@ -222,7 +223,17 @@ const std::vector>& RefreshRateOverlay::getOrCreateBuffers(uin color.g = HIGH_FPS_COLOR.g * fpsScale + LOW_FPS_COLOR.g * (1 - fpsScale); color.b = HIGH_FPS_COLOR.b * fpsScale + LOW_FPS_COLOR.b * (1 - fpsScale); color.a = ALPHA; - mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner)); + auto buffers = SevenSegmentDrawer::drawNumber(fps, color, mShowSpinner); + std::vector> textures; + std::transform(buffers.begin(), buffers.end(), std::back_inserter(textures), + [&](const auto& buffer) -> std::shared_ptr { + return std::make_shared< + renderengine::ExternalTexture>(buffer, + mFlinger.getRenderEngine(), + renderengine::ExternalTexture:: + Usage::READABLE); + }); + mBufferCache.emplace(fps, textures); } return mBufferCache[fps]; diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index c16cfa07a4..aa8329c46a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -16,13 +16,14 @@ #pragma once -#include - #include +#include #include #include #include +#include + #include "Fps.h" namespace android { @@ -70,7 +71,8 @@ private: }; bool createLayer(); - const std::vector>& getOrCreateBuffers(uint32_t fps); + const std::vector>& getOrCreateBuffers( + uint32_t fps); SurfaceFlinger& mFlinger; const sp mClient; @@ -78,7 +80,8 @@ private: sp mIBinder; sp mGbp; - std::unordered_map>> mBufferCache; + std::unordered_map>> + mBufferCache; std::optional mCurrentFps; int mFrame = 0; static constexpr float ALPHA = 0.8f; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index d0032ac7fd..00090d948a 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -438,18 +438,22 @@ void RegionSamplingThread::captureSample() { mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor); }; - sp buffer = nullptr; - if (mCachedBuffer && mCachedBuffer->getWidth() == sampledBounds.getWidth() && - mCachedBuffer->getHeight() == sampledBounds.getHeight()) { + std::shared_ptr buffer = nullptr; + if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() && + mCachedBuffer->getBuffer()->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), - PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); - const status_t bufferStatus = buffer->initCheck(); + sp graphicBuffer = + new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), + PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); + const status_t bufferStatus = graphicBuffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d", bufferStatus); + buffer = std::make_shared< + renderengine::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); } const sp captureListener = new SyncScreenCaptureListener(); @@ -465,8 +469,8 @@ void RegionSamplingThread::captureSample() { } ALOGV("Sampling %zu descriptors", activeDescriptors.size()); - std::vector lumas = - sampleBuffer(buffer, sampledBounds.leftTop(), activeDescriptors, orientation); + std::vector lumas = sampleBuffer(buffer->getBuffer(), sampledBounds.leftTop(), + activeDescriptors, orientation); if (lumas.size() != activeDescriptors.size()) { ALOGW("collected %zu median luma values for %zu descriptors", lumas.size(), activeDescriptors.size()); @@ -477,16 +481,6 @@ void RegionSamplingThread::captureSample() { activeDescriptors[d].listener->onSampleCollected(lumas[d]); } - // Extend the lifetime of mCachedBuffer from the previous frame to here to ensure that: - // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer - // happens in this thread, as opposed to the main thread. - // 2) The listener(s) receive their notifications prior to freeing the buffer. - if (mCachedBuffer != nullptr && mCachedBuffer != buffer) { - if (mFlinger.getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { - mFlinger.getRenderEngine().unbindExternalTextureBuffer(mCachedBuffer->getId()); - } - } mCachedBuffer = buffer; ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index 0defdb3fcb..86632db490 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -16,17 +16,19 @@ #pragma once +#include +#include +#include +#include +#include +#include + #include #include #include #include #include -#include -#include -#include -#include -#include #include "Scheduler/OneShotTimer.h" namespace android { @@ -122,7 +124,8 @@ private: std::mutex mSamplingMutex; std::unordered_map, Descriptor, WpHash> mDescriptors GUARDED_BY(mSamplingMutex); - sp mCachedBuffer GUARDED_BY(mSamplingMutex) = nullptr; + std::shared_ptr mCachedBuffer GUARDED_BY(mSamplingMutex) = + nullptr; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a4803df9f0..21c8193ca1 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -727,6 +727,7 @@ void SurfaceFlinger::init() { mCompositionEngine->setTimeStats(mTimeStats); mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName)); mCompositionEngine->getHwComposer().setConfiguration(this, getBE().mComposerSequenceId); + ClientCache::getInstance().setRenderEngine(&getRenderEngine()); // Process any initial hotplug and resulting display changes. processDisplayHotplugEventsLocked(); const auto display = getDefaultDisplayDeviceLocked(); @@ -3692,7 +3693,6 @@ void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin if (uncacheBuffer.isValid()) { ClientCache::getInstance().erase(uncacheBuffer); - getRenderEngine().unbindExternalTextureBuffer(uncacheBuffer.id); } // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -4056,23 +4056,16 @@ uint32_t SurfaceFlinger::setClientStateLocked( } bool bufferChanged = what & layer_state_t::eBufferChanged; bool cacheIdChanged = what & layer_state_t::eCachedBufferChanged; - sp buffer; + std::shared_ptr buffer; if (bufferChanged && cacheIdChanged && s.buffer != nullptr) { - buffer = s.buffer; - bool success = ClientCache::getInstance().add(s.cachedBuffer, s.buffer); - if (success) { - getRenderEngine().cacheExternalTextureBuffer(s.buffer); - success = ClientCache::getInstance() - .registerErasedRecipient(s.cachedBuffer, - wp(this)); - if (!success) { - getRenderEngine().unbindExternalTextureBuffer(s.buffer->getId()); - } - } + ClientCache::getInstance().add(s.cachedBuffer, s.buffer); + buffer = ClientCache::getInstance().get(s.cachedBuffer); } else if (cacheIdChanged) { buffer = ClientCache::getInstance().get(s.cachedBuffer); - } else if (bufferChanged) { - buffer = s.buffer; + } else if (bufferChanged && s.buffer != nullptr) { + buffer = std::make_shared< + renderengine::ExternalTexture>(s.buffer, getRenderEngine(), + renderengine::ExternalTexture::Usage::READABLE); } if (buffer) { const bool frameNumberChanged = what & layer_state_t::eFrameNumberChanged; @@ -5993,15 +5986,17 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, const status_t bufferStatus = buffer->initCheck(); LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d", bufferStatus); - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + const auto texture = std::make_shared< + renderengine::ExternalTexture>(buffer, getRenderEngine(), + renderengine::ExternalTexture::Usage::WRITEABLE); + return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - TraverseLayersFunction traverseLayers, - sp& buffer, bool regionSampling, - bool grayscale, - const sp& captureListener) { +status_t SurfaceFlinger::captureScreenCommon( + RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, + const std::shared_ptr& buffer, bool regionSampling, + bool grayscale, const sp& captureListener) { ATRACE_CALL(); if (captureListener == nullptr) { @@ -6034,15 +6029,6 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, regionSampling, grayscale, captureResults); }); - // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine - // Only do this when we're not doing region sampling, to allow the region sampling thread to - // manage buffer lifecycle itself. - if (!regionSampling && - getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { - getRenderEngine().unbindExternalTextureBuffer(buffer->getId()); - } - captureResults.result = result; captureListener->onScreenCaptureCompleted(captureResults); })); @@ -6050,11 +6036,10 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, return NO_ERROR; } -status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, - TraverseLayersFunction traverseLayers, - const sp& buffer, bool forSystem, - bool regionSampling, bool grayscale, - ScreenCaptureResults& captureResults) { +status_t SurfaceFlinger::renderScreenImplLocked( + const RenderArea& renderArea, TraverseLayersFunction traverseLayers, + const std::shared_ptr& buffer, bool forSystem, + bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -6062,7 +6047,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, captureResults.capturedSecureLayers || (layer->isVisible() && layer->isSecure()); }); - const bool useProtected = buffer->getUsage() & GRALLOC_USAGE_PROTECTED; + const bool useProtected = buffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED; // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place @@ -6072,7 +6057,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, return PERMISSION_DENIED; } - captureResults.buffer = buffer; + captureResults.buffer = buffer->getBuffer(); captureResults.capturedDataspace = renderArea.getReqDataSpace(); const auto reqWidth = renderArea.getReqWidth(); @@ -6163,11 +6148,9 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, base::unique_fd drawFence; getRenderEngine().useProtectedContext(useProtected); - // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine - const bool useFramebufferCache = getRenderEngine().getRenderEngineType() == - renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED; + const constexpr bool kUseFramebufferCache = false; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - useFramebufferCache, std::move(bufferFence), &drawFence); + kUseFramebufferCache, std::move(bufferFence), &drawFence); if (drawFence >= 0) { sp releaseFence = new Fence(dup(drawFence)); @@ -6432,10 +6415,6 @@ void SurfaceFlinger::removeFromOffscreenLayers(Layer* layer) { mOffscreenLayers.erase(layer); } -void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { - getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); -} - status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor, float lightPosY, float lightPosZ, float lightRadius) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9135632bef..893b3d8751 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -178,7 +178,6 @@ struct SurfaceFlingerBE { class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, - public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, private HWC2::ComposerCallback, private ISchedulerCallback { @@ -326,9 +325,6 @@ public: wp fromHandle(const sp& handle); wp fromHandleLocked(const sp& handle) const REQUIRES(mStateLock); - // Inherit from ClientCache::ErasedRecipient - void bufferErased(const client_cache_t& clientCacheId) override; - // If set, disables reusing client composition buffers. This can be set by // debug.sf.disable_client_composition_cache bool mDisableClientCompositionCache = false; @@ -901,12 +897,14 @@ private: status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, bool allowProtected, bool grayscale, const sp&); - status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp&, + status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, bool regionSampling, bool grayscale, const sp&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const sp&, bool forSystem, bool regionSampling, - bool grayscale, ScreenCaptureResults&); + const std::shared_ptr&, + bool forSystem, bool regionSampling, bool grayscale, + ScreenCaptureResults&); sp getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp getDisplayById(DisplayId displayId) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 4e1c0c77ea..3042450f29 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -15,6 +15,7 @@ */ // TODO(b/129481165): remove the #pragma below and fix conversion issues +#include "renderengine/ExternalTexture.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wextra" @@ -194,7 +195,7 @@ public: sp mClientTargetAcquireFence = Fence::NO_FENCE; - sp mCaptureScreenBuffer; + std::shared_ptr mCaptureScreenBuffer; }; template @@ -243,11 +244,15 @@ void CompositionTest::captureScreenComposition() { // TODO: Eliminate expensive/real allocation if possible. const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; - mCaptureScreenBuffer = new GraphicBuffer(renderArea->getReqWidth(), renderArea->getReqHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot"); + mCaptureScreenBuffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(renderArea->getReqWidth(), + renderArea->getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, + "screenshot"), + *mRenderEngine, true); status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer.get(), + mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, forSystem, regionSampling); EXPECT_EQ(NO_ERROR, result); @@ -340,8 +345,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, + const bool, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -389,8 +394,8 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([](const renderengine::DisplaySettings& displaySettings, const std::vector&, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, + const bool, base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -625,8 +630,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -674,8 +679,8 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -751,8 +756,8 @@ struct CommonSecureLayerProperties : public BaseLayerProperties EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([](const renderengine::DisplaySettings& displaySettings, const std::vector& layerSettings, - const sp&, const bool, base::unique_fd&&, - base::unique_fd*) -> status_t { + const std::shared_ptr&, const bool, + base::unique_fd&&, base::unique_fd*) -> status_t { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 63baf7dee2..d004b9d9eb 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -352,8 +352,8 @@ public: auto renderScreenImplLocked(const RenderArea& renderArea, SurfaceFlinger::TraverseLayersFunction traverseLayers, - const sp& buffer, bool forSystem, - bool regionSampling) { + const std::shared_ptr& buffer, + bool forSystem, bool regionSampling) { ScreenCaptureResults captureResults; return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem, regionSampling, false /* grayscale */, diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index ea1ce47b70..25001d3890 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include "TestableSurfaceFlinger.h" @@ -99,6 +101,7 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; + renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -106,9 +109,12 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getId(); + uint64_t bufferId = buffer->getBuffer()->getId(); uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 09a1c2af75..b7917aa00e 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include "TestableSurfaceFlinger.h" @@ -99,6 +101,7 @@ public: TestableSurfaceFlinger mFlinger; Hwc2::mock::Composer* mComposer = nullptr; + renderengine::mock::RenderEngine mRenderEngine; FenceToFenceTimeMap fenceFactory; client_cache_t mClientCache; @@ -119,7 +122,10 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -144,7 +150,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -153,7 +162,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); nsecs_t start = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -191,8 +203,10 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); @@ -217,8 +231,10 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -247,8 +263,10 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - sp buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; - + const auto buffer = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -283,7 +301,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); @@ -291,7 +312,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); @@ -318,7 +342,10 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); @@ -327,7 +354,10 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - sp buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer2 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); auto dropStartTime1 = systemTime(); layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, @@ -339,7 +369,10 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - sp buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer3 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, 0), + mRenderEngine, false); auto dropStartTime2 = systemTime(); layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); @@ -379,7 +412,11 @@ public: std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence1(new Fence()); - sp buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)}; + const auto buffer1 = std::make_shared< + renderengine::ExternalTexture>(new GraphicBuffer(1, 1, + HAL_PIXEL_FORMAT_RGBA_8888, 1, + 0), + mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); -- cgit v1.2.3-59-g8ed1b From 6a160319a4f4923bb35d6c3b586d1d7a22ec6fa6 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Mon, 17 May 2021 12:08:20 -0700 Subject: Start removing Current state Now that we only write to current state from the main thread we can actually just write directly in to drawing state and avoid copying current to drawing state on each frame. simpleperf on bouncing ball indicates this was saving around 8% CPU or so per frame. As a next target we will eliminate the remaining work in doTransaction and eliminate the doTransaction pass. Test: Existing tests pass. simpleperf Bug: 186200583 Change-Id: I59b75747d7371b3ffe870129c8be100c7daa6c4e --- services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 183 +++---- services/surfaceflinger/BufferStateLayer.h | 6 +- services/surfaceflinger/EffectLayer.cpp | 22 +- services/surfaceflinger/FpsReporter.cpp | 4 +- services/surfaceflinger/Layer.cpp | 557 ++++++++------------- services/surfaceflinger/Layer.h | 21 +- services/surfaceflinger/LayerVector.cpp | 12 +- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 7 +- services/surfaceflinger/SurfaceInterceptor.cpp | 34 +- .../surfaceflinger/TunnelModeEnabledReporter.cpp | 4 +- .../tests/unittests/RefreshRateSelectionTest.cpp | 2 +- .../tests/unittests/SetFrameRateTest.cpp | 2 +- .../SurfaceFlinger_DestroyDisplayTest.cpp | 2 +- .../tests/unittests/TestableSurfaceFlinger.h | 2 - .../tests/unittests/TransactionFrameTracerTest.cpp | 2 +- .../unittests/TransactionSurfaceFrameTest.cpp | 94 ++-- 18 files changed, 419 insertions(+), 543 deletions(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e7f373ff3f..c64371b84a 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -223,7 +223,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // buffer mode. bool queuedBuffer = false; const int32_t layerId = getSequence(); - LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, + LayerRejecter r(mDrawingState, getDrawingState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName, getTransformToDisplayInverse()); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index f8af908737..a3b7b13d4c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -65,7 +65,7 @@ const std::array BufferStateLayer::IDENTITY_MATRIX{ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { - mCurrentState.dataspace = ui::Dataspace::V0_SRGB; + mDrawingState.dataspace = ui::Dataspace::V0_SRGB; } BufferStateLayer::~BufferStateLayer() { @@ -257,8 +257,8 @@ void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptrgetBuffer()->getWidth(); - uint32_t bufferHeight = mCurrentState.buffer->getBuffer()->getHeight(); + uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth(); + uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->getHeight(); // Undo any transformations on the buffer. - if (mCurrentState.bufferTransform & ui::Transform::ROT_90) { + if (mDrawingState.bufferTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags(); - if (mCurrentState.transformToDisplayInverse) { + if (mDrawingState.transformToDisplayInverse) { if (invTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); } @@ -361,8 +367,7 @@ void BufferStateLayer::updateGeometry() { ui::Transform t; t.set(sx, 0, 0, sy); t.set(destRect.left, destRect.top); - mCurrentState.transform = t; - return; + return assignTransform(&mDrawingState.transform, t); } bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, @@ -383,8 +388,8 @@ bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix, mRequestedTransform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - mCurrentState.sequence++; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -397,8 +402,8 @@ bool BufferStateLayer::setPosition(float x, float y) { mRequestedTransform.set(x, y); - mCurrentState.sequence++; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; @@ -410,7 +415,7 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post mAcquireTimeline.updateSignalTimes(); std::shared_ptr acquireFenceTime = std::make_shared((acquireFence ? acquireFence : Fence::NO_FENCE)); - NewFrameEventsEntry newTimestamps = {mCurrentState.frameNumber, postedTime, desiredPresentTime, + NewFrameEventsEntry newTimestamps = {mDrawingState.frameNumber, postedTime, desiredPresentTime, acquireFenceTime}; mFrameEventHistory.setProducerWantsEvents(); mFrameEventHistory.addQueue(newTimestamps); @@ -425,38 +430,39 @@ bool BufferStateLayer::setBuffer(const std::shared_ptr& releaseBufferListener) { ATRACE_CALL(); - if (mCurrentState.buffer) { + if (mDrawingState.buffer) { mReleasePreviousBuffer = true; - if (!mDrawingState.buffer || - mCurrentState.buffer->getBuffer() != mDrawingState.buffer->getBuffer()) { - // If mCurrentState has a buffer, and we are about to update again + if (mDrawingState.buffer != mBufferInfo.mBuffer) { + // If mDrawingState has a buffer, and we are about to update again // before swapping to drawing state, then the first buffer will be // dropped and we should decrement the pending buffer count and // call any release buffer callbacks if set. - callReleaseBufferCallback(mCurrentState.releaseBufferListener, - mCurrentState.buffer->getBuffer(), mCurrentState.acquireFence, + callReleaseBufferCallback(mDrawingState.releaseBufferListener, + mDrawingState.buffer->getBuffer(), mDrawingState.acquireFence, mTransformHint, mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate( mOwnerUid)); decrementPendingBufferCount(); - if (mCurrentState.bufferSurfaceFrameTX != nullptr) { - addSurfaceFrameDroppedForBuffer(mCurrentState.bufferSurfaceFrameTX); - mCurrentState.bufferSurfaceFrameTX.reset(); + if (mDrawingState.bufferSurfaceFrameTX != nullptr && + mDrawingState.bufferSurfaceFrameTX->getPresentState() != PresentState::Presented) { + addSurfaceFrameDroppedForBuffer(mDrawingState.bufferSurfaceFrameTX); + mDrawingState.bufferSurfaceFrameTX.reset(); } } } - mCurrentState.frameNumber = frameNumber; - mCurrentState.releaseBufferListener = releaseBufferListener; - mCurrentState.buffer = buffer; - mCurrentState.clientCacheId = clientCacheId; - mCurrentState.modified = true; + + mDrawingState.frameNumber = frameNumber; + mDrawingState.releaseBufferListener = releaseBufferListener; + mDrawingState.buffer = buffer; + mDrawingState.clientCacheId = clientCacheId; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); const int32_t layerId = getSequence(); - mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(), + mFlinger->mTimeStats->setPostTime(layerId, mDrawingState.frameNumber, getName().c_str(), mOwnerUid, postTime, getGameMode()); - mCurrentState.desiredPresentTime = desiredPresentTime; - mCurrentState.isAutoTimestamp = isAutoTimestamp; + mDrawingState.desiredPresentTime = desiredPresentTime; + mDrawingState.isAutoTimestamp = isAutoTimestamp; const nsecs_t presentTime = [&] { if (!isAutoTimestamp) return desiredPresentTime; @@ -483,59 +489,59 @@ bool BufferStateLayer::setBuffer(const std::shared_ptrgetBuffer()->getWidth(); - mCurrentState.height = mCurrentState.buffer->getBuffer()->getHeight(); + mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth(); + mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight(); return true; } bool BufferStateLayer::setAcquireFence(const sp& fence) { - mCurrentState.acquireFence = fence; - mCurrentState.acquireFenceTime = std::make_unique(fence); + mDrawingState.acquireFence = fence; + mDrawingState.acquireFenceTime = std::make_unique(fence); // The acquire fences of BufferStateLayers have already signaled before they are set - mCallbackHandleAcquireTime = mCurrentState.acquireFenceTime->getSignalTime(); + mCallbackHandleAcquireTime = mDrawingState.acquireFenceTime->getSignalTime(); - mCurrentState.modified = true; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) { - if (mCurrentState.dataspace == dataspace) return false; - mCurrentState.dataspace = dataspace; - mCurrentState.modified = true; + if (mDrawingState.dataspace == dataspace) return false; + mDrawingState.dataspace = dataspace; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) { - if (mCurrentState.hdrMetadata == hdrMetadata) return false; - mCurrentState.hdrMetadata = hdrMetadata; - mCurrentState.modified = true; + if (mDrawingState.hdrMetadata == hdrMetadata) return false; + mDrawingState.hdrMetadata = hdrMetadata; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) { - mCurrentState.surfaceDamageRegion = surfaceDamage; - mCurrentState.modified = true; + mDrawingState.surfaceDamageRegion = surfaceDamage; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setApi(int32_t api) { - if (mCurrentState.api == api) return false; - mCurrentState.api = api; - mCurrentState.modified = true; + if (mDrawingState.api == api) return false; + mDrawingState.api = api; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool BufferStateLayer::setSidebandStream(const sp& sidebandStream) { - if (mCurrentState.sidebandStream == sidebandStream) return false; - mCurrentState.sidebandStream = sidebandStream; - mCurrentState.modified = true; + if (mDrawingState.sidebandStream == sidebandStream) return false; + mDrawingState.sidebandStream = sidebandStream; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); if (!mSidebandStreamChanged.exchange(true)) { @@ -563,14 +569,14 @@ bool BufferStateLayer::setTransactionCompletedListeners( if (willPresent) { // If this transaction set an acquire fence on this layer, set its acquire time handle->acquireTime = mCallbackHandleAcquireTime; - handle->frameNumber = mCurrentState.frameNumber; + handle->frameNumber = mDrawingState.frameNumber; // Notify the transaction completed thread that there is a pending latched callback // handle mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle); // Store so latched time and release fence can be set - mCurrentState.callbackHandles.push_back(handle); + mDrawingState.callbackHandles.push_back(handle); } else { // If this layer will NOT need to be relatched and presented this frame // Notify the transaction completed thread this handle is done @@ -585,8 +591,8 @@ bool BufferStateLayer::setTransactionCompletedListeners( } bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.transparentRegionHint = transparent; - mCurrentState.modified = true; + mDrawingState.transparentRegionHint = transparent; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -645,7 +651,7 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return true; } - return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime; + return mDrawingState.isAutoTimestamp || mDrawingState.desiredPresentTime <= expectedPresentTime; } bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) { @@ -674,7 +680,7 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const * } * Now imagine getHeadFrameNumber returned mDrawingState.mFrameNumber (or mCurrentFrameNumber). * Prior to doTransaction SurfaceFlinger will call notifyAvailableFrames, but because we - * haven't swapped mCurrentState to mDrawingState yet we will think the sync point + * haven't swapped mDrawingState to mDrawingState yet we will think the sync point * is not ready. So we will return false from applyPendingState and not swap * current state to drawing state. But because we don't swap current state * to drawing state the number will never update and we will be stuck. This way @@ -682,7 +688,7 @@ uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const * to apply. */ uint64_t BufferStateLayer::getHeadFrameNumber(nsecs_t /* expectedPresentTime */) const { - return mCurrentState.frameNumber; + return mDrawingState.frameNumber; } void BufferStateLayer::setAutoRefresh(bool autoRefresh) { @@ -712,8 +718,8 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { } bool BufferStateLayer::hasFrameUpdate() const { - const State& c(getCurrentState()); - return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); + const State& c(getDrawingState()); + return mDrawingStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, @@ -756,6 +762,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse addSurfaceFramePresentedForBuffer(bufferSurfaceFrame, mDrawingState.acquireFenceTime->getSignalTime(), latchTime); + mDrawingState.bufferSurfaceFrameTX.reset(); } std::deque> remainingHandles; @@ -763,7 +770,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse .finalizeOnCommitCallbackHandles(mDrawingState.callbackHandles, remainingHandles); mDrawingState.callbackHandles = remainingHandles; - mCurrentStateModified = false; + mDrawingStateModified = false; return NO_ERROR; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 2e484524a1..27470182bf 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -47,10 +47,6 @@ public: bool isBufferDue(nsecs_t /*expectedPresentTime*/) const override { return true; } - uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { - return flags; - } - Region getActiveTransparentRegion(const Layer::State& s) const override { return s.transparentRegionHint; } @@ -87,7 +83,7 @@ public: bool setBufferCrop(const Rect& bufferCrop) override; bool setDestinationFrame(const Rect& destinationFrame) override; - void updateGeometry() override; + bool updateGeometry() override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp index 0cc5f33d73..86c6b2161c 100644 --- a/services/surfaceflinger/EffectLayer.cpp +++ b/services/surfaceflinger/EffectLayer.cpp @@ -78,28 +78,28 @@ bool EffectLayer::isVisible() const { } bool EffectLayer::setColor(const half3& color) { - if (mCurrentState.color.r == color.r && mCurrentState.color.g == color.g && - mCurrentState.color.b == color.b) { + if (mDrawingState.color.r == color.r && mDrawingState.color.g == color.g && + mDrawingState.color.b == color.b) { return false; } - mCurrentState.sequence++; - mCurrentState.color.r = color.r; - mCurrentState.color.g = color.g; - mCurrentState.color.b = color.b; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.color.r = color.r; + mDrawingState.color.g = color.g; + mDrawingState.color.b = color.b; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool EffectLayer::setDataspace(ui::Dataspace dataspace) { - if (mCurrentState.dataspace == dataspace) { + if (mDrawingState.dataspace == dataspace) { return false; } - mCurrentState.sequence++; - mCurrentState.dataspace = dataspace; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.dataspace = dataspace; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } diff --git a/services/surfaceflinger/FpsReporter.cpp b/services/surfaceflinger/FpsReporter.cpp index 23db805d5b..e12835f0f6 100644 --- a/services/surfaceflinger/FpsReporter.cpp +++ b/services/surfaceflinger/FpsReporter.cpp @@ -55,7 +55,7 @@ void FpsReporter::dispatchLayerFps() { std::vector>> listenersAndLayersToReport; mFlinger.mCurrentState.traverse([&](Layer* layer) { - auto& currentState = layer->getCurrentState(); + auto& currentState = layer->getDrawingState(); if (currentState.metadata.has(METADATA_TASK_ID)) { int32_t taskId = currentState.metadata.getInt32(METADATA_TASK_ID, 0); if (seenTasks.count(taskId) == 0) { @@ -100,4 +100,4 @@ void FpsReporter::removeListener(const sp& listener) { mListeners.erase(wp(IInterface::asBinder(listener))); } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4beb5262d4..b819dbe7ce 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -98,52 +98,49 @@ Layer::Layer(const LayerCreationArgs& args) if (args.flags & ISurfaceComposerClient::eSkipScreenshot) layerFlags |= layer_state_t::eLayerSkipScreenshot; - mCurrentState.active_legacy.w = args.w; - mCurrentState.active_legacy.h = args.h; - mCurrentState.flags = layerFlags; - mCurrentState.active_legacy.transform.set(0, 0); - mCurrentState.crop.makeInvalid(); - mCurrentState.requestedCrop = mCurrentState.crop; - mCurrentState.z = 0; - mCurrentState.color.a = 1.0f; - mCurrentState.layerStack = 0; - mCurrentState.sequence = 0; - mCurrentState.requested_legacy = mCurrentState.active_legacy; - mCurrentState.width = UINT32_MAX; - mCurrentState.height = UINT32_MAX; - mCurrentState.transform.set(0, 0); - mCurrentState.frameNumber = 0; - mCurrentState.bufferTransform = 0; - mCurrentState.transformToDisplayInverse = false; - mCurrentState.crop.makeInvalid(); - mCurrentState.acquireFence = sp::make(-1); - mCurrentState.acquireFenceTime = std::make_shared(mCurrentState.acquireFence); - mCurrentState.dataspace = ui::Dataspace::UNKNOWN; - mCurrentState.hdrMetadata.validTypes = 0; - mCurrentState.surfaceDamageRegion = Region::INVALID_REGION; - mCurrentState.cornerRadius = 0.0f; - mCurrentState.backgroundBlurRadius = 0; - mCurrentState.api = -1; - mCurrentState.hasColorTransform = false; - mCurrentState.colorSpaceAgnostic = false; - mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET; - mCurrentState.metadata = args.metadata; - mCurrentState.shadowRadius = 0.f; - mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID; - mCurrentState.frameTimelineInfo = {}; - mCurrentState.postTime = -1; - mCurrentState.destinationFrame.makeInvalid(); + mDrawingState.active_legacy.w = args.w; + mDrawingState.active_legacy.h = args.h; + mDrawingState.flags = layerFlags; + mDrawingState.active_legacy.transform.set(0, 0); + mDrawingState.crop.makeInvalid(); + mDrawingState.requestedCrop = mDrawingState.crop; + mDrawingState.z = 0; + mDrawingState.color.a = 1.0f; + mDrawingState.layerStack = 0; + mDrawingState.sequence = 0; + mDrawingState.requested_legacy = mDrawingState.active_legacy; + mDrawingState.width = UINT32_MAX; + mDrawingState.height = UINT32_MAX; + mDrawingState.transform.set(0, 0); + mDrawingState.frameNumber = 0; + mDrawingState.bufferTransform = 0; + mDrawingState.transformToDisplayInverse = false; + mDrawingState.crop.makeInvalid(); + mDrawingState.acquireFence = sp::make(-1); + mDrawingState.acquireFenceTime = std::make_shared(mDrawingState.acquireFence); + mDrawingState.dataspace = ui::Dataspace::UNKNOWN; + mDrawingState.hdrMetadata.validTypes = 0; + mDrawingState.surfaceDamageRegion = Region::INVALID_REGION; + mDrawingState.cornerRadius = 0.0f; + mDrawingState.backgroundBlurRadius = 0; + mDrawingState.api = -1; + mDrawingState.hasColorTransform = false; + mDrawingState.colorSpaceAgnostic = false; + mDrawingState.frameRateSelectionPriority = PRIORITY_UNSET; + mDrawingState.metadata = args.metadata; + mDrawingState.shadowRadius = 0.f; + mDrawingState.fixedTransformHint = ui::Transform::ROT_INVALID; + mDrawingState.frameTimelineInfo = {}; + mDrawingState.postTime = -1; + mDrawingState.destinationFrame.makeInvalid(); if (args.flags & ISurfaceComposerClient::eNoColorFill) { // Set an invalid color so there is no color fill. - mCurrentState.color.r = -1.0_hf; - mCurrentState.color.g = -1.0_hf; - mCurrentState.color.b = -1.0_hf; + mDrawingState.color.r = -1.0_hf; + mDrawingState.color.g = -1.0_hf; + mDrawingState.color.b = -1.0_hf; } - // drawing state & current state are identical - mDrawingState = mCurrentState; - CompositorTiming compositorTiming; args.flinger->getCompositorTiming(&compositorTiming); mFrameEventHistory.initializeCompositorTiming(compositorTiming); @@ -203,11 +200,11 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { - if (mCurrentState.zOrderRelativeOf == nullptr) { + if (mDrawingState.zOrderRelativeOf == nullptr) { return; } - sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); + sp strongRelative = mDrawingState.zOrderRelativeOf.promote(); if (strongRelative == nullptr) { setZOrderRelativeOf(nullptr); return; @@ -221,8 +218,8 @@ void Layer::removeRelativeZ(const std::vector& layersInTree) { } void Layer::removeFromCurrentState() { - if (!mRemovedFromCurrentState) { - mRemovedFromCurrentState = true; + if (!mRemovedFromDrawingState) { + mRemovedFromDrawingState = true; mFlinger->mScheduler->deregisterLayer(this); } @@ -249,8 +246,8 @@ void Layer::onRemovedFromCurrentState() { } void Layer::addToCurrentState() { - if (mRemovedFromCurrentState) { - mRemovedFromCurrentState = false; + if (mRemovedFromDrawingState) { + mRemovedFromDrawingState = false; mFlinger->mScheduler->registerLayer(this); } @@ -679,78 +676,6 @@ bool Layer::isSecure() const { // transaction // ---------------------------------------------------------------------------- -uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { - const State& s(getDrawingState()); - - const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) || - (stateToCommit->requested_legacy.h != s.requested_legacy.h); - - if (sizeChanged) { - // the size changed, we need to ask our client to request a new buffer - ALOGD_IF(DEBUG_RESIZE, - "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n" - " current={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" - " 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().c_str(), getBufferTransform(), getEffectiveScalingMode(), - stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, - stateToCommit->crop.left, stateToCommit->crop.top, stateToCommit->crop.right, - stateToCommit->crop.bottom, stateToCommit->crop.getWidth(), - stateToCommit->crop.getHeight(), stateToCommit->requested_legacy.w, - stateToCommit->requested_legacy.h, s.active_legacy.w, s.active_legacy.h, - s.crop.left, s.crop.top, s.crop.right, s.crop.bottom, s.crop.getWidth(), - s.crop.getHeight(), s.requested_legacy.w, s.requested_legacy.h); - } - - // Don't let Layer::doTransaction update the drawing state - // if we have a pending resize, unless we are in fixed-size mode. - // the drawing state will be updated only once we receive a buffer - // with the correct size. - // - // In particular, we want to make sure the clip (which is part - // of the geometry state) is latched together with the size but is - // latched immediately when no resizing is involved. - // - // If a sideband stream is attached, however, we want to skip this - // optimization so that transactions aren't missed when a buffer - // never arrives - // - // In the case that we don't have a buffer we ignore other factors - // and avoid entering the resizePending state. At a high level the - // resizePending state is to avoid applying the state of the new buffer - // to the old buffer. However in the state where we don't have an old buffer - // there is no such concern but we may still be being used as a parent layer. - const bool resizePending = - ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || - (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && - (getBuffer() != nullptr); - if (!isFixedSize()) { - if (resizePending && mSidebandStream == nullptr) { - flags |= eDontUpdateGeometryState; - } - } - - // Here we apply various requested geometry states, depending on our - // latching configuration. See Layer.h for a detailed discussion of - // how geometry latching is controlled. - if (!(flags & eDontUpdateGeometryState)) { - State& editCurrentState(getCurrentState()); - - // There is an awkward asymmetry in the handling of the crop states in the position - // states, as can be seen below. Largely this arises from position and transform - // being stored in the same data structure while having different latching rules. - // b/38182305 - // - // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to - // applyPendingStates in the presence of deferred transactions. - editCurrentState.active_legacy = editCurrentState.requested_legacy; - stateToCommit->active_legacy = stateToCommit->requested_legacy; - } - - return flags; -} - uint32_t Layer::doTransaction(uint32_t flags) { ATRACE_CALL(); @@ -760,77 +685,37 @@ uint32_t Layer::doTransaction(uint32_t flags) { } // TODO: This is unfortunate. - mCurrentStateModified = mCurrentState.modified; - mCurrentState.modified = false; - - flags = doTransactionResize(flags, &mCurrentState); + mDrawingStateModified = mDrawingState.modified; + mDrawingState.modified = false; const State& s(getDrawingState()); - State& c(getCurrentState()); - - // Translates dest frame into scale and position updates. This helps align geometry calculations - // for BufferStateLayer with other layers. This should ideally happen in the client once client - // has the display orientation details from WM. - updateGeometry(); - if (c.width != s.width || c.height != s.height || !(c.transform == s.transform)) { + if (updateGeometry()) { // invalidate and recompute the visible regions if needed flags |= Layer::eVisibleRegion; } - if (c.sequence != s.sequence) { + if (s.sequence != mLastCommittedTxSequence) { // invalidate and recompute the visible regions if needed + mLastCommittedTxSequence = s.sequence; flags |= eVisibleRegion; this->contentDirty = true; // we may use linear filtering, if the matrix scales us - mNeedsFiltering = getActiveTransform(c).needsBilinearFiltering(); + mNeedsFiltering = getActiveTransform(s).needsBilinearFiltering(); } - if (mCurrentState.inputInfoChanged) { + if (mDrawingState.inputInfoChanged) { flags |= eInputInfoChanged; - mCurrentState.inputInfoChanged = false; - } - - // Add the callbacks from the drawing state into the current state. This is so when the current - // state gets copied to drawing, we don't lose the callback handles that are still in drawing. - for (auto& handle : s.callbackHandles) { - c.callbackHandles.push_back(handle); + mDrawingState.inputInfoChanged = false; } - // Allow BufferStateLayer to release any unlatched buffers in drawing state. - bufferMayChange(c.buffer->getBuffer()); - - // Commit the transaction - commitTransaction(c); - mCurrentState.callbackHandles = {}; + commitTransaction(mDrawingState); return flags; } -void Layer::commitTransaction(State& stateToCommit) { - if (auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX; - ((mDrawingState.buffer && stateToCommit.buffer && - mDrawingState.buffer->getBuffer() != stateToCommit.buffer->getBuffer()) || - (mDrawingState.buffer && !stateToCommit.buffer) || - (!mDrawingState.buffer && stateToCommit.buffer)) && - bufferSurfaceFrame != nullptr && - bufferSurfaceFrame->getPresentState() != PresentState::Presented) { - // If the previous buffer was committed but not latched (refreshPending - happens during - // back to back invalidates), it gets silently dropped here. Mark the corresponding - // SurfaceFrame as dropped to prevent it from getting stuck in the pending classification - // list. - addSurfaceFrameDroppedForBuffer(bufferSurfaceFrame); - } - const bool frameRateVoteChanged = - mDrawingState.frameRateForLayerTree != stateToCommit.frameRateForLayerTree; - mDrawingState = stateToCommit; - - if (frameRateVoteChanged) { - mFlinger->mScheduler->recordLayerHistory(this, systemTime(), - LayerHistory::LayerUpdateType::SetFrameRate); - } - +void Layer::commitTransaction(State&) { // Set the present state for all bufferlessSurfaceFramesTX to Presented. The // bufferSurfaceFrameTX will be presented in latchBuffer. for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) { @@ -841,9 +726,7 @@ void Layer::commitTransaction(State& stateToCommit) { mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame); } } - // Clear the surfaceFrames from the old state now that it has been copied into DrawingState. - stateToCommit.bufferSurfaceFrameTX.reset(); - stateToCommit.bufferlessSurfaceFramesTX.clear(); + mDrawingState.bufferlessSurfaceFramesTX.clear(); } uint32_t Layer::getTransactionFlags(uint32_t flags) { @@ -857,20 +740,11 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { } bool Layer::setPosition(float x, float y) { - if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y) return false; - mCurrentState.sequence++; - - // We update the requested and active position simultaneously because - // we want to apply the position portion of the transform matrix immediately, - // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. - mCurrentState.transform.set(x, y); - // Here we directly update the active state - // unlike other setters, because we store it within - // the transform, but use different latching rules. - // b/38182305 - mCurrentState.transform.set(x, y); - - mCurrentState.modified = true; + if (mDrawingState.transform.tx() == x && mDrawingState.transform.ty() == y) return false; + mDrawingState.sequence++; + mDrawingState.transform.set(x, y); + + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -903,14 +777,14 @@ bool Layer::setChildRelativeLayer(const sp& childLayer, } bool Layer::setLayer(int32_t z) { - if (mCurrentState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; - mCurrentState.sequence++; - mCurrentState.z = z; - mCurrentState.modified = true; + if (mDrawingState.z == z && !usingRelativeZ(LayerVector::StateSet::Current)) return false; + mDrawingState.sequence++; + mDrawingState.z = z; + mDrawingState.modified = true; // Discard all relative layering. - if (mCurrentState.zOrderRelativeOf != nullptr) { - sp strongRelative = mCurrentState.zOrderRelativeOf.promote(); + if (mDrawingState.zOrderRelativeOf != nullptr) { + sp strongRelative = mDrawingState.zOrderRelativeOf.promote(); if (strongRelative != nullptr) { strongRelative->removeZOrderRelative(this); } @@ -921,24 +795,24 @@ bool Layer::setLayer(int32_t z) { } void Layer::removeZOrderRelative(const wp& relative) { - mCurrentState.zOrderRelatives.remove(relative); - mCurrentState.sequence++; - mCurrentState.modified = true; + mDrawingState.zOrderRelatives.remove(relative); + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); } void Layer::addZOrderRelative(const wp& relative) { - mCurrentState.zOrderRelatives.add(relative); - mCurrentState.modified = true; - mCurrentState.sequence++; + mDrawingState.zOrderRelatives.add(relative); + mDrawingState.modified = true; + mDrawingState.sequence++; setTransactionFlags(eTransactionNeeded); } void Layer::setZOrderRelativeOf(const wp& relativeOf) { - mCurrentState.zOrderRelativeOf = relativeOf; - mCurrentState.sequence++; - mCurrentState.modified = true; - mCurrentState.isRelativeOf = relativeOf != nullptr; + mDrawingState.zOrderRelativeOf = relativeOf; + mDrawingState.sequence++; + mDrawingState.modified = true; + mDrawingState.isRelativeOf = relativeOf != nullptr; setTransactionFlags(eTransactionNeeded); } @@ -953,16 +827,16 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati return false; } - if (mCurrentState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && - mCurrentState.zOrderRelativeOf == relative) { + if (mDrawingState.z == relativeZ && usingRelativeZ(LayerVector::StateSet::Current) && + mDrawingState.zOrderRelativeOf == relative) { return false; } - mCurrentState.sequence++; - mCurrentState.modified = true; - mCurrentState.z = relativeZ; + mDrawingState.sequence++; + mDrawingState.modified = true; + mDrawingState.z = relativeZ; - auto oldZOrderRelativeOf = mCurrentState.zOrderRelativeOf.promote(); + auto oldZOrderRelativeOf = mDrawingState.zOrderRelativeOf.promote(); if (oldZOrderRelativeOf != nullptr) { oldZOrderRelativeOf->removeZOrderRelative(this); } @@ -975,82 +849,82 @@ bool Layer::setRelativeLayer(const sp& relativeToHandle, int32_t relati } bool Layer::setSize(uint32_t w, uint32_t h) { - if (mCurrentState.requested_legacy.w == w && mCurrentState.requested_legacy.h == h) + if (mDrawingState.requested_legacy.w == w && mDrawingState.requested_legacy.h == h) return false; - mCurrentState.requested_legacy.w = w; - mCurrentState.requested_legacy.h = h; - mCurrentState.modified = true; + mDrawingState.requested_legacy.w = w; + mDrawingState.requested_legacy.h = h; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); // record the new size, from this point on, when the client request // a buffer, it'll get the new size. - setDefaultBufferSize(mCurrentState.requested_legacy.w, mCurrentState.requested_legacy.h); + setDefaultBufferSize(mDrawingState.requested_legacy.w, mDrawingState.requested_legacy.h); return true; } bool Layer::setAlpha(float alpha) { - if (mCurrentState.color.a == alpha) return false; - mCurrentState.sequence++; - mCurrentState.color.a = alpha; - mCurrentState.modified = true; + if (mDrawingState.color.a == alpha) return false; + mDrawingState.sequence++; + mDrawingState.color.a = alpha; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) { - if (!mCurrentState.bgColorLayer && alpha == 0) { + if (!mDrawingState.bgColorLayer && alpha == 0) { return false; } - mCurrentState.sequence++; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); - if (!mCurrentState.bgColorLayer && alpha != 0) { + if (!mDrawingState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceEffect; std::string name = mName + "BackgroundColorLayer"; - mCurrentState.bgColorLayer = mFlinger->getFactory().createEffectLayer( + mDrawingState.bgColorLayer = mFlinger->getFactory().createEffectLayer( LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, LayerMetadata())); // add to child list - addChild(mCurrentState.bgColorLayer); + addChild(mDrawingState.bgColorLayer); mFlinger->mLayersAdded = true; // set up SF to handle added color layer if (isRemovedFromCurrentState()) { - mCurrentState.bgColorLayer->onRemovedFromCurrentState(); + mDrawingState.bgColorLayer->onRemovedFromCurrentState(); } mFlinger->setTransactionFlags(eTransactionNeeded); - } else if (mCurrentState.bgColorLayer && alpha == 0) { - mCurrentState.bgColorLayer->reparent(nullptr); - mCurrentState.bgColorLayer = nullptr; + } else if (mDrawingState.bgColorLayer && alpha == 0) { + mDrawingState.bgColorLayer->reparent(nullptr); + mDrawingState.bgColorLayer = nullptr; return true; } - mCurrentState.bgColorLayer->setColor(color); - mCurrentState.bgColorLayer->setLayer(std::numeric_limits::min()); - mCurrentState.bgColorLayer->setAlpha(alpha); - mCurrentState.bgColorLayer->setDataspace(dataspace); + mDrawingState.bgColorLayer->setColor(color); + mDrawingState.bgColorLayer->setLayer(std::numeric_limits::min()); + mDrawingState.bgColorLayer->setAlpha(alpha); + mDrawingState.bgColorLayer->setDataspace(dataspace); return true; } bool Layer::setCornerRadius(float cornerRadius) { - if (mCurrentState.cornerRadius == cornerRadius) return false; + if (mDrawingState.cornerRadius == cornerRadius) return false; - mCurrentState.sequence++; - mCurrentState.cornerRadius = cornerRadius; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.cornerRadius = cornerRadius; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) { - if (mCurrentState.backgroundBlurRadius == backgroundBlurRadius) return false; + if (mDrawingState.backgroundBlurRadius == backgroundBlurRadius) return false; - mCurrentState.sequence++; - mCurrentState.backgroundBlurRadius = backgroundBlurRadius; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.backgroundBlurRadius = backgroundBlurRadius; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1065,81 +939,82 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix, "ROTATE_SURFACE_FLINGER ignored"); return false; } - mCurrentState.sequence++; - mCurrentState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy); + mDrawingState.modified = true; + setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.requestedTransparentRegion_legacy = transparent; - mCurrentState.modified = true; + mDrawingState.requestedTransparentRegion_legacy = transparent; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setBlurRegions(const std::vector& blurRegions) { - mCurrentState.sequence++; - mCurrentState.blurRegions = blurRegions; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.blurRegions = blurRegions; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setFlags(uint32_t flags, uint32_t mask) { - const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); - if (mCurrentState.flags == newFlags) return false; - mCurrentState.sequence++; - mCurrentState.flags = newFlags; - mCurrentState.modified = true; + const uint32_t newFlags = (mDrawingState.flags & ~mask) | (flags & mask); + if (mDrawingState.flags == newFlags) return false; + mDrawingState.sequence++; + mDrawingState.flags = newFlags; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setCrop(const Rect& crop) { - if (mCurrentState.requestedCrop == crop) return false; - mCurrentState.sequence++; - mCurrentState.requestedCrop = crop; - mCurrentState.crop = crop; + if (mDrawingState.requestedCrop == crop) return false; + mDrawingState.sequence++; + mDrawingState.requestedCrop = crop; + mDrawingState.crop = crop; - mCurrentState.modified = true; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setMetadata(const LayerMetadata& data) { - if (!mCurrentState.metadata.merge(data, true /* eraseEmpty */)) return false; - mCurrentState.modified = true; + if (!mDrawingState.metadata.merge(data, true /* eraseEmpty */)) return false; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setLayerStack(uint32_t layerStack) { - if (mCurrentState.layerStack == layerStack) return false; - mCurrentState.sequence++; - mCurrentState.layerStack = layerStack; - mCurrentState.modified = true; + if (mDrawingState.layerStack == layerStack) return false; + mDrawingState.sequence++; + mDrawingState.layerStack = layerStack; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setColorSpaceAgnostic(const bool agnostic) { - if (mCurrentState.colorSpaceAgnostic == agnostic) { + if (mDrawingState.colorSpaceAgnostic == agnostic) { return false; } - mCurrentState.sequence++; - mCurrentState.colorSpaceAgnostic = agnostic; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.colorSpaceAgnostic = agnostic; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setFrameRateSelectionPriority(int32_t priority) { - if (mCurrentState.frameRateSelectionPriority == priority) return false; - mCurrentState.frameRateSelectionPriority = priority; - mCurrentState.sequence++; - mCurrentState.modified = true; + if (mDrawingState.frameRateSelectionPriority == priority) return false; + mDrawingState.frameRateSelectionPriority = priority; + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1171,25 +1046,25 @@ uint32_t Layer::getLayerStack() const { } bool Layer::setShadowRadius(float shadowRadius) { - if (mCurrentState.shadowRadius == shadowRadius) { + if (mDrawingState.shadowRadius == shadowRadius) { return false; } - mCurrentState.sequence++; - mCurrentState.shadowRadius = shadowRadius; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.shadowRadius = shadowRadius; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint) { - if (mCurrentState.fixedTransformHint == fixedTransformHint) { + if (mDrawingState.fixedTransformHint == fixedTransformHint) { return false; } - mCurrentState.sequence++; - mCurrentState.fixedTransformHint = fixedTransformHint; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.fixedTransformHint = fixedTransformHint; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1197,12 +1072,12 @@ bool Layer::setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHin bool Layer::setStretchEffect(const StretchEffect& effect) { StretchEffect temp = effect; temp.sanitize(); - if (mCurrentState.stretchEffect == temp) { + if (mDrawingState.stretchEffect == temp) { return false; } - mCurrentState.sequence++; - mCurrentState.stretchEffect = temp; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.stretchEffect = temp; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1239,12 +1114,12 @@ void Layer::updateTreeHasFrameRateVote() { int layersWithVote = 0; traverseTree([&layersWithVote](Layer* layer) { const auto layerVotedWithDefaultCompatibility = - layer->mCurrentState.frameRate.rate.isValid() && - layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default; + layer->mDrawingState.frameRate.rate.isValid() && + layer->mDrawingState.frameRate.type == FrameRateCompatibility::Default; const auto layerVotedWithNoVote = - layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote; + layer->mDrawingState.frameRate.type == FrameRateCompatibility::NoVote; const auto layerVotedWithExactCompatibility = - layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact; + layer->mDrawingState.frameRate.type == FrameRateCompatibility::Exact; // We do not count layers that are ExactOrMultiple for the same reason // we are allowing touch boost for those layers. See @@ -1258,6 +1133,7 @@ void Layer::updateTreeHasFrameRateVote() { // Now we can update the tree frame rate vote for each layer in the tree const bool treeHasFrameRateVote = layersWithVote > 0; bool transactionNeeded = false; + traverseTree([treeHasFrameRateVote, &transactionNeeded](Layer* layer) { transactionNeeded = layer->updateFrameRateForLayerTree(treeHasFrameRateVote); }); @@ -1271,13 +1147,13 @@ bool Layer::setFrameRate(FrameRate frameRate) { if (!mFlinger->useFrameRateApi) { return false; } - if (mCurrentState.frameRate == frameRate) { + if (mDrawingState.frameRate == frameRate) { return false; } - mCurrentState.sequence++; - mCurrentState.frameRate = frameRate; - mCurrentState.modified = true; + mDrawingState.sequence++; + mDrawingState.frameRate = frameRate; + mDrawingState.modified = true; updateTreeHasFrameRateVote(); @@ -1287,33 +1163,33 @@ bool Layer::setFrameRate(FrameRate frameRate) { void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { - mCurrentState.postTime = postTime; + mDrawingState.postTime = postTime; // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if // there are two transactions with the same token, the first one without a buffer and the // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX // in that case. - auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); - if (it != mCurrentState.bufferlessSurfaceFramesTX.end()) { + auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it != mDrawingState.bufferlessSurfaceFramesTX.end()) { // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX - mCurrentState.bufferSurfaceFrameTX = it->second; - mCurrentState.bufferlessSurfaceFramesTX.erase(it); - mCurrentState.bufferSurfaceFrameTX->promoteToBuffer(); - mCurrentState.bufferSurfaceFrameTX->setActualQueueTime(postTime); + mDrawingState.bufferSurfaceFrameTX = it->second; + mDrawingState.bufferlessSurfaceFramesTX.erase(it); + mDrawingState.bufferSurfaceFrameTX->promoteToBuffer(); + mDrawingState.bufferSurfaceFrameTX->setActualQueueTime(postTime); } else { - mCurrentState.bufferSurfaceFrameTX = + mDrawingState.bufferSurfaceFrameTX = createSurfaceFrameForBuffer(info, postTime, mTransactionName); } } void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info, nsecs_t postTime) { - mCurrentState.frameTimelineInfo = info; - mCurrentState.postTime = postTime; - mCurrentState.modified = true; + mDrawingState.frameTimelineInfo = info; + mDrawingState.postTime = postTime; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); - if (const auto& bufferSurfaceFrameTX = mCurrentState.bufferSurfaceFrameTX; + if (const auto& bufferSurfaceFrameTX = mDrawingState.bufferSurfaceFrameTX; bufferSurfaceFrameTX != nullptr) { if (bufferSurfaceFrameTX->getToken() == info.vsyncId) { // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is @@ -1324,10 +1200,10 @@ void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInf // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are // targeting different vsyncs). - auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId); - if (it == mCurrentState.bufferlessSurfaceFramesTX.end()) { + auto it = mDrawingState.bufferlessSurfaceFramesTX.find(info.vsyncId); + if (it == mDrawingState.bufferlessSurfaceFramesTX.end()) { auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime); - mCurrentState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame; + mDrawingState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame; } else { if (it->second->getPresentState() == PresentState::Presented) { // If the SurfaceFrame was already presented, its safe to overwrite it since it must @@ -1389,36 +1265,41 @@ std::shared_ptr Layer::createSurfaceFrameForBuffer( } bool Layer::updateFrameRateForLayerTree(bool treeHasFrameRateVote) { - const auto updateCurrentState = [&](FrameRate frameRate) { - if (mCurrentState.frameRateForLayerTree == frameRate) { + const auto updateDrawingState = [&](FrameRate frameRate) { + if (mDrawingState.frameRateForLayerTree == frameRate) { return false; } - mCurrentState.frameRateForLayerTree = frameRate; - mCurrentState.sequence++; - mCurrentState.modified = true; + + mDrawingState.frameRateForLayerTree = frameRate; + mDrawingState.sequence++; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); + + mFlinger->mScheduler->recordLayerHistory(this, systemTime(), + LayerHistory::LayerUpdateType::SetFrameRate); + return true; }; - const auto frameRate = mCurrentState.frameRate; + const auto frameRate = mDrawingState.frameRate; if (frameRate.rate.isValid() || frameRate.type == FrameRateCompatibility::NoVote) { - return updateCurrentState(frameRate); + return updateDrawingState(frameRate); } // This layer doesn't have a frame rate. Check if its ancestors have a vote for (sp parent = getParent(); parent; parent = parent->getParent()) { - if (parent->mCurrentState.frameRate.rate.isValid()) { - return updateCurrentState(parent->mCurrentState.frameRate); + if (parent->mDrawingState.frameRate.rate.isValid()) { + return updateDrawingState(parent->mDrawingState.frameRate); } } // This layer and its ancestors don't have a frame rate. If one of successors // has a vote, return a NoVote for successors to set the vote if (treeHasFrameRateVote) { - return updateCurrentState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote)); + return updateDrawingState(FrameRate(Fps(0.0f), FrameRateCompatibility::NoVote)); } - return updateCurrentState(frameRate); + return updateDrawingState(frameRate); } Layer::FrameRate Layer::getFrameRateForLayerTree() const { @@ -1670,7 +1551,7 @@ size_t Layer::getChildrenCount() const { void Layer::setGameModeForTree(int parentGameMode) { int gameMode = parentGameMode; - auto& currentState = getCurrentState(); + auto& currentState = getDrawingState(); if (currentState.metadata.has(METADATA_GAME_MODE)) { gameMode = currentState.metadata.getInt32(METADATA_GAME_MODE, 0); } @@ -1749,13 +1630,13 @@ bool Layer::reparent(const sp& newParentHandle) { bool Layer::setColorTransform(const mat4& matrix) { static const mat4 identityMatrix = mat4(); - if (mCurrentState.colorTransform == matrix) { + if (mDrawingState.colorTransform == matrix) { return false; } - ++mCurrentState.sequence; - mCurrentState.colorTransform = matrix; - mCurrentState.hasColorTransform = matrix != identityMatrix; - mCurrentState.modified = true; + ++mDrawingState.sequence; + mDrawingState.colorTransform = matrix; + mDrawingState.hasColorTransform = matrix != identityMatrix; + mDrawingState.modified = true; setTransactionFlags(eTransactionNeeded); return true; } @@ -1787,15 +1668,13 @@ void Layer::setParent(const sp& layer) { mCurrentParent = layer; } -int32_t Layer::getZ(LayerVector::StateSet stateSet) const { - const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; - const State& state = useDrawing ? mDrawingState : mCurrentState; - return state.z; +int32_t Layer::getZ(LayerVector::StateSet) const { + return mDrawingState.z; } bool Layer::usingRelativeZ(LayerVector::StateSet stateSet) const { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; - const State& state = useDrawing ? mDrawingState : mCurrentState; + const State& state = useDrawing ? mDrawingState : mDrawingState; return state.isRelativeOf; } @@ -1805,7 +1684,7 @@ __attribute__((no_sanitize("unsigned-integer-overflow"))) LayerVector Layer::mak "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mCurrentState; + const State& state = useDrawing ? mDrawingState : mDrawingState; if (state.zOrderRelatives.size() == 0) { *outSkipRelativeZUsers = true; @@ -1904,7 +1783,7 @@ void Layer::traverseInReverseZOrder(LayerVector::StateSet stateSet, void Layer::traverse(LayerVector::StateSet state, const LayerVector::Visitor& visitor) { visitor(this); const LayerVector& children = - state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren; + state == LayerVector::StateSet::Drawing ? mDrawingChildren : mCurrentChildren; for (const sp& child : children) { child->traverse(state, visitor); } @@ -1916,7 +1795,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, "makeTraversalList received invalid stateSet"); const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mCurrentState; + const State& state = useDrawing ? mDrawingState : mDrawingState; LayerVector traverse(stateSet); for (const wp& weakRelative : state.zOrderRelatives) { @@ -1929,7 +1808,7 @@ LayerVector Layer::makeChildrenTraversalList(LayerVector::StateSet stateSet, } for (const sp& child : children) { - const State& childState = useDrawing ? child->mDrawingState : child->mCurrentState; + const State& childState = useDrawing ? child->mDrawingState : child->mDrawingState; // If a layer has a relativeOf layer, only ignore if the layer it's relative to is a // descendent of the top most parent of the tree. If it's not a descendent, then just add // the child here since it won't be added later as a relative. @@ -1997,7 +1876,7 @@ half Layer::getAlpha() const { } ui::Transform::RotationFlags Layer::getFixedTransformHint() const { - ui::Transform::RotationFlags fixedTransformHint = mCurrentState.fixedTransformHint; + ui::Transform::RotationFlags fixedTransformHint = mDrawingState.fixedTransformHint; if (fixedTransformHint != ui::Transform::ROT_INVALID) { return fixedTransformHint; } @@ -2109,10 +1988,10 @@ static wp extractLayerFromBinder(const wp& weakBinderHandle) { } void Layer::setInputInfo(const InputWindowInfo& info) { - mCurrentState.inputInfo = info; - mCurrentState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle); - mCurrentState.modified = true; - mCurrentState.inputInfoChanged = true; + mDrawingState.inputInfo = info; + mDrawingState.touchableRegionCrop = extractLayerFromBinder(info.touchableRegionCropHandle); + mDrawingState.modified = true; + mDrawingState.inputInfoChanged = true; setTransactionFlags(eTransactionNeeded); } @@ -2190,7 +2069,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet uint32_t traceFlags) { const bool useDrawing = stateSet == LayerVector::StateSet::Drawing; const LayerVector& children = useDrawing ? mDrawingChildren : mCurrentChildren; - const State& state = useDrawing ? mDrawingState : mCurrentState; + const State& state = useDrawing ? mDrawingState : mDrawingState; ui::Transform requestedTransform = state.transform; @@ -2278,7 +2157,7 @@ void Layer::writeToProtoCommonState(LayerProto* layerInfo, LayerVector::StateSet } bool Layer::isRemovedFromCurrentState() const { - return mRemovedFromCurrentState; + return mRemovedFromDrawingState; } ui::Transform Layer::getInputTransform() const { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 5669049512..9b30fcb315 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1,3 +1,4 @@ + /* * Copyright (C) 2007 The Android Open Source Project * @@ -732,8 +733,7 @@ public: void updateTransformHint(ui::Transform::RotationFlags); inline const State& getDrawingState() const { return mDrawingState; } - inline const State& getCurrentState() const { return mCurrentState; } - inline State& getCurrentState() { return mCurrentState; } + inline State& getDrawingState() { return mDrawingState; } LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const; @@ -884,7 +884,7 @@ public: virtual bool setDestinationFrame(const Rect& /* destinationFrame */) { return false; } virtual std::atomic* getPendingBufferCounter() { return nullptr; } virtual std::string getPendingBufferCounterName() { return ""; } - virtual void updateGeometry() {} + virtual bool updateGeometry() { return false; } protected: friend class impl::SurfaceInterceptor; @@ -902,7 +902,6 @@ protected: compositionengine::LayerFE::ClientCompositionTargetSettings&); virtual void preparePerFrameCompositionState(); virtual void commitTransaction(State& stateToCommit); - virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit); virtual void onSurfaceFrameCreated(const std::shared_ptr&) {} // Returns mCurrentScaling mode (originating from the @@ -958,9 +957,11 @@ protected: // These are only accessed by the main thread or the tracing thread. State mDrawingState; - // these are protected by an external lock (mStateLock) - State mCurrentState; uint32_t mTransactionFlags{0}; + // Updated in doTransaction, used to track the last sequence number we + // committed. Currently this is really only used for updating visible + // regions. + int32_t mLastCommittedTxSequence = -1; // Timestamp history for UIAutomation. Thread safe. FrameTracker mFrameTracker; @@ -983,7 +984,7 @@ protected: // Whether filtering is needed b/c of the drawingstate bool mNeedsFiltering{false}; - std::atomic mRemovedFromCurrentState{false}; + std::atomic mRemovedFromDrawingState{false}; // page-flip thread (currently main thread) bool mProtectedByApp{false}; // application requires protected path to external sink @@ -996,9 +997,7 @@ protected: // This layer can be a cursor on some displays. bool mPotentialCursor{false}; - // Child list about to be committed/used for editing. - LayerVector mCurrentChildren{LayerVector::StateSet::Current}; - // Child list used for rendering. + LayerVector mCurrentChildren{LayerVector::StateSet::Drawing}; LayerVector mDrawingChildren{LayerVector::StateSet::Drawing}; wp mCurrentParent; @@ -1022,7 +1021,7 @@ protected: // Used in buffer stuffing analysis in FrameTimeline. nsecs_t mLastLatchTime = 0; - mutable bool mCurrentStateModified = false; + mutable bool mDrawingStateModified = false; private: virtual void setTransformHint(ui::Transform::RotationFlags) {} diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 9b94920408..aee820a88c 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -42,10 +42,8 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const const auto& l = *reinterpret_cast*>(lhs); const auto& r = *reinterpret_cast*>(rhs); - const auto& lState = - (mStateSet == StateSet::Current) ? l->getCurrentState() : l->getDrawingState(); - const auto& rState = - (mStateSet == StateSet::Current) ? r->getCurrentState() : r->getDrawingState(); + const auto& lState = l->getDrawingState(); + const auto& rState = r->getDrawingState(); uint32_t ls = lState.layerStack; uint32_t rs = rState.layerStack; @@ -66,8 +64,7 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) const { for (size_t i = 0; i < size(); i++) { const auto& layer = (*this)[i]; - auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState() - : layer->getDrawingState(); + auto& state = layer->getDrawingState(); if (state.isRelativeOf) { continue; } @@ -78,8 +75,7 @@ void LayerVector::traverseInZOrder(StateSet stateSet, const Visitor& visitor) co void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visitor) const { for (auto i = static_cast(size()) - 1; i >= 0; i--) { const auto& layer = (*this)[i]; - auto& state = (stateSet == StateSet::Current) ? layer->getCurrentState() - : layer->getDrawingState(); + auto& state = layer->getDrawingState(); if (state.isRelativeOf) { continue; } diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index a9fd16cb75..663e62a2f5 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -199,10 +199,10 @@ bool RefreshRateOverlay::createLayer() { mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote)); // setting Layer's Z requires resorting layersSortedByZ - ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); + ssize_t idx = mFlinger.mDrawingState.layersSortedByZ.indexOf(mLayer); if (mLayer->setLayer(INT32_MAX - 2) && idx >= 0) { - mFlinger.mCurrentState.layersSortedByZ.removeAt(idx); - mFlinger.mCurrentState.layersSortedByZ.add(mLayer); + mFlinger.mDrawingState.layersSortedByZ.removeAt(idx); + mFlinger.mDrawingState.layersSortedByZ.add(mLayer); } return true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e7187b1381..317b4f6bc3 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3200,6 +3200,7 @@ void SurfaceFlinger::setVsyncConfig(const VsyncModulator::VsyncConfig& config, } void SurfaceFlinger::commitTransaction() { + ATRACE_CALL(); commitTransactionLocked(); signalSynchronousTransactions(CountDownLatch::eSyncTransaction); mAnimTransactionPending = false; @@ -6050,12 +6051,12 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, } if (!canCaptureBlackoutContent && - parent->getCurrentState().flags & layer_state_t::eLayerSecure) { + parent->getDrawingState().flags & layer_state_t::eLayerSecure) { ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); return PERMISSION_DENIED; } - Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getCurrentState()); + Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getDrawingState()); if (args.sourceCrop.width() <= 0) { crop.left = 0; crop.right = parentSourceBounds.getWidth(); @@ -6294,7 +6295,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( Region clearRegion = Region::INVALID_REGION; bool disableBlurs = false; traverseLayers([&](Layer* layer) { - disableBlurs |= layer->getCurrentState().sidebandStream != nullptr; + disableBlurs |= layer->getDrawingState().sidebandStream != nullptr; Region clip(renderArea.getBounds()); compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{ diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index c5f1598d15..8ca241e53d 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -130,25 +130,25 @@ void SurfaceInterceptor::addInitialSurfaceStateLocked(Increment* increment, transaction->set_animation(layerFlags & BnSurfaceComposer::eAnimation); const int32_t layerId(getLayerId(layer)); - addPositionLocked(transaction, layerId, layer->mCurrentState.transform.tx(), - layer->mCurrentState.transform.ty()); - addDepthLocked(transaction, layerId, layer->mCurrentState.z); - addAlphaLocked(transaction, layerId, layer->mCurrentState.color.a); + addPositionLocked(transaction, layerId, layer->mDrawingState.transform.tx(), + layer->mDrawingState.transform.ty()); + addDepthLocked(transaction, layerId, layer->mDrawingState.z); + addAlphaLocked(transaction, layerId, layer->mDrawingState.color.a); addTransparentRegionLocked(transaction, layerId, - layer->mCurrentState.activeTransparentRegion_legacy); - addLayerStackLocked(transaction, layerId, layer->mCurrentState.layerStack); - addCropLocked(transaction, layerId, layer->mCurrentState.crop); - addCornerRadiusLocked(transaction, layerId, layer->mCurrentState.cornerRadius); - addBackgroundBlurRadiusLocked(transaction, layerId, layer->mCurrentState.backgroundBlurRadius); - addBlurRegionsLocked(transaction, layerId, layer->mCurrentState.blurRegions); - addFlagsLocked(transaction, layerId, layer->mCurrentState.flags, + layer->mDrawingState.activeTransparentRegion_legacy); + addLayerStackLocked(transaction, layerId, layer->mDrawingState.layerStack); + addCropLocked(transaction, layerId, layer->mDrawingState.crop); + addCornerRadiusLocked(transaction, layerId, layer->mDrawingState.cornerRadius); + addBackgroundBlurRadiusLocked(transaction, layerId, layer->mDrawingState.backgroundBlurRadius); + addBlurRegionsLocked(transaction, layerId, layer->mDrawingState.blurRegions); + addFlagsLocked(transaction, layerId, layer->mDrawingState.flags, layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque | layer_state_t::eLayerSecure); - addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent)); + addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mDrawingParent)); addRelativeParentLocked(transaction, layerId, - getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf), - layer->mCurrentState.z); - addShadowRadiusLocked(transaction, layerId, layer->mCurrentState.shadowRadius); + getLayerIdFromWeakRef(layer->mDrawingState.zOrderRelativeOf), + layer->mDrawingState.z); + addShadowRadiusLocked(transaction, layerId, layer->mDrawingState.shadowRadius); } void SurfaceInterceptor::addInitialDisplayStateLocked(Increment* increment, @@ -511,8 +511,8 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); creation->set_name(layer->getName()); - creation->set_w(layer->mCurrentState.active_legacy.w); - creation->set_h(layer->mCurrentState.active_legacy.h); + creation->set_w(layer->mDrawingState.active_legacy.w); + creation->set_h(layer->mDrawingState.active_legacy.h); } void SurfaceInterceptor::addSurfaceDeletionLocked(Increment* increment, diff --git a/services/surfaceflinger/TunnelModeEnabledReporter.cpp b/services/surfaceflinger/TunnelModeEnabledReporter.cpp index 1b3ddf7a00..48e321635b 100644 --- a/services/surfaceflinger/TunnelModeEnabledReporter.cpp +++ b/services/surfaceflinger/TunnelModeEnabledReporter.cpp @@ -31,8 +31,8 @@ TunnelModeEnabledReporter::TunnelModeEnabledReporter(SurfaceFlinger& flinger) : void TunnelModeEnabledReporter::updateTunnelModeStatus() { bool tunnelModeEnabled = false; mFlinger.mCurrentState.traverse([&](Layer* layer) { - auto& currentState = layer->getCurrentState(); - if (currentState.sidebandStream != nullptr) { + auto& state = layer->getDrawingState(); + if (state.sidebandStream != nullptr) { tunnelModeEnabled = true; return; } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp index fd3e564cd9..35033ea545 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -116,7 +116,7 @@ void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { } void RefreshRateSelectionTest::commitTransaction(Layer* layer) { - auto c = layer->getCurrentState(); + auto c = layer->getDrawingState(); layer->commitTransaction(c); } diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp index 46ef75091e..1ed52ea389 100644 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp @@ -152,7 +152,7 @@ void SetFrameRateTest::removeChild(sp layer, sp child) { void SetFrameRateTest::commitTransaction() { for (auto layer : mLayers) { - auto c = layer->getCurrentState(); + auto c = layer->getDrawingState(); layer->commitTransaction(c); } } diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp index 061443479e..e2be074fc4 100644 --- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DestroyDisplayTest.cpp @@ -74,4 +74,4 @@ TEST_F(DestroyDisplayTest, destroyDisplayHandlesUnknownDisplay) { } } // namespace -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index b363146e10..7f6e05ec9f 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -259,7 +259,6 @@ public: memcpy(&mFlinger->mInternalDisplayPrimaries, &primaries, sizeof(ui::DisplayPrimaries)); } - static auto& mutableLayerCurrentState(const sp& layer) { return layer->mCurrentState; } static auto& mutableLayerDrawingState(const sp& layer) { return layer->mDrawingState; } auto& mutableStateLock() { return mFlinger->mStateLock; } @@ -272,7 +271,6 @@ public: static void setLayerSidebandStream(const sp& layer, const sp& sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; - layer->mCurrentState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; layer->editCompositionState()->sidebandStream = sidebandStream; } diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index 546bc4a17b..2845d0ab14 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -62,7 +62,7 @@ public: } void commitTransaction(Layer* layer) { - auto c = layer->getCurrentState(); + auto c = layer->getDrawingState(); layer->commitTransaction(c); } diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index c1123cd6e8..7bf224d557 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -62,7 +62,7 @@ public: } void commitTransaction(Layer* layer) { - auto c = layer->getCurrentState(); + auto c = layer->getDrawingState(); layer->commitTransaction(c); } @@ -101,9 +101,9 @@ public: sp layer = createBufferStateLayer(); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, 10); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_TRUE(layer->mCurrentState.bufferSurfaceFrameTX == nullptr); - const auto surfaceFrame = layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_TRUE(layer->mDrawingState.bufferSurfaceFrameTX == nullptr); + const auto surfaceFrame = layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1); commitTransaction(layer.get()); EXPECT_EQ(1, surfaceFrame->getToken()); EXPECT_EQ(false, surfaceFrame->getIsBuffer()); @@ -123,9 +123,9 @@ public: acquireFence->signalForTest(12); commitTransaction(layer.get()); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto surfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; // Buffers are presented only at latch time. EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState()); @@ -148,9 +148,9 @@ public: mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); @@ -164,9 +164,9 @@ public: nsecs_t end = systemTime(); acquireFence2->signalForTest(12); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); bool computeVisisbleRegions; @@ -190,8 +190,8 @@ public: layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, 10); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); @@ -203,9 +203,9 @@ public: {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence->signalForTest(12); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto surfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); EXPECT_EQ(1, surfaceFrame->getToken()); @@ -229,29 +229,29 @@ public: mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, 10); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); } void MultipleSurfaceFramesPresentedTogether() { sp layer = createBufferStateLayer(); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0}, 10); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); + EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto bufferlessSurfaceFrame1 = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1); + layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0}, 10); - EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto bufferlessSurfaceFrame2 = layer->mCurrentState.bufferlessSurfaceFramesTX[4]; + EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto bufferlessSurfaceFrame2 = layer->mDrawingState.bufferlessSurfaceFramesTX[4]; sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); @@ -261,9 +261,9 @@ public: mRenderEngine, false); layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); - EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX; acquireFence->signalForTest(12); @@ -299,8 +299,8 @@ public: mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); @@ -312,8 +312,8 @@ public: {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); acquireFence2->signalForTest(12); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); bool computeVisisbleRegions; @@ -340,9 +340,9 @@ public: mRenderEngine, false); layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto droppedSurfaceFrame1 = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); @@ -355,9 +355,9 @@ public: {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */); auto dropEndTime1 = systemTime(); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto droppedSurfaceFrame2 = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto droppedSurfaceFrame2 = layer->mDrawingState.bufferSurfaceFrameTX; sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); @@ -371,9 +371,9 @@ public: auto dropEndTime2 = systemTime(); acquireFence3->signalForTest(12); - EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX; + EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + const auto presentedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; commitTransaction(layer.get()); bool computeVisisbleRegions; @@ -415,10 +415,10 @@ public: layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, 10); - ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX); - EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size()); + ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); + EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); auto& bufferlessSurfaceFrame = - layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2); + layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*vsyncId*/ 2); bufferlessSurfaceFrames.push_back(bufferlessSurfaceFrame); commitTransaction(layer.get()); -- cgit v1.2.3-59-g8ed1b From 14d218b589719842142dd7455484f80025fb63f3 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Tue, 13 Jul 2021 13:57:39 -0700 Subject: SF: Avoid promoting parent layer in binder thread Some components in SF extend the life cycle of layer objects causing them to be destroyed without the state lock held. If a binder thread promotes a layer, there is a chance it will be left holding the last reference. This will cause the layer to be destroyed in the binder thread, resulting in invalid accesses and crashes. Fix this by tracking root layers with a variable to avoid promoting parent layer in binder thread. Test: presubmit, manually test refresh rate overlay Test: go/wm-smoke Fixes: 186412934 Change-Id: Icd9f4e851bbd92c887e113e52505ce4d8eb3ea0c --- services/surfaceflinger/Layer.h | 7 +++++++ services/surfaceflinger/RefreshRateOverlay.cpp | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 5 ++++- 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'services/surfaceflinger/RefreshRateOverlay.cpp') diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e726d379d6..6b56b2d924 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -796,6 +796,11 @@ public: // for symmetry with Vector::remove ssize_t removeChild(const sp& layer); sp getParent() const { return mCurrentParent.promote(); } + + // Should be called with the surfaceflinger statelock held + bool isAtRoot() const { return mIsAtRoot; } + void setIsAtRoot(bool isAtRoot) { mIsAtRoot = isAtRoot; } + bool hasParent() const { return getParent() != nullptr; } Rect getScreenBounds(bool reduceTransparentRegion = true) const; bool setChildLayer(const sp& childLayer, int32_t z); @@ -1103,6 +1108,8 @@ private: // A list of regions on this layer that should have blurs. const std::vector getBlurRegions() const; + + bool mIsAtRoot = false; }; std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate); diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 663e62a2f5..27a1c280fb 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -197,6 +197,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); mLayer->setFrameRate(Layer::FrameRate(Fps(0.0f), Layer::FrameRateCompatibility::NoVote)); + mLayer->setIsAtRoot(true); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mDrawingState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 2650fa0583..72700162ba 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4181,6 +4181,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( : nullptr; if (layer->reparent(parentHandle)) { if (!hadParent) { + layer->setIsAtRoot(false); mCurrentState.layersSortedByZ.remove(layer); } flags |= eTransactionNeeded | eTraversalNeeded; @@ -4447,7 +4448,8 @@ void SurfaceFlinger::onHandleDestroyed(sp& layer) { // with the idea that the parent holds a reference and will eventually // be cleaned up. However no one cleans up the top-level so we do so // here. - if (layer->getParent() == nullptr) { + if (layer->isAtRoot()) { + layer->setIsAtRoot(false); mCurrentState.layersSortedByZ.remove(layer); } markLayerPendingRemovalLocked(layer); @@ -6924,6 +6926,7 @@ sp SurfaceFlinger::handleLayerCreatedLocked(const sp& handle, bo } if (parent == nullptr && allowAddRoot) { + layer->setIsAtRoot(true); mCurrentState.layersSortedByZ.add(layer); } else if (parent == nullptr) { layer->onRemovedFromCurrentState(); -- cgit v1.2.3-59-g8ed1b