From e0e0cde7fa7d4dc34fb68c862f4a255d7d3252c7 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Fri, 30 Jul 2021 10:42:05 -0700 Subject: SF: Decouple MessageQueue Define an ICompositor interface against which MessageQueue (which ought to be an implementation detail of Scheduler) is implemented. Change the equivocal invalidate/refresh nomenclature to commit/composite. Schedule sampling only after composite. Bug: 185535769 Test: libsurfaceflinger_unittest Change-Id: I0c18f312459bae48531449f24f7b53c104fc5812 --- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index aa2fec56ad..9465b197b2 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -150,7 +150,7 @@ void RegionSamplingThread::checkForStaleLuma() { if (mSampleRequestTime.has_value()) { ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::waitForSamplePhase)); mSampleRequestTime.reset(); - mFlinger.scheduleRegionSamplingThread(); + mFlinger.scheduleSample(); } } -- cgit v1.2.3-59-g8ed1b From 59a9f506c7293fdee01482a4bb532df953600d4c Mon Sep 17 00:00:00 2001 From: Sally Qi Date: Tue, 12 Oct 2021 18:53:23 +0000 Subject: Revert^2 "Second Patch for async RenderEngine" Keep the change of Second Patch for async RenderEngine and fix the regression - remove the vector variables which is to store futureFence locally in BufferStateLayer to get avoid fd leaking - screenshots initiated from the app don't wait on the SF main thread. 2109270e74a18585aceffc94d1758cee47bb4175 Bug: 202843200 Bug: 202833127 Bug: 202808760 Test: Wembley PIN setting test, NexusLauncherOutOfProcTests Change-Id: I87847d01e2e330ddec88272cd8608f0b78c0a2cd --- libs/renderengine/RenderEngine.cpp | 2 +- libs/renderengine/gl/GLESRenderEngine.cpp | 66 +++++----- libs/renderengine/gl/GLESRenderEngine.h | 2 +- .../include/renderengine/RenderEngine.h | 4 +- .../include/renderengine/mock/RenderEngine.h | 4 +- libs/renderengine/skia/Cache.cpp | 16 +-- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 113 +++++++++-------- libs/renderengine/skia/SkiaGLRenderEngine.h | 7 +- libs/renderengine/skia/SkiaRenderEngine.h | 2 +- libs/renderengine/tests/RenderEngineTest.cpp | 125 +++++++++---------- .../tests/RenderEngineThreadedTest.cpp | 7 +- .../renderengine/threaded/RenderEngineThreaded.cpp | 11 +- libs/renderengine/threaded/RenderEngineThreaded.h | 4 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 88 +++----------- services/surfaceflinger/BufferStateLayer.h | 7 +- .../include/compositionengine/LayerFE.h | 4 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 23 ++-- .../CompositionEngine/src/planner/CachedSet.cpp | 17 +-- .../CompositionEngine/tests/OutputTest.cpp | 87 +++++++++----- .../tests/planner/CachedSetTest.cpp | 84 ++++++------- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 11 +- services/surfaceflinger/SurfaceFlinger.cpp | 133 +++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 22 ++-- .../surfaceflinger/TransactionCallbackInvoker.cpp | 32 +++++ .../surfaceflinger/TransactionCallbackInvoker.h | 6 +- .../tests/unittests/CompositionTest.cpp | 78 ++++++------ 31 files changed, 513 insertions(+), 457 deletions(-) (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 2174df5515..a9ea690a7c 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -96,7 +96,7 @@ void RenderEngine::validateOutputBufferUsage(const sp& buffer) { } std::future RenderEngine::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { const auto resultPromise = std::make_shared>(); diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 2375cb7bf1..22dd86698b 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1080,7 +1080,7 @@ EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer void GLESRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); @@ -1110,10 +1110,10 @@ void GLESRenderEngine::drawLayersInternal( std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. - std::deque blurLayers; + std::deque blurLayers; if (CC_LIKELY(mBlurFilter != nullptr)) { - for (auto layer : layers) { - if (layer->backgroundBlurRadius > 0) { + for (const auto& layer : layers) { + if (layer.backgroundBlurRadius > 0) { blurLayers.push_back(layer); } } @@ -1137,7 +1137,7 @@ void GLESRenderEngine::drawLayersInternal( } else { setViewportAndProjection(display.physicalDisplay, display.clip); auto status = - mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius); + 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); @@ -1167,7 +1167,7 @@ void GLESRenderEngine::drawLayersInternal( .setTexCoords(2 /* size */) .setCropCoords(2 /* size */) .build(); - for (auto const layer : layers) { + for (const auto& layer : layers) { if (blurLayers.size() > 0 && blurLayers.front() == layer) { blurLayers.pop_front(); @@ -1193,7 +1193,7 @@ void GLESRenderEngine::drawLayersInternal( // There's still something else to blur, so let's keep rendering to our FBO // instead of to the display. status = mBlurFilter->setAsDrawTarget(display, - blurLayers.front()->backgroundBlurRadius); + blurLayers.front().backgroundBlurRadius); } if (status != NO_ERROR) { ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).", @@ -1214,42 +1214,42 @@ void GLESRenderEngine::drawLayersInternal( } // Ensure luminance is at least 100 nits to avoid div-by-zero - const float maxLuminance = std::max(100.f, layer->source.buffer.maxLuminanceNits); + const float maxLuminance = std::max(100.f, layer.source.buffer.maxLuminanceNits); mState.maxMasteringLuminance = maxLuminance; mState.maxContentLuminance = maxLuminance; - mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform; + mState.projectionMatrix = projectionMatrix * layer.geometry.positionTransform; - const FloatRect bounds = layer->geometry.boundaries; + const FloatRect bounds = layer.geometry.boundaries; Mesh::VertexArray position(mesh.getPositionArray()); position[0] = vec2(bounds.left, bounds.top); position[1] = vec2(bounds.left, bounds.bottom); position[2] = vec2(bounds.right, bounds.bottom); position[3] = vec2(bounds.right, bounds.top); - setupLayerCropping(*layer, mesh); - setColorTransform(layer->colorTransform); + setupLayerCropping(layer, mesh); + setColorTransform(layer.colorTransform); bool usePremultipliedAlpha = true; bool disableTexture = true; bool isOpaque = false; - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableTexture = false; - isOpaque = layer->source.buffer.isOpaque; + isOpaque = layer.source.buffer.isOpaque; - sp gBuf = layer->source.buffer.buffer->getBuffer(); + sp gBuf = layer.source.buffer.buffer->getBuffer(); validateInputBufferUsage(gBuf); - bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, - layer->source.buffer.fence); + bindExternalTextureBuffer(layer.source.buffer.textureName, gBuf, + layer.source.buffer.fence); - usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha; - Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName); - mat4 texMatrix = layer->source.buffer.textureTransform; + usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha; + Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName); + mat4 texMatrix = layer.source.buffer.textureTransform; texture.setMatrix(texMatrix.asArray()); - texture.setFiltering(layer->source.buffer.useTextureFiltering); + texture.setFiltering(layer.source.buffer.useTextureFiltering); texture.setDimensions(gBuf->getWidth(), gBuf->getHeight()); - setSourceY410BT2020(layer->source.buffer.isY410BT2020); + setSourceY410BT2020(layer.source.buffer.isY410BT2020); renderengine::Mesh::VertexArray texCoords(mesh.getTexCoordArray()); texCoords[0] = vec2(0.0, 0.0); @@ -1264,32 +1264,32 @@ void GLESRenderEngine::drawLayersInternal( } } - const half3 solidColor = layer->source.solidColor; - const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha); + const half3 solidColor = layer.source.solidColor; + const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha); // Buffer sources will have a black solid color ignored in the shader, // so in that scenario the solid color passed here is arbitrary. setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, - layer->geometry.roundedCornersRadius); - if (layer->disableBlending) { + layer.geometry.roundedCornersRadius); + if (layer.disableBlending) { glDisable(GL_BLEND); } - setSourceDataSpace(layer->sourceDataspace); + setSourceDataSpace(layer.sourceDataspace); - if (layer->shadow.length > 0.0f) { - handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius, - layer->shadow); + if (layer.shadow.length > 0.0f) { + handleShadow(layer.geometry.boundaries, layer.geometry.roundedCornersRadius, + layer.shadow); } // We only want to do a special handling for rounded corners when having rounded corners // is the only reason it needs to turn on blending, otherwise, we handle it like the // usual way since it needs to turn on blending anyway. - else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { - handleRoundedCorners(display, *layer, mesh); + else if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) { + handleRoundedCorners(display, layer, mesh); } else { drawMesh(mesh); } // Cleanup if there's a buffer source - if (layer->source.buffer.buffer != nullptr) { + if (layer.source.buffer.buffer != nullptr) { disableBlending(); setSourceY410BT2020(false); disableTexturing(); diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index c4adfdf752..1d7c2cafb5 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -104,7 +104,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 701c1f2071..b9cc6485e5 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -160,7 +160,7 @@ public: // @return A future object of RenderEngineResult struct indicating whether // drawing was successful in async mode. virtual std::future drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence); @@ -231,7 +231,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) = 0; }; diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index a7e6809223..248bd652c0 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -49,12 +49,12 @@ public: MOCK_CONST_METHOD0(canSkipPostRenderCleanup, bool()); MOCK_METHOD5(drawLayers, std::future(const DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD6(drawLayersInternal, void(const std::shared_ptr>&&, - const DisplaySettings&, const std::vector&, + const DisplaySettings&, const std::vector&, const std::shared_ptr&, const bool, base::unique_fd&&)); MOCK_METHOD0(cleanFramebufferCache, void()); MOCK_METHOD0(getContextPriority, int()); diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index c4fa1bb091..b18a872836 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -95,7 +95,7 @@ static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettin .alpha = 1, }; - auto layers = std::vector{&layer, &caster}; + auto layers = std::vector{layer, caster}; // Four combinations of settings are used (two transforms here, and drawShadowLayers is // called with two different destination data spaces) They're all rounded rect. // Three of these are cache misses that generate new shaders. @@ -140,7 +140,7 @@ static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySetting }}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { layer.sourceDataspace = dataspace; // Cache shaders for both rects and round rects. @@ -176,7 +176,7 @@ static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySetting .alpha = 0.5, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto transform : {mat4(), kScaleAndTranslate}) { layer.geometry.positionTransform = transform; for (float roundedCornersRadius : {0.0f, 50.f}) { @@ -201,7 +201,7 @@ static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings .skipContentDraw = true, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // Different blur code is invoked for radii less and greater than 30 pixels for (int radius : {9, 60}) { layer.backgroundBlurRadius = radius; @@ -242,7 +242,7 @@ static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySetti }, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; for (auto pixelSource : {bufferSource, bufferOpaque, colorSource}) { layer.source = pixelSource; for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) { @@ -289,7 +289,7 @@ static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySetti }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -317,7 +317,7 @@ static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySett }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()); } @@ -429,7 +429,7 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { LayerSettings layer{ .source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)}, }; - auto layers = std::vector{&layer}; + auto layers = std::vector{layer}; // call get() to make it synchronous renderengine ->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd()) diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index cb686a643a..d5ec774e9c 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -610,17 +610,18 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; -sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( - sk_sp shader, - const LayerSettings* layer, const DisplaySettings& display, bool undoPremultipliedAlpha, - bool requiresLinearEffect) { - const auto stretchEffect = layer->stretchEffect; +sk_sp SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp shader, + const LayerSettings& layer, + const DisplaySettings& display, + bool undoPremultipliedAlpha, + bool requiresLinearEffect) { + const auto stretchEffect = layer.stretchEffect; // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger if (stretchEffect.hasEffect()) { - const auto targetBuffer = layer->source.buffer.buffer; + const auto targetBuffer = layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); @@ -629,7 +630,7 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( if (requiresLinearEffect) { const ui::Dataspace inputDataspace = - mUseColorManagement ? layer->sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; + mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; @@ -645,13 +646,13 @@ sk_sp SkiaGLRenderEngine::createRuntimeEffectShader( } else { runtimeEffect = effectIter->second; } - float maxLuminance = layer->source.buffer.maxLuminanceNits; + float maxLuminance = layer.source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } - return createLinearEffectShader(shader, effect, runtimeEffect, layer->colorTransform, + return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, display.maxLuminance, maxLuminance); } return shader; @@ -729,7 +730,7 @@ static SkRRect getBlurRRect(const BlurRegion& region) { void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool /*useFramebufferCache*/, base::unique_fd&& bufferFence) { ATRACE_NAME("SkiaGL::drawLayers"); @@ -801,11 +802,11 @@ void SkiaGLRenderEngine::drawLayersInternal( if (!layerHasBlur(layer, ctModifiesAlpha)) { continue; } - if (layer->backgroundBlurRadius > 0 && - layer->backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { + if (layer.backgroundBlurRadius > 0 && + layer.backgroundBlurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } - for (auto region : layer->blurRegions) { + for (auto region : layer.blurRegions) { if (region.blurRadius < BlurFilter::kMaxCrossFadeRadius) { requiresCompositionLayer = true; } @@ -813,7 +814,7 @@ void SkiaGLRenderEngine::drawLayersInternal( if (requiresCompositionLayer) { activeSurface = dstSurface->makeSurface(dstSurface->imageInfo()); canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState); - blurCompositionLayer = layer; + blurCompositionLayer = &layer; break; } } @@ -825,11 +826,11 @@ void SkiaGLRenderEngine::drawLayersInternal( initCanvas(canvas, display); for (const auto& layer : layers) { - ATRACE_FORMAT("DrawLayer: %s", layer->name.c_str()); + ATRACE_FORMAT("DrawLayer: %s", layer.name.c_str()); if (kPrintLayerSettings) { std::stringstream ls; - PrintTo(*layer, &ls); + PrintTo(layer, &ls); auto debugs = ls.str(); int pos = 0; while (pos < debugs.size()) { @@ -839,7 +840,7 @@ void SkiaGLRenderEngine::drawLayersInternal( } sk_sp blurInput; - if (blurCompositionLayer == layer) { + if (blurCompositionLayer == &layer) { LOG_ALWAYS_FATAL_IF(activeSurface == dstSurface); LOG_ALWAYS_FATAL_IF(canvas == dstCanvas); @@ -878,17 +879,17 @@ void SkiaGLRenderEngine::drawLayersInternal( if (CC_UNLIKELY(mCapture->isCaptureRunning())) { // Record the name of the layer if the capture is running. std::stringstream layerSettings; - PrintTo(*layer, &layerSettings); + PrintTo(layer, &layerSettings); // Store the LayerSettings in additional information. - canvas->drawAnnotation(SkRect::MakeEmpty(), layer->name.c_str(), + canvas->drawAnnotation(SkRect::MakeEmpty(), layer.name.c_str(), SkData::MakeWithCString(layerSettings.str().c_str())); } // Layers have a local transform that should be applied to them - canvas->concat(getSkM44(layer->geometry.positionTransform).asM33()); + canvas->concat(getSkM44(layer.geometry.positionTransform).asM33()); const auto [bounds, roundRectClip] = - getBoundsAndClip(layer->geometry.boundaries, layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.geometry.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); if (mBlurFilter && layerHasBlur(layer, ctModifiesAlpha)) { std::unordered_map> cachedBlurs; @@ -909,20 +910,19 @@ void SkiaGLRenderEngine::drawLayersInternal( // TODO(b/182216890): Filter out empty layers earlier if (blurRect.width() > 0 && blurRect.height() > 0) { - if (layer->backgroundBlurRadius > 0) { + if (layer.backgroundBlurRadius > 0) { ATRACE_NAME("BackgroundBlur"); - auto blurredImage = - mBlurFilter->generate(grContext, layer->backgroundBlurRadius, blurInput, - blurRect); + auto blurredImage = mBlurFilter->generate(grContext, layer.backgroundBlurRadius, + blurInput, blurRect); - cachedBlurs[layer->backgroundBlurRadius] = blurredImage; + cachedBlurs[layer.backgroundBlurRadius] = blurredImage; - mBlurFilter->drawBlurRegion(canvas, bounds, layer->backgroundBlurRadius, 1.0f, + mBlurFilter->drawBlurRegion(canvas, bounds, layer.backgroundBlurRadius, 1.0f, blurRect, blurredImage, blurInput); } - canvas->concat(getSkM44(layer->blurRegionTransform).asM33()); - for (auto region : layer->blurRegions) { + canvas->concat(getSkM44(layer.blurRegionTransform).asM33()); + for (auto region : layer.blurRegions) { if (cachedBlurs[region.blurRadius] == nullptr) { ATRACE_NAME("BlurRegion"); cachedBlurs[region.blurRadius] = @@ -937,19 +937,18 @@ void SkiaGLRenderEngine::drawLayersInternal( } } - if (layer->shadow.length > 0) { + if (layer.shadow.length > 0) { // This would require a new parameter/flag to SkShadowUtils::DrawShadow - LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow"); + LOG_ALWAYS_FATAL_IF(layer.disableBlending, "Cannot disableBlending with a shadow"); SkRRect shadowBounds, shadowClip; - if (layer->geometry.boundaries == layer->shadow.boundaries) { + if (layer.geometry.boundaries == layer.shadow.boundaries) { shadowBounds = bounds; shadowClip = roundRectClip; } else { std::tie(shadowBounds, shadowClip) = - getBoundsAndClip(layer->shadow.boundaries, - layer->geometry.roundedCornersCrop, - layer->geometry.roundedCornersRadius); + getBoundsAndClip(layer.shadow.boundaries, layer.geometry.roundedCornersCrop, + layer.geometry.roundedCornersRadius); } // Technically, if bounds is a rect and roundRectClip is not empty, @@ -960,18 +959,18 @@ void SkiaGLRenderEngine::drawLayersInternal( // looks more like the intent. const auto& rrect = shadowBounds.isRect() && !shadowClip.isEmpty() ? shadowClip : shadowBounds; - drawShadow(canvas, rrect, layer->shadow); + drawShadow(canvas, rrect, layer.shadow); } - const bool requiresLinearEffect = layer->colorTransform != mat4() || + const bool requiresLinearEffect = layer.colorTransform != mat4() || (mUseColorManagement && - needsToneMapping(layer->sourceDataspace, display.outputDataspace)) || + needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); // quick abort from drawing the remaining portion of the layer - if (layer->skipContentDraw || - (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending && + if (layer.skipContentDraw || + (layer.alpha == 0 && !requiresLinearEffect && !layer.disableBlending && (!displayColorTransform || displayColorTransform->isAlphaUnchanged()))) { continue; } @@ -981,13 +980,13 @@ void SkiaGLRenderEngine::drawLayersInternal( // management is a no-op. const ui::Dataspace layerDataspace = (!mUseColorManagement || requiresLinearEffect) ? dstDataspace - : layer->sourceDataspace; + : layer.sourceDataspace; SkPaint paint; - if (layer->source.buffer.buffer) { + if (layer.source.buffer.buffer) { ATRACE_NAME("DrawImage"); - validateInputBufferUsage(layer->source.buffer.buffer->getBuffer()); - const auto& item = layer->source.buffer; + validateInputBufferUsage(layer.source.buffer.buffer->getBuffer()); + const auto& item = layer.source.buffer; std::shared_ptr imageTextureRef = nullptr; if (const auto& iter = cache.find(item.buffer->getBuffer()->getId()); @@ -1006,8 +1005,8 @@ void SkiaGLRenderEngine::drawLayersInternal( // if the layer's buffer has a fence, then we must must respect the fence prior to using // the buffer. - if (layer->source.buffer.fence != nullptr) { - waitFence(layer->source.buffer.fence->get()); + if (layer.source.buffer.fence != nullptr) { + waitFence(layer.source.buffer.fence->get()); } // isOpaque means we need to ignore the alpha in the image, @@ -1051,7 +1050,7 @@ void SkiaGLRenderEngine::drawLayersInternal( sk_sp shader; - if (layer->source.buffer.useTextureFiltering) { + if (layer.source.buffer.useTextureFiltering) { shader = image->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions( {SkFilterMode::kLinear, SkMipmapMode::kNone}), @@ -1069,21 +1068,21 @@ void SkiaGLRenderEngine::drawLayersInternal( paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); - paint.setAlphaf(layer->alpha); + paint.setAlphaf(layer.alpha); } else { ATRACE_NAME("DrawColor"); - const auto color = layer->source.solidColor; + const auto color = layer.source.solidColor; sk_sp shader = SkShaders::Color(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, - .fA = layer->alpha}, + .fA = layer.alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); } - if (layer->disableBlending) { + if (layer.disableBlending) { paint.setBlendMode(SkBlendMode::kSrc); } @@ -1251,13 +1250,13 @@ inline std::pair SkiaGLRenderEngine::getBoundsAndClip(const Fl return {SkRRect::MakeRect(bounds), clip}; } -inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings* layer, +inline bool SkiaGLRenderEngine::layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha) { - if (layer->backgroundBlurRadius > 0 || layer->blurRegions.size()) { + if (layer.backgroundBlurRadius > 0 || layer.blurRegions.size()) { // return false if the content is opaque and would therefore occlude the blur - const bool opaqueContent = !layer->source.buffer.buffer || layer->source.buffer.isOpaque; - const bool opaqueAlpha = layer->alpha == 1.0f && !colorTransformModifiesAlpha; - return layer->skipContentDraw || !(opaqueContent && opaqueAlpha); + const bool opaqueContent = !layer.source.buffer.buffer || layer.source.buffer.isOpaque; + const bool opaqueAlpha = layer.alpha == 1.0f && !colorTransformModifiesAlpha; + return layer.skipContentDraw || !(opaqueContent && opaqueAlpha); } return false; } diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index e010c35c13..74ce6513e9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -74,7 +74,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -92,7 +92,7 @@ private: inline SkRect getSkRect(const Rect& layer); inline std::pair getBoundsAndClip(const FloatRect& bounds, const FloatRect& crop, float cornerRadius); - inline bool layerHasBlur(const LayerSettings* layer, bool colorTransformModifiesAlpha); + inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha); inline SkColor getSkColor(const vec4& color); inline SkM44 getSkM44(const mat4& matrix); inline SkPoint3 getSkPoint3(const vec3& vector); @@ -108,8 +108,7 @@ private: const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. - sk_sp createRuntimeEffectShader(sk_sp shader, - const LayerSettings* layer, + sk_sp createRuntimeEffectShader(sk_sp shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index f61653b940..eb65e83324 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -55,7 +55,7 @@ protected: virtual void drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override { resultPromise->set_value({NO_ERROR, base::unique_fd()}); diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index 694bda65d4..c2c05f41b7 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -417,10 +417,11 @@ public: DEFAULT_DISPLAY_HEIGHT - DEFAULT_DISPLAY_OFFSET); } - void invokeDraw(renderengine::DisplaySettings settings, - std::vector layers) { + void invokeDraw(const renderengine::DisplaySettings& settings, + const std::vector& layers) { std::future result = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); + ASSERT_TRUE(result.valid()); auto [status, fence] = result.get(); @@ -436,7 +437,7 @@ public: void drawEmptyLayers() { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; invokeDraw(settings, layers); } @@ -629,7 +630,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -637,7 +638,7 @@ void RenderEngineTest::fillBuffer(half r, half g, half b, half a) { SourceVariant::fillColor(layer, r, g, b, this); layer.alpha = a; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -673,7 +674,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { settings.physicalDisplay = offsetRect(); settings.clip = offsetRectAtZero(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -681,7 +682,7 @@ void RenderEngineTest::fillRedOffsetBuffer() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -708,7 +709,7 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { settings.clip = Rect(2, 2); settings.orientation = orientationFlag; - std::vector layers; + std::vector layers; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -731,9 +732,9 @@ void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) { SourceVariant::fillColor(layerThree, 0.0f, 0.0f, 1.0f, this); layerThree.alpha = 1.0f; - layers.push_back(&layerOne); - layers.push_back(&layerTwo); - layers.push_back(&layerThree); + layers.push_back(layerOne); + layers.push_back(layerTwo); + layers.push_back(layerThree); invokeDraw(settings, layers); } @@ -810,7 +811,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { settings.clip = Rect(2, 2); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -821,7 +822,7 @@ void RenderEngineTest::fillBufferWithLayerTransform() { layer.source.solidColor = half3(1.0f, 0.0f, 0.0f); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -843,7 +844,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -860,7 +861,7 @@ void RenderEngineTest::fillBufferWithColorTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -877,7 +878,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { settings.physicalDisplay = fullscreenRect(); settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); @@ -890,7 +891,7 @@ void RenderEngineTest::fillBufferWithColorTransformZeroLayerAlpha() { layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -908,7 +909,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -918,7 +919,7 @@ void RenderEngineTest::fillRedBufferWithRoundedCorners() { SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0f; - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -949,14 +950,14 @@ void RenderEngineTest::fillBufferAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 0.0f, 1.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.emplace_back(backgroundLayer); renderengine::LayerSettings leftLayer; leftLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -964,7 +965,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT).toFloatRect(); SourceVariant::fillColor(leftLayer, 1.0f, 0.0f, 0.0f, this); leftLayer.alpha = 1.0f; - layers.push_back(&leftLayer); + layers.emplace_back(leftLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -972,7 +973,7 @@ void RenderEngineTest::fillBufferAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.emplace_back(blurLayer); invokeDraw(settings, layers); @@ -994,14 +995,14 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings backgroundLayer; backgroundLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; backgroundLayer.geometry.boundaries = fullscreenRect().toFloatRect(); SourceVariant::fillColor(backgroundLayer, 1.0f, 0.0f, 0.0f, this); backgroundLayer.alpha = 1.0f; - layers.push_back(&backgroundLayer); + layers.push_back(backgroundLayer); renderengine::LayerSettings blurLayer; blurLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1009,7 +1010,7 @@ void RenderEngineTest::fillSmallLayerAndBlurBackground() { blurLayer.backgroundBlurRadius = blurRadius; SourceVariant::fillColor(blurLayer, 0.0f, 0.0f, 1.0f, this); blurLayer.alpha = 0; - layers.push_back(&blurLayer); + layers.push_back(blurLayer); invokeDraw(settings, layers); @@ -1026,7 +1027,7 @@ void RenderEngineTest::overlayCorners() { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layersFirst; + std::vector layersFirst; renderengine::LayerSettings layerOne; layerOne.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1035,14 +1036,14 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this); layerOne.alpha = 0.2; - layersFirst.push_back(&layerOne); + layersFirst.push_back(layerOne); invokeDraw(settings, layersFirst); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 0); - std::vector layersSecond; + std::vector layersSecond; renderengine::LayerSettings layerTwo; layerTwo.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; layerTwo.geometry.boundaries = @@ -1051,7 +1052,7 @@ void RenderEngineTest::overlayCorners() { SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this); layerTwo.alpha = 1.0f; - layersSecond.push_back(&layerTwo); + layersSecond.push_back(layerTwo); invokeDraw(settings, layersSecond); expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0); @@ -1066,7 +1067,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { settings.clip = Rect(1, 1); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1102,7 +1103,7 @@ void RenderEngineTest::fillRedBufferTextureTransform() { layer.alpha = 1.0f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1118,7 +1119,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1141,7 +1142,7 @@ void RenderEngineTest::fillRedBufferWithPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1157,7 +1158,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { // Here logical space is 1x1 settings.clip = Rect(1, 1); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; const auto buf = allocateSourceBuffer(1, 1); @@ -1180,7 +1181,7 @@ void RenderEngineTest::fillRedBufferWithoutPremultiplyAlpha() { layer.alpha = 0.5f; layer.geometry.boundaries = Rect(1, 1).toFloatRect(); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1199,7 +1200,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1208,7 +1209,7 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1216,14 +1217,14 @@ void RenderEngineTest::drawShadow(const renderengine::LayerSettings& castingLaye shadowLayer.geometry.boundaries = castingLayer.geometry.boundaries; shadowLayer.alpha = castingLayer.alpha; shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); // add layer casting the shadow renderengine::LayerSettings layer = castingLayer; layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; SourceVariant::fillColor(layer, casterColor.r / 255.0f, casterColor.g / 255.0f, casterColor.b / 255.0f, this); - layers.push_back(&layer); + layers.push_back(layer); invokeDraw(settings, layers); } @@ -1236,7 +1237,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; // add background layer renderengine::LayerSettings bgLayer; @@ -1245,7 +1246,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, ColorSourceVariant::fillColor(bgLayer, backgroundColor.r / 255.0f, backgroundColor.g / 255.0f, backgroundColor.b / 255.0f, this); bgLayer.alpha = backgroundColor.a / 255.0f; - layers.push_back(&bgLayer); + layers.push_back(bgLayer); // add shadow layer renderengine::LayerSettings shadowLayer; @@ -1255,7 +1256,7 @@ void RenderEngineTest::drawShadowWithoutCaster(const FloatRect& castingBounds, shadowLayer.alpha = 1.0f; ColorSourceVariant::fillColor(shadowLayer, 0, 0, 0, this); shadowLayer.shadow = shadow; - layers.push_back(&shadowLayer); + layers.push_back(shadowLayer); invokeDraw(settings, layers); } @@ -1291,8 +1292,8 @@ TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) { // Transform the red color. bgLayer.colorTransform = mat4(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - std::vector layers; - layers.push_back(&bgLayer); + std::vector layers; + layers.push_back(bgLayer); invokeDraw(settings, layers); @@ -1306,11 +1307,11 @@ TEST_P(RenderEngineTest, drawLayers_nullOutputBuffer) { renderengine::DisplaySettings settings; settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + 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); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, nullptr, true, base::unique_fd()); @@ -1335,12 +1336,12 @@ TEST_P(RenderEngineTest, drawLayers_doesNotCacheFramebuffer) { settings.physicalDisplay = fullscreenRect(); settings.clip = fullscreenRect(); - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future result = mRE->drawLayers(settings, layers, mBuffer, false, base::unique_fd()); @@ -1743,12 +1744,12 @@ TEST_P(RenderEngineTest, cleanupPostRender_cleansUpOnce) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings layer; layer.geometry.boundaries = fullscreenRect().toFloatRect(); BufferSourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this); layer.alpha = 1.0; - layers.push_back(&layer); + layers.push_back(layer); std::future resultOne = mRE->drawLayers(settings, layers, mBuffer, true, base::unique_fd()); @@ -1779,7 +1780,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1790,7 +1791,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/3 size. renderengine::LayerSettings greenLayer; @@ -1805,7 +1806,7 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) { greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); greenLayer.alpha = 1.0f; - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1828,7 +1829,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1839,7 +1840,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); // Green layer with 1/2 size with parent crop rect. renderengine::LayerSettings greenLayer = redLayer; @@ -1847,7 +1848,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCrop) { FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT / 2); greenLayer.source.solidColor = half3(0.0f, 1.0f, 0.0f); - layers.push_back(&greenLayer); + layers.push_back(greenLayer); invokeDraw(settings, layers); @@ -1873,7 +1874,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { settings.clip = fullscreenRect(); settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR; - std::vector layers; + std::vector layers; renderengine::LayerSettings redLayer; redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR; @@ -1884,7 +1885,7 @@ TEST_P(RenderEngineTest, testRoundedCornersParentCropSmallBounds) { redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f); redLayer.alpha = 1.0f; - layers.push_back(&redLayer); + layers.push_back(redLayer); invokeDraw(settings, layers); // Due to roundedCornersRadius, the top corners are untouched. @@ -1923,7 +1924,7 @@ TEST_P(RenderEngineTest, testClear) { .disableBlending = true, }; - std::vector layers{&redLayer, &clearLayer}; + std::vector layers{redLayer, clearLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 0, 0, 0); } @@ -1971,7 +1972,7 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { .disableBlending = true, }; - std::vector layers{&redLayer, &greenLayer}; + std::vector layers{redLayer, greenLayer}; invokeDraw(display, layers); expectBufferColor(rect, 0, 128, 0, 128); } @@ -2017,7 +2018,7 @@ TEST_P(RenderEngineTest, test_isOpaque) { .alpha = 1.0f, }; - std::vector layers{&greenLayer}; + std::vector layers{greenLayer}; invokeDraw(display, layers); if (GetParam()->useColorManagement()) { diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 99250c1412..db7e12b71b 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -172,20 +172,21 @@ TEST_F(RenderEngineThreadedTest, supportsBackgroundBlur_returnsTrue) { TEST_F(RenderEngineThreadedTest, drawLayers) { renderengine::DisplaySettings settings; - std::vector layers; + std::vector layers; std::shared_ptr buffer = std::make_shared< renderengine::ExternalTexture>(new GraphicBuffer(), *mRenderEngine, renderengine::ExternalTexture::Usage::READABLE | renderengine::ExternalTexture::Usage::WRITEABLE); + base::unique_fd bufferFence; EXPECT_CALL(*mRenderEngine, drawLayersInternal) .WillOnce([&](const std::shared_ptr>&& resultPromise, const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> void { + base::unique_fd&&) -> void { resultPromise->set_value({NO_ERROR, base::unique_fd()}); }); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index a549672259..3d446e8e72 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -306,7 +306,7 @@ bool RenderEngineThreaded::canSkipPostRenderCleanup() const { void RenderEngineThreaded::drawLayersInternal( const std::shared_ptr>&& resultPromise, - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { resultPromise->set_value({NO_ERROR, base::unique_fd()}); @@ -314,19 +314,20 @@ void RenderEngineThreaded::drawLayersInternal( } std::future RenderEngineThreaded::drawLayers( - const DisplaySettings& display, const std::vector& layers, + const DisplaySettings& display, const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) { ATRACE_CALL(); const auto resultPromise = std::make_shared>(); std::future resultFuture = resultPromise->get_future(); + int fd = bufferFence.release(); { std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([resultPromise, &display, &layers, &buffer, useFramebufferCache, - &bufferFence](renderengine::RenderEngine& instance) { + mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache, + fd](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::drawLayers"); instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer, - useFramebufferCache, std::move(bufferFence)); + useFramebufferCache, base::unique_fd(fd)); }); } mCondition.notify_one(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 2303caa7eb..0159cfaece 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -57,7 +57,7 @@ public: void cleanupPostRender() override; std::future drawLayers(const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; @@ -73,7 +73,7 @@ protected: bool canSkipPostRenderCleanup() const override; void drawLayersInternal(const std::shared_ptr>&& resultPromise, const DisplaySettings& display, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence) override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 52bd420d91..4e5d2d03b0 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,7 +48,9 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { +void BufferQueueLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { + sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index a3bd725cfe..dfdb5c055d 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,7 +42,8 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fda7a928a1..c213570c7f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -70,69 +70,11 @@ BufferStateLayer::~BufferStateLayer() { } } -status_t BufferStateLayer::addReleaseFence(const sp& ch, - const sp& fence) { - if (ch == nullptr) { - return OK; - } - ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - if (!ch->previousReleaseFence.get()) { - ch->previousReleaseFence = fence; - return OK; - } - - // Below logic is lifted from ConsumerBase.cpp: - // Check status of fences first because merging is expensive. - // Merging an invalid fence with any other fence results in an - // invalid fence. - auto currentStatus = ch->previousReleaseFence->getStatus(); - if (currentStatus == Fence::Status::Invalid) { - ALOGE("Existing fence has invalid state, layer: %s", mName.c_str()); - return BAD_VALUE; - } - - auto incomingStatus = fence->getStatus(); - if (incomingStatus == Fence::Status::Invalid) { - ALOGE("New fence has invalid state, layer: %s", mName.c_str()); - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - - // If both fences are signaled or both are unsignaled, we need to merge - // them to get an accurate timestamp. - if (currentStatus == incomingStatus) { - char fenceName[32] = {}; - snprintf(fenceName, 32, "%.28s", mName.c_str()); - sp mergedFence = Fence::merge( - fenceName, ch->previousReleaseFence, fence); - if (!mergedFence.get()) { - ALOGE("failed to merge release fences, layer: %s", mName.c_str()); - // synchronization is broken, the best we can do is hope fences - // signal in order so the new fence will act like a union - ch->previousReleaseFence = fence; - return BAD_VALUE; - } - ch->previousReleaseFence = mergedFence; - } else if (incomingStatus == Fence::Status::Unsignaled) { - // If one fence has signaled and the other hasn't, the unsignaled - // fence will approximately correspond with the correct timestamp. - // There's a small race if both fences signal at about the same time - // and their statuses are retrieved with unfortunate timing. However, - // by this point, they will have both signaled and only the timestamp - // will be slightly off; any dependencies after this point will - // already have been met. - ch->previousReleaseFence = fence; - } - // else if (currentStatus == Fence::Status::Unsignaled) is a no-op. - - return OK; -} - // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { - +void BufferStateLayer::onLayerDisplayed( + std::shared_future futureRenderEngineResult) { // If a layer has been displayed again we may need to clear // the mLastClientComposition fence that we use for early release in setBuffer // (as we now have a new fence which won't pass through the client composition path in some cases @@ -146,9 +88,6 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { mLastClientCompositionDisplayed = true; } - if (!releaseFence->isValid()) { - return; - } // The previous release fence notifies the client that SurfaceFlinger is done with the previous // buffer that was presented on this layer. The first transaction that came in this frame that // replaced the previous buffer on this layer needs this release fence, because the fence will @@ -173,17 +112,17 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { break; } } - auto status = addReleaseFence(ch, releaseFence); - if (status != OK) { - ALOGE("Failed to add release fence for layer %s", getName().c_str()); - } - - mPreviousReleaseFence = releaseFence; // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { mPreviousReleasedFrameNumber = mPreviousFrameNumber; } + + if (ch != nullptr) { + ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; + ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->name = mName; + } } void BufferStateLayer::onSurfaceFrameCreated( @@ -231,9 +170,18 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { mFlinger->getTransactionCallbackInvoker().addCallbackHandles( mDrawingState.callbackHandles, jankData); + sp releaseFence = Fence::NO_FENCE; + for (auto& handle : mDrawingState.callbackHandles) { + if (handle->releasePreviousBuffer && + mDrawingState.releaseBufferEndpoint == handle->listener) { + releaseFence = + handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE; + break; + } + } + mDrawingState.callbackHandles = {}; - const sp& releaseFence(mPreviousReleaseFence); std::shared_ptr releaseFenceTime = std::make_shared(releaseFence); { Mutex::Autolock lock(mFrameEventHistoryMutex); diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 87b68ea71b..eea700cf7b 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,7 +39,9 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; + void releasePendingBuffer(nsecs_t dequeueReadyTime) override; void finalizeFrameEventHistory(const std::shared_ptr& glDoneFence, @@ -115,8 +117,6 @@ private: bool updateFrameEventHistory(const sp& acquireFence, nsecs_t postedTime, nsecs_t requestedPresentTime); - status_t addReleaseFence(const sp& ch, const sp& releaseFence); - bool latchSidebandStream(bool& recomputeVisibleRegions) override; bool hasFrameUpdate() const override; @@ -139,7 +139,6 @@ private: std::shared_ptr getBufferFromBufferData( const BufferData& bufferData); - sp mPreviousReleaseFence; ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index f7b71cf9fe..ac243c0a17 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -26,6 +27,7 @@ #pragma clang diagnostic ignored "-Wextra" #include +#include // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -151,7 +153,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(const sp&) = 0; + virtual void onLayerDisplayed(std::shared_future) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index d215bda891..16aebef9f3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -39,7 +39,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(const sp&)); + MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index fad1fa74dd..6800004a90 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -1097,12 +1098,12 @@ std::optional Output::composeSurfaces( setExpensiveRenderingExpected(true); } - std::vector clientCompositionLayerPointers; - clientCompositionLayerPointers.reserve(clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - std::back_inserter(clientCompositionLayerPointers), - [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings* { - return &settings; + std::back_inserter(clientRenderEngineLayers), + [](LayerFE::LayerSettings& settings) -> renderengine::LayerSettings { + return settings; }); const nsecs_t renderEngineStart = systemTime(); @@ -1115,7 +1116,7 @@ std::optional Output::composeSurfaces( const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; auto [status, drawFence] = renderEngine - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, tex, + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, useFramebufferCache, std::move(fd)) .get(); @@ -1295,8 +1296,10 @@ void Output::postFramebuffer() { releaseFence = Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } - - layer->getLayerFE().onLayerDisplayed(releaseFence); + layer->getLayerFE().onLayerDisplayed( + ftl::yield( + {NO_ERROR, base::unique_fd(releaseFence->dup())}) + .share()); } // We've got a list of layers needing fences, that are disjoint with @@ -1304,7 +1307,9 @@ void Output::postFramebuffer() { // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(frame.presentFence); + layer->onLayerDisplayed(ftl::yield( + {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) + .share()); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index e6b716e8f2..ec52e59ab0 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -193,11 +193,6 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te clientCompositionList.cend()); } - std::vector layerSettingsPointers; - std::transform(layerSettings.cbegin(), layerSettings.cend(), - std::back_inserter(layerSettingsPointers), - [](const renderengine::LayerSettings& settings) { return &settings; }); - renderengine::LayerSettings blurLayerSettings; if (mBlurLayer) { auto blurSettings = targetSettings; @@ -212,7 +207,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te blurLayerSettings.name = std::string("blur layer"); // Clear out the shadow settings blurLayerSettings.shadow = {}; - layerSettingsPointers.push_back(&blurLayerSettings); + layerSettings.push_back(blurLayerSettings); } renderengine::LayerSettings holePunchSettings; @@ -230,7 +225,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchSettings.disableBlending = true; holePunchSettings.alpha = 0.0f; holePunchSettings.name = std::string("hole punch layer"); - layerSettingsPointers.push_back(&holePunchSettings); + layerSettings.push_back(holePunchSettings); // Add a solid background as the first layer in case there is no opaque // buffer behind the punch hole @@ -239,7 +234,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te holePunchBackgroundSettings.geometry.boundaries = holePunchSettings.geometry.boundaries; holePunchBackgroundSettings.geometry.positionTransform = holePunchSettings.geometry.positionTransform; - layerSettingsPointers.insert(layerSettingsPointers.begin(), &holePunchBackgroundSettings); + layerSettings.emplace(layerSettings.begin(), holePunchBackgroundSettings); } if (sDebugHighlighLayers) { @@ -257,7 +252,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te .alpha = half(0.05f), }; - layerSettingsPointers.emplace_back(&highlight); + layerSettings.emplace_back(highlight); } auto texture = texturePool.borrowTexture(); @@ -273,8 +268,8 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te } auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettingsPointers, - texture->get(), false, std::move(bufferFence)) + .drawLayers(displaySettings, layerSettings, texture->get(), + false, std::move(bufferFence)) .get(); if (status == NO_ERROR) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 8f0028c399..cf63ef5183 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2884,12 +2885,24 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - EXPECT_CALL(*mLayer1.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer1Fence.get())))); - EXPECT_CALL(*mLayer2.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer2Fence.get())))); - EXPECT_CALL(*mLayer3.layerFE, - onLayerDisplayed(Property(&sp::get, Eq(layer3Fence.get())))); + base::unique_fd layer1FD(layer1Fence->dup()); + base::unique_fd layer2FD(layer2Fence->dup()); + base::unique_fd layer3FD(layer3Fence->dup()); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer1FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer2FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) + .WillOnce([&layer3FD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); } @@ -2915,9 +2928,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) // Fence::merge is called, and since none of the fences are actually valid, // Fence::NO_FENCE is returned and passed to each onLayerDisplayed() call. // This is the best we can do without creating a real kernel fence object. - EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(Fence::NO_FENCE)); - EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(Fence::NO_FENCE)); + EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed).WillOnce(Return()); + EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed).WillOnce(Return()); mOutput.postFramebuffer(); } @@ -2949,12 +2962,22 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - EXPECT_CALL(*releasedLayer1, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer2, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); - EXPECT_CALL(*releasedLayer3, - onLayerDisplayed(Property(&sp::get, Eq(presentFence.get())))); + base::unique_fd layerFD(presentFence.get()->dup()); + EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); + EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) + .WillOnce([&layerFD](std::shared_future + futureRenderEngineResult) { + EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + }); mOutput.postFramebuffer(); @@ -3131,9 +3154,9 @@ TEST_F(OutputComposeSurfacesTest, handlesZeroCompositionRequests) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3161,11 +3184,11 @@ TEST_F(OutputComposeSurfacesTest, buildsAndRendersRequestList) { })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3196,11 +3219,11 @@ TEST_F(OutputComposeSurfacesTest, })); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, true, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3226,7 +3249,7 @@ TEST_F(OutputComposeSurfacesTest, renderDuplicateClientCompositionRequestsWithou .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .Times(2) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))) @@ -3258,7 +3281,7 @@ TEST_F(OutputComposeSurfacesTest, skipDuplicateClientCompositionRequests) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false)); @@ -3294,11 +3317,11 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)) .WillOnce(Return(mOutputBuffer)) .WillOnce(Return(otherOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillRepeatedly([&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) + base::unique_fd&&) -> std::future { return futureOf({NO_ERROR, base::unique_fd()}); }); @@ -3330,10 +3353,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfRequestChanges) { .WillRepeatedly(Return()); EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer)); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r2), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); - EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _)) + EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(r1, r3), _, false, _)) .WillOnce(Return(ByMove( futureOf({NO_ERROR, base::unique_fd()})))); @@ -3487,9 +3510,9 @@ struct OutputComposeSurfacesTest_HandlesProtectedContent : public OutputComposeS EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _)) .WillRepeatedly( [&](const renderengine::DisplaySettings&, - const std::vector&, + const std::vector&, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { return futureOf( {NO_ERROR, base::unique_fd()}); }); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index ecb05f8e5f..42b3d972a8 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -346,15 +346,15 @@ TEST_F(CachedSetTest, renderUnsecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); }; @@ -398,15 +398,15 @@ TEST_F(CachedSetTest, renderSecureOutput) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -453,15 +453,15 @@ TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) { const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()), displaySettings.orientation); - EXPECT_EQ(0.5f, layers[0]->alpha); - EXPECT_EQ(0.75f, layers[1]->alpha); + EXPECT_EQ(0.5f, layers[0].alpha); + EXPECT_EQ(0.75f, layers[1].alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return futureOf({NO_ERROR, base::unique_fd()}); @@ -656,26 +656,26 @@ TEST_F(CachedSetTest, addHolePunch) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -717,27 +717,27 @@ TEST_F(CachedSetTest, addHolePunch_noBuffer) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 4u); { - const auto* holePunchSettings = layers[3]; - EXPECT_EQ(nullptr, holePunchSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings->source.solidColor); - EXPECT_TRUE(holePunchSettings->disableBlending); - EXPECT_EQ(0.0f, holePunchSettings->alpha); + const auto holePunchSettings = layers[3]; + EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor); + EXPECT_TRUE(holePunchSettings.disableBlending); + EXPECT_EQ(0.0f, holePunchSettings.alpha); } { - const auto* holePunchBackgroundSettings = layers[0]; - EXPECT_EQ(nullptr, holePunchBackgroundSettings->source.buffer.buffer); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings->source.solidColor); - EXPECT_FALSE(holePunchBackgroundSettings->disableBlending); - EXPECT_EQ(1.0f, holePunchBackgroundSettings->alpha); + const auto holePunchBackgroundSettings = layers[0]; + EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor); + EXPECT_FALSE(holePunchBackgroundSettings.disableBlending); + EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha); } return futureOf({NO_ERROR, base::unique_fd()}); @@ -867,16 +867,16 @@ TEST_F(CachedSetTest, addBlur) { const auto drawLayers = [&](const renderengine::DisplaySettings&, - const std::vector& layers, + const std::vector& layers, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { // If the highlight layer is enabled, it will increase the size by 1. // We're interested in the third layer either way. EXPECT_GE(layers.size(), 3u); - const auto* blurSettings = layers[2]; - EXPECT_TRUE(blurSettings->skipContentDraw); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor); - EXPECT_EQ(0.0f, blurSettings->alpha); + const auto blurSettings = layers[2]; + EXPECT_TRUE(blurSettings.skipContentDraw); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor); + EXPECT_EQ(0.0f, blurSettings.alpha); return futureOf({NO_ERROR, base::unique_fd()}); }; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5707c67a56..d68cf9720f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -221,7 +221,8 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed(const sp& /*releaseFence*/) {} +void Layer::onLayerDisplayed( + std::shared_future /*futureRenderEngineResult*/) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 07b2eb5130..4569f9af23 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -616,7 +616,8 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed(const sp& releaseFence) override; + void onLayerDisplayed( + std::shared_future futureRenderEngineResult) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 9465b197b2..32585dd9ac 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -356,10 +356,13 @@ void RegionSamplingThread::captureSample() { renderengine::ExternalTexture::Usage::WRITEABLE); } - const sp captureListener = new SyncScreenCaptureListener(); - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, captureListener); - ScreenCaptureResults captureResults = captureListener->waitForResults(); + auto captureScreenResultFuture = + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + true /* regionSampling */, false /* grayscale */, nullptr); + auto& captureScreenResult = captureScreenResultFuture.get(); + if (captureScreenResult.drawFence.ok()) { + sync_wait(captureScreenResult.drawFence.get(), -1); + } std::vector activeDescriptors; for (const auto& descriptor : descriptors) { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e9665bdec8..da5fefda94 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5923,9 +5923,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -5960,9 +5961,15 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + auto captureResultFuture = + captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, false /* allowProtected */, + false /* grayscale */, captureListener); + return captureResultFuture.get().status; } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6089,23 +6096,28 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, }); }; - return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, - args.pixelFormat, args.allowProtected, args.grayscale, - captureListener); + if (captureListener == nullptr) { + ALOGE("capture screen must provide a capture listener callback"); + return BAD_VALUE; + } + + auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, + reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); + return captureResultFuture.get().status; } -status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - TraverseLayersFunction traverseLayers, - ui::Size bufferSize, ui::PixelFormat reqPixelFormat, - bool allowProtected, bool grayscale, - const sp& captureListener) { +std::shared_future SurfaceFlinger::captureScreenCommon( + RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, + ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, + const sp& captureListener) { ATRACE_CALL(); if (exceedsMaxRenderTargetSize(bufferSize.getWidth(), bufferSize.getHeight())) { ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return BAD_VALUE; + return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6145,44 +6157,65 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, false /* regionSampling */, grayscale, captureListener); } -status_t SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { ATRACE_CALL(); - if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); - return BAD_VALUE; - } - bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - static_cast(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { + auto scheduleResultFuture = schedule([=, + renderAreaFuture = std::move(renderAreaFuture)]() mutable + -> std::shared_future { ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return; + return ftl::yield({NO_ERROR, base::unique_fd()}) + .share(); } - status_t result = NO_ERROR; + std::shared_future renderEngineResultFuture; + renderArea->render([&] { - result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + renderEngineResultFuture = + renderScreenImplLocked(*renderArea, traverseLayers, buffer, + canCaptureBlackoutContent, regionSampling, grayscale, + captureResults); }); + // spring up a thread to unblock SF main thread and wait for + // RenderEngineResult to be available + if (captureListener != nullptr) { + std::async([=]() mutable { + ATRACE_NAME("captureListener is nonnull!"); + auto& [status, drawFence] = renderEngineResultFuture.get(); + captureResults.result = status; + captureResults.fence = new Fence(dup(drawFence)); + captureListener->onScreenCaptureCompleted(captureResults); + }); + } + return renderEngineResultFuture; + }); - captureResults.result = result; - captureListener->onScreenCaptureCompleted(captureResults); - })); - - return NO_ERROR; + // flatten scheduleResultFuture object to single shared_future object + if (captureListener == nullptr) { + std::future captureScreenResultFuture = + ftl::chain(std::move(scheduleResultFuture)) + .then([=](std::shared_future futureObject) + -> renderengine::RenderEngineResult { + auto& [status, drawFence] = futureObject.get(); + return {status, base::unique_fd(dup(drawFence))}; + }); + return captureScreenResultFuture.share(); + } else { + return ftl::yield({NO_ERROR, base::unique_fd()}).share(); + } } -status_t SurfaceFlinger::renderScreenImplLocked( +std::shared_future SurfaceFlinger::renderScreenImplLocked( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6201,7 +6234,8 @@ status_t SurfaceFlinger::renderScreenImplLocked( // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return PERMISSION_DENIED; + return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) + .share(); } captureResults.buffer = buffer->getBuffer(); @@ -6283,11 +6317,12 @@ status_t SurfaceFlinger::renderScreenImplLocked( }); - std::vector clientCompositionLayerPointers( - clientCompositionLayers.size()); + std::vector clientRenderEngineLayers; + clientRenderEngineLayers.reserve(clientCompositionLayers.size()); std::transform(clientCompositionLayers.begin(), clientCompositionLayers.end(), - clientCompositionLayerPointers.begin(), - std::pointer_traits::pointer_to); + std::back_inserter(clientRenderEngineLayers), + [](compositionengine::LayerFE::LayerSettings& settings) + -> renderengine::LayerSettings { return settings; }); // Use an empty fence for the buffer fence, since we just created the buffer so // there is no need for synchronization with the GPU. @@ -6295,24 +6330,22 @@ status_t SurfaceFlinger::renderScreenImplLocked( getRenderEngine().useProtectedContext(useProtected); const constexpr bool kUseFramebufferCache = false; - auto [status, drawFence] = - getRenderEngine() - .drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - kUseFramebufferCache, std::move(bufferFence)) - .get(); + std::future drawLayersResult = + getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence)); - if (drawFence >= 0) { - sp releaseFence = new Fence(dup(drawFence)); - for (auto* layer : renderedLayers) { - layer->onLayerDisplayed(releaseFence); - } + std::shared_future drawLayersResultFuture = + drawLayersResult.share(); // drawLayersResult will be moved to shared one + + for (auto* layer : renderedLayers) { + // make a copy of shared_future object for each layer + layer->onLayerDisplayed(drawLayersResultFuture); } - captureResults.fence = new Fence(drawFence.release()); // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return status; + return drawLayersResultFuture; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index cb1611097a..3dda9f0607 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -809,17 +809,17 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - 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&, - bool regionSampling, bool grayscale, - const sp&); - status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, - const std::shared_ptr&, - bool canCaptureBlackoutContent, bool regionSampling, - bool grayscale, ScreenCaptureResults&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, const sp&); + std::shared_future captureScreenCommon( + RenderAreaFuture, TraverseLayersFunction, + const std::shared_ptr&, bool regionSampling, + bool grayscale, const sp&); + std::shared_future renderScreenImplLocked( + const RenderArea&, TraverseLayersFunction, + const std::shared_ptr&, bool canCaptureBlackoutContent, + bool regionSampling, bool grayscale, ScreenCaptureResults&); // If the uid provided is not UNSET_UID, the traverse will skip any layers that don't have a // matching ownerUid diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index c1eb8966d1..8fbf0b4d07 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -154,6 +154,38 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // destroyed the client side is dead and there won't be anyone to send the callback to. sp surfaceControl = handle->surfaceControl.promote(); if (surfaceControl) { + sp prevFence = nullptr; + + for (const auto& futureStruct : handle->previousReleaseFences) { + sp currentFence = sp::make(dup(futureStruct.get().drawFence)); + if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { + prevFence = currentFence; + handle->previousReleaseFence = prevFence; + } else if (prevFence != nullptr) { + // If both fences are signaled or both are unsignaled, we need to merge + // them to get an accurate timestamp. + if (prevFence->getStatus() != Fence::Status::Invalid && + prevFence->getStatus() == currentFence->getStatus()) { + char fenceName[32] = {}; + snprintf(fenceName, 32, "%.28s", handle->name.c_str()); + sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); + if (mergedFence->isValid()) { + handle->previousReleaseFence = mergedFence; + prevFence = handle->previousReleaseFence; + } + } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { + // If one fence has signaled and the other hasn't, the unsignaled + // fence will approximately correspond with the correct timestamp. + // There's a small race if both fences signal at about the same time + // and their statuses are retrieved with unfortunate timing. However, + // by this point, they will have both signaled and only the timestamp + // will be slightly off; any dependencies after this point will + // already have been met. + handle->previousReleaseFence = currentFence; + } + } + } + handle->previousReleaseFences = {}; FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index 7e879e119b..100dbfa8aa 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -18,8 +18,9 @@ #include #include -#include +#include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include +#include #include namespace android { @@ -42,7 +44,9 @@ public: wp surfaceControl; bool releasePreviousBuffer = false; + std::string name; sp previousReleaseFence; + std::vector> previousReleaseFences; nsecs_t acquireTime = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index a0812912d4..40ef6e702d 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -245,10 +245,16 @@ void CompositionTest::captureScreenComposition() { "screenshot"), *mRenderEngine, true); - status_t result = - mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, - forSystem, regionSampling); - EXPECT_EQ(NO_ERROR, result); + auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, + forSystem, regionSampling); + EXPECT_TRUE(result.valid()); + + auto& [status, drawFence] = result.get(); + + EXPECT_EQ(NO_ERROR, status); + if (drawFence.ok()) { + sync_wait(drawFence.get(), -1); + } LayerCase::cleanup(this); } @@ -344,9 +350,9 @@ struct BaseDisplayVariant { static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -395,9 +401,9 @@ struct BaseDisplayVariant { Return(0))); EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings, - const std::vector&, + const std::vector&, const std::shared_ptr&, - const bool, base::unique_fd &&) + const bool, base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), @@ -631,9 +637,9 @@ struct BaseLayerProperties { static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -650,16 +656,16 @@ struct BaseLayerProperties { "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, Not(IsNull())); - EXPECT_THAT(layer->source.buffer.fence, Not(IsNull())); - EXPECT_EQ(DEFAULT_TEXTURE_ID, layer->source.buffer.textureName); - EXPECT_EQ(false, layer->source.buffer.isY410BT2020); - EXPECT_EQ(true, layer->source.buffer.usePremultipliedAlpha); - EXPECT_EQ(false, layer->source.buffer.isOpaque); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull())); + EXPECT_THAT(layer.source.buffer.fence, Not(IsNull())); + EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName); + EXPECT_EQ(false, layer.source.buffer.isY410BT2020); + EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha); + EXPECT_EQ(false, layer.source.buffer.isOpaque); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -683,9 +689,9 @@ struct BaseLayerProperties { static void setupREColorCompositionCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -702,14 +708,14 @@ struct BaseLayerProperties { "setupREColorCompositionCallExpectations verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1], LayerProperties::COLOR[2]), - layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(LayerProperties::COLOR[3], layer->alpha); + layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha); return resultFuture; }); } @@ -763,9 +769,9 @@ struct CommonSecureLayerProperties : public BaseLayerProperties static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) { EXPECT_CALL(*test->mRenderEngine, drawLayers) .WillOnce([&](const renderengine::DisplaySettings& displaySettings, - const std::vector& layerSettings, + const std::vector& layerSettings, const std::shared_ptr&, const bool, - base::unique_fd &&) -> std::future { + base::unique_fd&&) -> std::future { EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance); EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT), displaySettings.physicalDisplay); @@ -782,12 +788,12 @@ struct CommonSecureLayerProperties : public BaseLayerProperties "verification lambda"; return resultFuture; } - const renderengine::LayerSettings* layer = layerSettings.back(); - EXPECT_THAT(layer->source.buffer.buffer, IsNull()); - EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer->source.solidColor); - EXPECT_EQ(0.0, layer->geometry.roundedCornersRadius); - EXPECT_EQ(ui::Dataspace::UNKNOWN, layer->sourceDataspace); - EXPECT_EQ(1.0f, layer->alpha); + const renderengine::LayerSettings layer = layerSettings.back(); + EXPECT_THAT(layer.source.buffer.buffer, IsNull()); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor); + EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius); + EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace); + EXPECT_EQ(1.0f, layer.alpha); return resultFuture; }); } -- cgit v1.2.3-59-g8ed1b From ecc1f90e00ffd577a77ea7c763ee330c83626773 Mon Sep 17 00:00:00 2001 From: Huihong Luo Date: Sat, 20 Nov 2021 11:55:05 -0800 Subject: Migrate IRegionSamplingListener interface to AIDL This addresses security vulnerabilities due to hard coded binder interface. Bug: 195660647 Test: (1) atest RegionSamplingTest (2) install Google I/O 2019 app, tap Agenda menu, scrolling to examine the bottom horizontal bar color changes Change-Id: If2d33c5168b2df5fc7fd8f55e3bca75d3f385a89 --- libs/binder/include/binder/IInterface.h | 1 - libs/gui/Android.bp | 1 - libs/gui/IRegionSamplingListener.cpp | 64 ---------------------- libs/gui/ISurfaceComposer.cpp | 3 +- libs/gui/SurfaceComposerClient.cpp | 1 + .../aidl/android/gui/IRegionSamplingListener.aidl | 22 ++++++++ libs/gui/include/gui/IRegionSamplingListener.h | 43 --------------- libs/gui/include/gui/ISurfaceComposer.h | 3 +- libs/gui/include/gui/SurfaceComposerClient.h | 3 +- libs/gui/tests/RegionSampling_test.cpp | 7 ++- libs/gui/tests/SamplingDemo.cpp | 7 ++- libs/gui/tests/Surface_test.cpp | 1 + services/surfaceflinger/RegionSamplingThread.cpp | 1 - services/surfaceflinger/RegionSamplingThread.h | 4 +- services/surfaceflinger/SurfaceFlinger.h | 1 + 15 files changed, 42 insertions(+), 120 deletions(-) delete mode 100644 libs/gui/IRegionSamplingListener.cpp create mode 100644 libs/gui/aidl/android/gui/IRegionSamplingListener.aidl delete mode 100644 libs/gui/include/gui/IRegionSamplingListener.h (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h index 7d14315b01..415b19adf6 100644 --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -231,7 +231,6 @@ constexpr const char* const kManualInterfaces[] = { "android.gui.DisplayEventConnection", "android.gui.IConsumerListener", "android.gui.IGraphicBufferConsumer", - "android.gui.IRegionSamplingListener", "android.gui.ITransactionComposerListener", "android.gui.SensorEventConnection", "android.gui.SensorServer", diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 19a29c196d..fea9f810c2 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -184,7 +184,6 @@ cc_library_shared { "IGraphicBufferConsumer.cpp", "IGraphicBufferProducer.cpp", "IProducerListener.cpp", - "IRegionSamplingListener.cpp", "ISurfaceComposer.cpp", "ISurfaceComposerClient.cpp", "ITransactionCompletedListener.cpp", diff --git a/libs/gui/IRegionSamplingListener.cpp b/libs/gui/IRegionSamplingListener.cpp deleted file mode 100644 index 40cbfceaf7..0000000000 --- a/libs/gui/IRegionSamplingListener.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "IRegionSamplingListener" -//#define LOG_NDEBUG 0 - -#include - -namespace android { - -namespace { // Anonymous - -enum class Tag : uint32_t { - ON_SAMPLE_COLLECTED = IBinder::FIRST_CALL_TRANSACTION, - LAST = ON_SAMPLE_COLLECTED, -}; - -} // Anonymous namespace - -class BpRegionSamplingListener : public SafeBpInterface { -public: - explicit BpRegionSamplingListener(const sp& impl) - : SafeBpInterface(impl, "BpRegionSamplingListener") {} - - ~BpRegionSamplingListener() override; - - void onSampleCollected(float medianLuma) override { - callRemoteAsync(Tag::ON_SAMPLE_COLLECTED, medianLuma); - } -}; - -// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see -// clang warning -Wweak-vtables) -BpRegionSamplingListener::~BpRegionSamplingListener() = default; - -IMPLEMENT_META_INTERFACE(RegionSamplingListener, "android.gui.IRegionSamplingListener"); - -status_t BnRegionSamplingListener::onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags) { - if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast(Tag::LAST)) { - return BBinder::onTransact(code, data, reply, flags); - } - auto tag = static_cast(code); - switch (tag) { - case Tag::ON_SAMPLE_COLLECTED: - return callLocalAsync(data, reply, &IRegionSamplingListener::onSampleCollected); - } -} - -} // namespace android diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 02950995af..a90f7559b3 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -17,13 +17,13 @@ // tag as surfaceflinger #define LOG_TAG "SurfaceFlinger" +#include #include #include #include #include #include #include -#include #include #include #include @@ -44,6 +44,7 @@ namespace android { +using gui::IRegionSamplingListener; using gui::IWindowInfosListener; using ui::ColorMode; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index b139cf126c..f6253a256c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -53,6 +53,7 @@ namespace android { using gui::FocusRequest; +using gui::IRegionSamplingListener; using gui::WindowInfo; using gui::WindowInfoHandle; using gui::WindowInfosListener; diff --git a/libs/gui/aidl/android/gui/IRegionSamplingListener.aidl b/libs/gui/aidl/android/gui/IRegionSamplingListener.aidl new file mode 100644 index 0000000000..00a3959d79 --- /dev/null +++ b/libs/gui/aidl/android/gui/IRegionSamplingListener.aidl @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package android.gui; + +/** @hide */ +oneway interface IRegionSamplingListener { + void onSampleCollected(float medianLuma); +} diff --git a/libs/gui/include/gui/IRegionSamplingListener.h b/libs/gui/include/gui/IRegionSamplingListener.h deleted file mode 100644 index 1803d9a1da..0000000000 --- a/libs/gui/include/gui/IRegionSamplingListener.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#include -#include - -namespace android { - -class IRegionSamplingListener : public IInterface { -public: - DECLARE_META_INTERFACE(RegionSamplingListener) - - virtual void onSampleCollected(float medianLuma) = 0; -}; - -class BnRegionSamplingListener : public SafeBnInterface { -public: - BnRegionSamplingListener() - : SafeBnInterface("BnRegionSamplingListener") {} - - status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, - uint32_t flags = 0) override; -}; - -} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index e0183adbe6..e1e9182056 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -63,10 +64,10 @@ class HdrCapabilities; class IDisplayEventConnection; class IGraphicBufferProducer; class ISurfaceComposerClient; -class IRegionSamplingListener; class Rect; enum class FrameEvent; +using gui::IRegionSamplingListener; using gui::IScreenCaptureListener; namespace ui { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e05c3646c6..0fe1253f94 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -51,10 +51,11 @@ namespace android { class HdrCapabilities; class ISurfaceComposerClient; class IGraphicBufferProducer; -class IRegionSamplingListener; class ITunnelModeEnabledListener; class Region; +using gui::IRegionSamplingListener; + struct SurfaceControlStats { SurfaceControlStats(const sp& sc, nsecs_t latchTime, nsecs_t acquireTime, const sp& presentFence, const sp& prevReleaseFence, diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp index 6746b0a827..c9106bed4c 100644 --- a/libs/gui/tests/RegionSampling_test.cpp +++ b/libs/gui/tests/RegionSampling_test.cpp @@ -17,9 +17,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -135,12 +135,13 @@ private: std::atomic poll_{true}; }; -struct Listener : BnRegionSamplingListener { - void onSampleCollected(float medianLuma) override { +struct Listener : android::gui::BnRegionSamplingListener { + binder::Status onSampleCollected(float medianLuma) override { std::unique_lock lk(mutex); received = true; mLuma = medianLuma; cv.notify_all(); + return binder::Status::ok(); }; bool wait_event(std::chrono::milliseconds timeout) { std::unique_lock lk(mutex); diff --git a/libs/gui/tests/SamplingDemo.cpp b/libs/gui/tests/SamplingDemo.cpp index 0cd150d3cb..a083a228a6 100644 --- a/libs/gui/tests/SamplingDemo.cpp +++ b/libs/gui/tests/SamplingDemo.cpp @@ -20,9 +20,9 @@ #include #include +#include #include #include -#include #include #include #include @@ -33,7 +33,7 @@ using namespace std::chrono_literals; namespace android { -class Button : public BnRegionSamplingListener { +class Button : public gui::BnRegionSamplingListener { public: Button(const char* name, const Rect& samplingArea) { sp client = new SurfaceComposerClient; @@ -99,9 +99,10 @@ private: .apply(); } - void onSampleCollected(float medianLuma) override { + binder::Status onSampleCollected(float medianLuma) override { ATRACE_CALL(); setColor(medianLuma); + return binder::Status::ok(); } sp mClient; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index b2baea6aba..e0c2aa7181 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -45,6 +45,7 @@ using namespace std::chrono_literals; // retrieve wide-color and hdr settings from configstore using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; +using gui::IRegionSamplingListener; using ui::ColorMode; using Transaction = SurfaceComposerClient::Transaction; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 32585dd9ac..da8c3e062c 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index f715309b2e..686b4b1e1f 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include #include @@ -34,12 +35,13 @@ namespace android { -class IRegionSamplingListener; class Layer; class Scheduler; class SurfaceFlinger; struct SamplingOffsetCallback; +using gui::IRegionSamplingListener; + float sampleArea(const uint32_t* data, int32_t width, int32_t height, int32_t stride, uint32_t orientation, const Rect& area); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 7339b3bc3d..1545c0004f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -105,6 +105,7 @@ class TimeStats; class FrameTracer; class WindowInfosListenerInvoker; +using gui::IRegionSamplingListener; using gui::ScreenCaptureResults; namespace frametimeline { -- cgit v1.2.3-59-g8ed1b From dbbe3854efc2ceb6e0f5c2f0991161f6b7beea39 Mon Sep 17 00:00:00 2001 From: Vishnu Nair Date: Wed, 12 Jan 2022 20:22:11 -0800 Subject: SF: Make ExternalTexture mockable Expose GraphicBuffer properties via ExternalTexture class. Within SurfaceFlinger access the buffer via this proxy interface. This allows us to inject and mock GraphicBuffers as needed. Specifically this will be used to recreate layer state from transaction traces. Test: compiles Bug: 200284593 Change-Id: I2e7f6bee28314b70eac477cfadbf9f94c4d70339 --- libs/renderengine/ExternalTexture.cpp | 20 ++-- libs/renderengine/benchmark/RenderEngineBench.cpp | 19 ++-- .../include/renderengine/ExternalTexture.h | 32 +++--- .../include/renderengine/RenderEngine.h | 3 +- .../include/renderengine/impl/ExternalTexture.h | 60 ++++++++++++ .../renderengine/mock/FakeExternalTexture.h | 51 ++++++++++ libs/renderengine/skia/Cache.cpp | 21 ++-- libs/renderengine/tests/RenderEngineTest.cpp | 57 ++++++----- .../tests/RenderEngineThreadedTest.cpp | 8 +- services/surfaceflinger/BufferLayer.cpp | 26 ++--- services/surfaceflinger/BufferLayerConsumer.cpp | 11 ++- services/surfaceflinger/BufferStateLayer.cpp | 70 ++++--------- services/surfaceflinger/BufferStateLayer.h | 6 +- services/surfaceflinger/ClientCache.cpp | 6 +- .../CompositionEngine/src/RenderSurface.cpp | 8 +- .../CompositionEngine/src/planner/TexturePool.cpp | 24 +++-- .../CompositionEngine/tests/OutputLayerTest.cpp | 10 +- .../CompositionEngine/tests/OutputTest.cpp | 31 +++--- .../CompositionEngine/tests/RenderSurfaceTest.cpp | 20 ++-- .../tests/planner/CachedSetTest.cpp | 17 ++-- .../tests/planner/FlattenerTest.cpp | 22 +++-- services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/RegionSamplingThread.cpp | 6 +- services/surfaceflinger/SurfaceFlinger.cpp | 51 ++++++++-- services/surfaceflinger/SurfaceFlinger.h | 3 + .../tests/unittests/CompositionTest.cpp | 13 ++- .../tests/unittests/TransactionFrameTracerTest.cpp | 13 ++- .../unittests/TransactionSurfaceFrameTest.cpp | 109 ++++++++++++++------- 28 files changed, 458 insertions(+), 265 deletions(-) create mode 100644 libs/renderengine/include/renderengine/impl/ExternalTexture.h create mode 100644 libs/renderengine/include/renderengine/mock/FakeExternalTexture.h (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/libs/renderengine/ExternalTexture.cpp b/libs/renderengine/ExternalTexture.cpp index eabff58eba..84771c0917 100644 --- a/libs/renderengine/ExternalTexture.cpp +++ b/libs/renderengine/ExternalTexture.cpp @@ -14,30 +14,32 @@ * limitations under the License. */ -#include #include +#include #include #include "log/log_main.h" -namespace android::renderengine { +namespace android::renderengine::impl { -ExternalTexture::ExternalTexture(const sp& buffer, RenderEngine& renderEngine, - uint32_t usage) +ExternalTexture::ExternalTexture(const sp& buffer, + renderengine::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)) { + if (usage == WRITEABLE && + (mRenderEngine.getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::GLES || + mRenderEngine.getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::THREADED)) { return; } - mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & Usage::WRITEABLE); + mRenderEngine.mapExternalTextureBuffer(mBuffer, usage & WRITEABLE); } ExternalTexture::~ExternalTexture() { mRenderEngine.unmapExternalTextureBuffer(mBuffer); } -} // namespace android::renderengine +} // namespace android::renderengine::impl diff --git a/libs/renderengine/benchmark/RenderEngineBench.cpp b/libs/renderengine/benchmark/RenderEngineBench.cpp index 6c8f8e878b..ead97cf5df 100644 --- a/libs/renderengine/benchmark/RenderEngineBench.cpp +++ b/libs/renderengine/benchmark/RenderEngineBench.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -115,15 +116,15 @@ static std::shared_ptr allocateBuffer(RenderEngine& re, uint32_ uint32_t height, uint64_t extraUsageFlags = 0, std::string name = "output") { - return std::make_shared(new GraphicBuffer(width, height, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_HW_RENDER | - GRALLOC_USAGE_HW_TEXTURE | - extraUsageFlags, - std::move(name)), - re, - ExternalTexture::Usage::READABLE | - ExternalTexture::Usage::WRITEABLE); + return std::make_shared< + impl::ExternalTexture>(new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE | + extraUsageFlags, + std::move(name)), + re, + impl::ExternalTexture::Usage::READABLE | + impl::ExternalTexture::Usage::WRITEABLE); } static std::shared_ptr copyBuffer(RenderEngine& re, diff --git a/libs/renderengine/include/renderengine/ExternalTexture.h b/libs/renderengine/include/renderengine/ExternalTexture.h index 07f0833d4a..621a209afa 100644 --- a/libs/renderengine/include/renderengine/ExternalTexture.h +++ b/libs/renderengine/include/renderengine/ExternalTexture.h @@ -33,28 +33,22 @@ class RenderEngine; */ 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(); + ExternalTexture() = default; + virtual ~ExternalTexture() = default; + + virtual bool hasSameBuffer(const ExternalTexture& other) const = 0; + virtual uint32_t getWidth() const = 0; + virtual uint32_t getHeight() const = 0; + virtual uint64_t getId() const = 0; + virtual PixelFormat getPixelFormat() const = 0; + virtual uint64_t getUsage() const = 0; // Retrieves the buffer that is bound to this texture. - const sp& getBuffer() const { return mBuffer; } + virtual const sp& getBuffer() const = 0; -private: - sp mBuffer; - RenderEngine& mRenderEngine; + Rect getBounds() const { + return {0, 0, static_cast(getWidth()), static_cast(getHeight())}; + } DISALLOW_COPY_AND_ASSIGN(ExternalTexture); }; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index d646756fc4..faa84fc1cd 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -76,6 +76,7 @@ class RenderEngineThreaded; namespace impl { class RenderEngine; +class ExternalTexture; } enum class Protection { @@ -228,7 +229,7 @@ protected: // avoid any thread synchronization that may be required by directly calling postRenderCleanup. virtual bool canSkipPostRenderCleanup() const = 0; - friend class ExternalTexture; + friend class impl::ExternalTexture; friend class threaded::RenderEngineThreaded; friend class RenderEngineTest_cleanupPostRender_cleansUpOnce_Test; const RenderEngineType mRenderEngineType; diff --git a/libs/renderengine/include/renderengine/impl/ExternalTexture.h b/libs/renderengine/include/renderengine/impl/ExternalTexture.h new file mode 100644 index 0000000000..c0e24f0c10 --- /dev/null +++ b/libs/renderengine/include/renderengine/impl/ExternalTexture.h @@ -0,0 +1,60 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +namespace android::renderengine::impl { + +class RenderEngine; + +class ExternalTexture : public android::renderengine::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, + android::renderengine::RenderEngine& renderEngine, uint32_t usage); + ~ExternalTexture(); + const sp& getBuffer() const override { return mBuffer; }; + uint32_t getWidth() const override { return getBuffer()->getWidth(); } + uint32_t getHeight() const override { return getBuffer()->getHeight(); } + uint64_t getId() const override { return getBuffer()->getId(); } + PixelFormat getPixelFormat() const override { return getBuffer()->getPixelFormat(); } + uint64_t getUsage() const override { return getBuffer()->getUsage(); } + bool hasSameBuffer(const renderengine::ExternalTexture& other) const override { + return getBuffer() == other.getBuffer(); + } + +private: + sp mBuffer; + android::renderengine::RenderEngine& mRenderEngine; +}; + +} // namespace android::renderengine::impl diff --git a/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h new file mode 100644 index 0000000000..974e0fddde --- /dev/null +++ b/libs/renderengine/include/renderengine/mock/FakeExternalTexture.h @@ -0,0 +1,51 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android { +namespace renderengine { +namespace mock { + +class FakeExternalTexture : public renderengine::ExternalTexture { + const sp mNullBuffer = nullptr; + uint32_t mWidth; + uint32_t mHeight; + uint64_t mId; + PixelFormat mPixelFormat; + uint64_t mUsage; + +public: + FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat, + uint64_t usage) + : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {} + const sp& getBuffer() const { return mNullBuffer; } + bool hasSameBuffer(const renderengine::ExternalTexture& other) const override { + return getId() == other.getId(); + } + uint32_t getWidth() const override { return mWidth; } + uint32_t getHeight() const override { return mHeight; } + uint64_t getId() const override { return mId; } + PixelFormat getPixelFormat() const override { return mPixelFormat; } + uint64_t getUsage() const override { return mUsage; } + ~FakeExternalTexture() = default; +}; + +} // namespace mock +} // namespace renderengine +} // namespace android diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp index b18a872836..a3a1969ee7 100644 --- a/libs/renderengine/skia/Cache.cpp +++ b/libs/renderengine/skia/Cache.cpp @@ -19,6 +19,7 @@ #include "android-base/unique_fd.h" #include "renderengine/DisplaySettings.h" #include "renderengine/LayerSettings.h" +#include "renderengine/impl/ExternalTexture.h" #include "ui/GraphicBuffer.h" #include "ui/GraphicTypes.h" #include "ui/PixelFormat.h" @@ -365,8 +366,8 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { 1, usage, "primeShaderCache_dst"); const auto dstTexture = - std::make_shared(dstBuffer, *renderengine, - ExternalTexture::Usage::WRITEABLE); + std::make_shared(dstBuffer, *renderengine, + impl::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 @@ -375,10 +376,10 @@ 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); + const auto srcTexture = std::make_shared< + impl::ExternalTexture>(srcBuffer, *renderengine, + impl::ExternalTexture::Usage::READABLE | + impl::ExternalTexture::Usage::WRITEABLE); drawHolePunchLayer(renderengine, display, dstTexture); drawSolidLayers(renderengine, display, dstTexture); @@ -398,8 +399,8 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { 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); + std::make_shared(externalBuffer, *renderengine, + impl::ExternalTexture::Usage::READABLE); std::vector> textures = {srcTexture, externalTexture}; @@ -412,8 +413,8 @@ void Cache::primeShaderCache(SkiaRenderEngine* renderengine) { status_t error = f16ExternalBuffer->initCheck(); if (!error) { const auto f16ExternalTexture = - std::make_shared(f16ExternalBuffer, *renderengine, - ExternalTexture::Usage::READABLE); + std::make_shared(f16ExternalBuffer, *renderengine, + impl::ExternalTexture::Usage::READABLE); textures.push_back(f16ExternalTexture); } diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index eb2b2dcbfa..2a25b0bfeb 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,7 @@ class RenderEngineTest : public ::testing::TestWithParam allocateDefaultBuffer() { return std::make_shared< - renderengine:: + renderengine::impl:: ExternalTexture>(new GraphicBuffer(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT, HAL_PIXEL_FORMAT_RGBA_8888, 1, @@ -188,15 +189,16 @@ public: GRALLOC_USAGE_HW_TEXTURE, "output"), *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); } // 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:: + renderengine::impl:: ExternalTexture>(new GraphicBuffer(width, height, HAL_PIXEL_FORMAT_RGBA_8888, 1, GRALLOC_USAGE_SW_READ_OFTEN | @@ -204,8 +206,9 @@ public: GRALLOC_USAGE_HW_TEXTURE, "input"), *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); } std::shared_ptr allocateAndFillSourceBuffer(uint32_t width, @@ -2439,16 +2442,17 @@ TEST_P(RenderEngineTest, test_tonemapPQMatches) { }; auto buf = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GRALLOC_USAGE_SW_READ_OFTEN | - GRALLOC_USAGE_SW_WRITE_OFTEN | - GRALLOC_USAGE_HW_RENDER | - GRALLOC_USAGE_HW_TEXTURE, - "input"), - *mRE, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, HAL_PIXEL_FORMAT_RGBA_8888, + 1, + GRALLOC_USAGE_SW_READ_OFTEN | + GRALLOC_USAGE_SW_WRITE_OFTEN | + GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE, + "input"), + *mRE, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); ASSERT_EQ(0, buf->getBuffer()->initCheck()); { @@ -2472,16 +2476,17 @@ TEST_P(RenderEngineTest, test_tonemapPQMatches) { } mBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, - 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); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(kGreyLevels, 1, 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::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); ASSERT_EQ(0, mBuffer->getBuffer()->initCheck()); const renderengine::LayerSettings layer{ diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index db7e12b71b..96851892b4 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "../threaded/RenderEngineThreaded.h" @@ -174,9 +175,10 @@ 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); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), *mRenderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); base::unique_fd bufferFence; diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index d61a4cbd01..649138a48e 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -164,7 +164,7 @@ std::optional BufferLayer::prepareCli const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || ((isSecure() || isProtected()) && !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", @@ -201,7 +201,7 @@ std::optional BufferLayer::prepareCli } layer.source.buffer.maxLuminanceNits = maxLuminance; 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(); @@ -436,7 +436,7 @@ void 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->getPixelFormat(); mBufferInfo.mFrameLatencyNeeded = true; } @@ -533,10 +533,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 != oldBufferInfo.mBuffer->getWidth() || + bufHeight != oldBufferInfo.mBuffer->getHeight()) { recomputeVisibleRegions = true; } } @@ -558,7 +558,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { bool BufferLayer::isProtected() const { return (mBufferInfo.mBuffer != nullptr) && - (mBufferInfo.mBuffer->getBuffer()->getUsage() & GRALLOC_USAGE_PROTECTED); + (mBufferInfo.mBuffer->getUsage() & GRALLOC_USAGE_PROTECTED); } // As documented in libhardware header, formats in the range @@ -638,8 +638,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) { @@ -670,8 +670,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) { @@ -713,7 +713,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(); diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index c79fa1104c..9ae45fc4cb 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -208,8 +209,9 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres 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); + renderengine::impl::ExternalTexture>(item->mGraphicBuffer, mRE, + renderengine::impl::ExternalTexture:: + Usage::READABLE); } } @@ -462,8 +464,9 @@ void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) { 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); + renderengine::impl::ExternalTexture>(item.mGraphicBuffer, mRE, + renderengine::impl::ExternalTexture:: + Usage::READABLE); } } } diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 2fac880065..6cecd8956a 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -295,8 +295,8 @@ bool BufferStateLayer::updateGeometry() { return assignTransform(&mDrawingState.transform, t); } - uint32_t bufferWidth = mDrawingState.buffer->getBuffer()->getWidth(); - uint32_t bufferHeight = mDrawingState.buffer->getBuffer()->getHeight(); + uint32_t bufferWidth = mDrawingState.buffer->getWidth(); + uint32_t bufferHeight = mDrawingState.buffer->getHeight(); // Undo any transformations on the buffer. if (mDrawingState.bufferTransform & ui::Transform::ROT_90) { std::swap(bufferWidth, bufferHeight); @@ -368,46 +368,13 @@ bool BufferStateLayer::addFrameEvent(const sp& acquireFence, nsecs_t post return true; } -std::shared_ptr BufferStateLayer::getBufferFromBufferData( - const BufferData& bufferData) { - bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged); - bool bufferSizeExceedsLimit = false; - std::shared_ptr buffer = nullptr; - if (cacheIdChanged && bufferData.buffer != nullptr) { - bufferSizeExceedsLimit = - mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), - bufferData.buffer->getHeight()); - if (!bufferSizeExceedsLimit) { - ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer); - buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); - } - } else if (cacheIdChanged) { - buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); - } else if (bufferData.buffer != nullptr) { - bufferSizeExceedsLimit = - mFlinger->exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), - bufferData.buffer->getHeight()); - if (!bufferSizeExceedsLimit) { - buffer = std::make_shared< - renderengine::ExternalTexture>(bufferData.buffer, mFlinger->getRenderEngine(), - renderengine::ExternalTexture::Usage::READABLE); - } - } - ALOGE_IF(bufferSizeExceedsLimit, - "Attempted to create an ExternalTexture for layer %s that exceeds render target size " - "limit.", - getDebugName()); - return buffer; -} - -bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, +bool BufferStateLayer::setBuffer(std::shared_ptr& buffer, + const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, std::optional dequeueTime, const FrameTimelineInfo& info) { ATRACE_CALL(); - const std::shared_ptr& buffer = - getBufferFromBufferData(bufferData); if (!buffer) { return false; } @@ -419,8 +386,9 @@ bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, if (mDrawingState.buffer) { mReleasePreviousBuffer = true; - if (mDrawingState.buffer != mBufferInfo.mBuffer || - mDrawingState.frameNumber != mBufferInfo.mFrameNumber) { + if (!mBufferInfo.mBuffer || + (!mDrawingState.buffer->hasSameBuffer(*mBufferInfo.mBuffer) || + mDrawingState.frameNumber != mBufferInfo.mFrameNumber)) { // 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 @@ -448,7 +416,7 @@ bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, mDrawingState.frameNumber = frameNumber; mDrawingState.releaseBufferListener = bufferData.releaseBufferListener; - mDrawingState.buffer = buffer; + mDrawingState.buffer = std::move(buffer); mDrawingState.clientCacheId = bufferData.cachedBuffer; mDrawingState.acquireFence = bufferData.flags.test(BufferData::BufferDataChange::fenceChanged) @@ -485,7 +453,7 @@ bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, setFrameTimelineVsyncForBufferTransaction(info, postTime); if (buffer && dequeueTime && *dequeueTime != 0) { - const uint64_t bufferId = buffer->getBuffer()->getId(); + const uint64_t bufferId = buffer->getId(); mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, frameNumber, *dequeueTime, FrameTracer::FrameEvent::DEQUEUE); @@ -493,8 +461,8 @@ bool BufferStateLayer::setBuffer(const BufferData& bufferData, nsecs_t postTime, FrameTracer::FrameEvent::QUEUE); } - mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth(); - mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight(); + mDrawingState.width = mDrawingState.buffer->getWidth(); + mDrawingState.height = mDrawingState.buffer->getHeight(); mDrawingState.releaseBufferEndpoint = bufferData.releaseBufferEndpoint; return true; } @@ -599,8 +567,8 @@ Rect BufferStateLayer::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) { @@ -709,7 +677,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); @@ -749,7 +717,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } - if (!mBufferInfo.mBuffer || s.buffer->getBuffer() != mBufferInfo.mBuffer->getBuffer()) { + if (!mBufferInfo.mBuffer || !s.buffer->hasSameBuffer(*mBufferInfo.mBuffer)) { decrementPendingBufferCount(); } @@ -874,10 +842,10 @@ uint32_t BufferStateLayer::getEffectiveScalingMode() const { Rect BufferStateLayer::computeBufferCrop(const State& s) { if (s.buffer && !s.bufferCrop.isEmpty()) { Rect bufferCrop; - s.buffer->getBuffer()->getBounds().intersect(s.bufferCrop, &bufferCrop); + s.buffer->getBounds().intersect(s.bufferCrop, &bufferCrop); return bufferCrop; } else if (s.buffer) { - return s.buffer->getBuffer()->getBounds(); + return s.buffer->getBounds(); } else { return s.bufferCrop; } @@ -898,8 +866,8 @@ bool BufferStateLayer::bufferNeedsFiltering() const { return false; } - int32_t bufferWidth = s.buffer->getBuffer()->width; - int32_t bufferHeight = s.buffer->getBuffer()->height; + int32_t bufferWidth = static_cast(s.buffer->getWidth()); + int32_t bufferHeight = static_cast(s.buffer->getHeight()); // Undo any transformations on the buffer and return the result. if (s.bufferTransform & ui::Transform::ROT_90) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index eea700cf7b..2f613d7f26 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -57,7 +57,8 @@ public: bool setTransform(uint32_t transform) override; bool setTransformToDisplayInverse(bool transformToDisplayInverse) override; bool setCrop(const Rect& crop) override; - bool setBuffer(const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, + bool setBuffer(std::shared_ptr& /* buffer */, + const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp, std::optional dequeueTime, const FrameTimelineInfo& info) override; bool setDataspace(ui::Dataspace dataspace) override; @@ -136,9 +137,6 @@ private: bool bufferNeedsFiltering() const override; - std::shared_ptr getBufferFromBufferData( - const BufferData& bufferData); - ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID; uint64_t mPreviousReleasedFrameNumber = 0; diff --git a/services/surfaceflinger/ClientCache.cpp b/services/surfaceflinger/ClientCache.cpp index e7b8995703..3c7b9d93aa 100644 --- a/services/surfaceflinger/ClientCache.cpp +++ b/services/surfaceflinger/ClientCache.cpp @@ -22,6 +22,7 @@ #include #include +#include #include "ClientCache.h" @@ -109,8 +110,9 @@ bool ClientCache::add(const client_cache_t& cacheId, const sp& bu "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); + renderengine::impl::ExternalTexture>(buffer, *mRenderEngine, + renderengine::impl::ExternalTexture::Usage:: + READABLE); return true; } diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index a19d23febf..12c2c8eb38 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -182,9 +183,10 @@ std::shared_ptr RenderSurface::dequeueBuffer( mTexture = texture; } else { mTexture = std::make_shared< - renderengine::ExternalTexture>(GraphicBuffer::from(buffer), - mCompositionEngine.getRenderEngine(), - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl::ExternalTexture>(GraphicBuffer::from(buffer), + mCompositionEngine.getRenderEngine(), + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); } mTextureCache.push_back(mTexture); if (mTextureCache.size() > mMaxTextureCacheSize) { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp index 497c433c76..54ecb5691d 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/TexturePool.cpp @@ -20,6 +20,7 @@ #define LOG_TAG "Planner" #include +#include #include namespace android::compositionengine::impl::planner { @@ -82,16 +83,19 @@ void TexturePool::returnTexture(std::shared_ptr&& std::shared_ptr TexturePool::genTexture() { LOG_ALWAYS_FATAL_IF(!mSize.isValid(), "Attempted to generate texture with invalid size"); return std::make_shared< - renderengine::ExternalTexture>(sp:: - make(mSize.getWidth(), mSize.getHeight(), - HAL_PIXEL_FORMAT_RGBA_8888, 1, - GraphicBuffer::USAGE_HW_RENDER | - GraphicBuffer::USAGE_HW_COMPOSER | - GraphicBuffer::USAGE_HW_TEXTURE, - "Planner"), - mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl:: + ExternalTexture>(sp:: + make(static_cast(mSize.getWidth()), + static_cast(mSize.getHeight()), + HAL_PIXEL_FORMAT_RGBA_8888, 1U, + static_cast( + GraphicBuffer::USAGE_HW_RENDER | + GraphicBuffer::USAGE_HW_COMPOSER | + GraphicBuffer::USAGE_HW_TEXTURE), + "Planner"), + mRenderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); } void TexturePool::setEnabled(bool enabled) { diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index ad7976f64c..37f17f5a9a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include "MockHWC2.h" @@ -815,10 +816,11 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { auto& overrideInfo = mOutputLayer.editState().overrideInfo; overrideInfo.buffer = std::make_shared< - renderengine::ExternalTexture>(kOverrideBuffer, mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage:: - WRITEABLE); + renderengine::impl::ExternalTexture>(kOverrideBuffer, mRenderEngine, + renderengine::impl::ExternalTexture::Usage:: + READABLE | + renderengine::impl::ExternalTexture:: + Usage::WRITEABLE); overrideInfo.acquireFence = kOverrideFence; overrideInfo.displayFrame = kOverrideDisplayFrame; overrideInfo.dataspace = kOverrideDataspace; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 6d96260de7..5fcb52d260 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,7 +39,6 @@ #include "MockHWC2.h" #include "RegionMatcher.h" #include "TestUtils.h" -#include "renderengine/ExternalTexture.h" namespace android::compositionengine { namespace { @@ -273,9 +274,10 @@ TEST_F(OutputTest, setLayerCachingEnabled_disablesCachingAndResetsOverrideInfo) // Inject some layers InjectedLayer layer; layer.outputLayerState.overrideInfo.buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), renderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); injectOutputLayer(layer); // inject a null layer to check for null exceptions injectNullOutputLayer(); @@ -956,9 +958,10 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, peekThroughLayerChangesOrder) { mOutput->planComposition(); std::shared_ptr buffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), renderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), renderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); layer1.outputLayerState.overrideInfo.buffer = buffer; layer2.outputLayerState.overrideInfo.buffer = buffer; layer1.outputLayerState.overrideInfo.peekThroughLayer = layer3.outputLayer; @@ -3077,9 +3080,10 @@ struct OutputComposeSurfacesTest : public testing::Test { 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); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); std::optional mReadyFence; }; @@ -3313,9 +3317,10 @@ TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) { .WillRepeatedly(Return()); const auto otherOutputBuffer = std::make_shared< - renderengine::ExternalTexture>(new GraphicBuffer(), mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE | - renderengine::ExternalTexture::Usage::WRITEABLE); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::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 7c8e41b53e..e5f9ebfbeb 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -251,9 +252,10 @@ 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); + renderengine::impl:: + ExternalTexture>(new GraphicBuffer(), mRenderEngine, + renderengine::impl::ExternalTexture::Usage::READABLE | + renderengine::impl::ExternalTexture::Usage::WRITEABLE); mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; @@ -269,8 +271,8 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesNoClientComposition) { } TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; @@ -288,8 +290,8 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesClientComposition) { } TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequest) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; @@ -327,8 +329,8 @@ TEST_F(RenderSurfaceTest, queueBufferHandlesFlipClientTargetRequestWithNoBufferY } TEST_F(RenderSurfaceTest, queueBufferHandlesNativeWindowQueueBufferFailureOnVirtualDisplay) { - const auto buffer = std::make_shared(new GraphicBuffer(), - mRenderEngine, false); + const auto buffer = std::make_shared(new GraphicBuffer(), + mRenderEngine, false); mSurface.mutableTextureForTest() = buffer; impl::OutputCompositionState state; diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index d5a117a597..4ae921d661 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -702,9 +703,11 @@ TEST_F(CachedSetTest, addHolePunch) { std::vector clientCompList3; clientCompList3.push_back({}); - clientCompList3[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(sp::make(), mRenderEngine, - renderengine::ExternalTexture::READABLE); + clientCompList3[0].source.buffer.buffer = + std::make_shared(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); @@ -901,9 +904,11 @@ TEST_F(CachedSetTest, addBlur) { std::vector clientCompList3; clientCompList3.push_back({}); - clientCompList3[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(sp::make(), mRenderEngine, - renderengine::ExternalTexture::READABLE); + clientCompList3[0].source.buffer.buffer = + std::make_shared(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); EXPECT_CALL(*layerFE1, prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq( diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index 35d051ebea..58dc244402 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -639,9 +640,10 @@ TEST_F(FlattenerTest, flattenLayers_pip) { LayerFE::LayerSettings{}, }; clientCompositionList[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer, - mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); + renderengine::impl::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer, + mRenderEngine, + renderengine::impl::ExternalTexture::Usage:: + READABLE); EXPECT_CALL(*mTestLayers[2]->layerFE, prepareClientCompositionList(_)) .WillOnce(Return(clientCompositionList)); @@ -711,9 +713,10 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) { LayerFE::LayerSettings{}, }; clientCompositionList[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, - mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); + renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, + mRenderEngine, + renderengine::impl::ExternalTexture::Usage:: + READABLE); EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_)) .WillOnce(Return(clientCompositionList)); @@ -781,9 +784,10 @@ TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) { LayerFE::LayerSettings{}, }; clientCompositionList[0].source.buffer.buffer = std::make_shared< - renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, - mRenderEngine, - renderengine::ExternalTexture::Usage::READABLE); + renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, + mRenderEngine, + renderengine::impl::ExternalTexture::Usage:: + READABLE); EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_)) .WillOnce(Return(clientCompositionList)); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 31cdf0b3e4..0d2618acf5 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -416,8 +416,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 BufferData&, nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/, - bool /*isAutoTimestamp*/, std::optional /* dequeueTime */, + virtual bool setBuffer(std::shared_ptr& /* buffer */, + const BufferData& /* bufferData */, nsecs_t /* postTime */, + nsecs_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/, + std::optional /* dequeueTime */, const FrameTimelineInfo& /*info*/) { return false; }; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index da8c3e062c..ff30348151 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -351,8 +352,9 @@ void RegionSamplingThread::captureSample() { 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); + renderengine::impl::ExternalTexture>(graphicBuffer, mFlinger.getRenderEngine(), + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); } auto captureScreenResultFuture = diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bd13c4169c..1dc75c8f43 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -4419,10 +4420,13 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime } } - if (what & layer_state_t::eBufferChanged && - layer->setBuffer(*s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, - dequeueBufferTimestamp, frameTimelineInfo)) { - flags |= eTraversalNeeded; + if (what & layer_state_t::eBufferChanged) { + std::shared_ptr buffer = + getExternalTextureFromBufferData(*s.bufferData, layer->getDebugName()); + if (layer->setBuffer(buffer, *s.bufferData, postTime, desiredPresentTime, isAutoTimestamp, + dequeueBufferTimestamp, frameTimelineInfo)) { + flags |= eTraversalNeeded; + } } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { layer->setFrameTimelineVsyncForBufferlessTransaction(frameTimelineInfo, postTime); } @@ -6384,9 +6388,10 @@ std::shared_future SurfaceFlinger::captureScre 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); + const std::shared_ptr texture = std::make_shared< + renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, texture, false /* regionSampling */, grayscale, captureListener); } @@ -6463,7 +6468,7 @@ std::shared_future SurfaceFlinger::renderScree 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 @@ -7074,6 +7079,36 @@ status_t SurfaceFlinger::removeWindowInfosListener( return NO_ERROR; } +std::shared_ptr SurfaceFlinger::getExternalTextureFromBufferData( + const BufferData& bufferData, const char* layerName) const { + bool cacheIdChanged = bufferData.flags.test(BufferData::BufferDataChange::cachedBufferChanged); + bool bufferSizeExceedsLimit = false; + std::shared_ptr buffer = nullptr; + if (cacheIdChanged && bufferData.buffer != nullptr) { + bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), + bufferData.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + ClientCache::getInstance().add(bufferData.cachedBuffer, bufferData.buffer); + buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); + } + } else if (cacheIdChanged) { + buffer = ClientCache::getInstance().get(bufferData.cachedBuffer); + } else if (bufferData.buffer != nullptr) { + bufferSizeExceedsLimit = exceedsMaxRenderTargetSize(bufferData.buffer->getWidth(), + bufferData.buffer->getHeight()); + if (!bufferSizeExceedsLimit) { + buffer = std::make_shared< + renderengine::impl::ExternalTexture>(bufferData.buffer, getRenderEngine(), + renderengine::impl::ExternalTexture:: + Usage::READABLE); + } + } + ALOGE_IF(bufferSizeExceedsLimit, + "Attempted to create an ExternalTexture for layer %s that exceeds render target size " + "limit.", + layerName); + return buffer; +} } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0c4236f9a4..338b35793d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -330,6 +330,9 @@ protected: virtual void processDisplayAdded(const wp& displayToken, const DisplayDeviceState&) REQUIRES(mStateLock); + virtual std::shared_ptr getExternalTextureFromBufferData( + const BufferData& bufferData, const char* layerName) const; + // Returns true if any display matches a `bool(const DisplayDevice&)` predicate. template bool hasDisplay(Predicate p) const REQUIRES(mStateLock) { diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index f1e9b314d8..427159fda9 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -234,15 +235,13 @@ void CompositionTest::captureScreenComposition() { CaptureArgs::UNSET_UID, visitor); }; - // 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 = + std::make_shared(renderArea->getReqWidth(), + renderArea->getReqHeight(), + HAL_PIXEL_FORMAT_RGBA_8888, 1, + usage); auto result = mFlinger.renderScreenImplLocked(*renderArea, traverseLayers, mCaptureScreenBuffer, forSystem, regionSampling); diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp index deeb785bb9..5364630400 100644 --- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -101,9 +102,8 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); int32_t layerId = layer->getSequence(); - uint64_t bufferId = buffer->getId(); + uint64_t bufferId = 42; uint64_t frameNumber = 5; nsecs_t dequeueTime = 10; nsecs_t postTime = 20; @@ -115,13 +115,16 @@ public: traceTimestamp(layerId, bufferId, frameNumber, postTime, FrameTracer::FrameEvent::QUEUE, /*duration*/ 0)); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = frameNumber; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, postTime, /*desiredPresentTime*/ 30, false, dequeueTime, - FrameTimelineInfo{}); + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, bufferId, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, postTime, /*desiredPresentTime*/ 30, false, + dequeueTime, FrameTimelineInfo{}); commitTransaction(layer.get()); bool computeVisisbleRegions; diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp index 704340deac..5bb4c92a8e 100644 --- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -114,14 +115,17 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence->signalForTest(12); @@ -145,14 +149,17 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer1; bufferData.acquireFence = fence1; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture1 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -160,14 +167,17 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); nsecs_t start = systemTime(); - bufferData.buffer = buffer2; bufferData.acquireFence = fence2; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture2 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 2ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); nsecs_t end = systemTime(); acquireFence2->signalForTest(12); @@ -203,14 +213,17 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence->signalForTest(12); @@ -234,14 +247,17 @@ public: sp layer = createBufferStateLayer(); sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -269,14 +285,17 @@ public: sp fence(new Fence()); auto acquireFence = fenceFactory.createFenceTimeForTest(fence); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 3, /*inputEventId*/ 0}); EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -310,27 +329,33 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer1; bufferData.acquireFence = fence1; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture1 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX; sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); - bufferData.buffer = buffer2; bufferData.acquireFence = fence2; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture2 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); acquireFence2->signalForTest(12); @@ -356,14 +381,17 @@ public: sp fence1(new Fence()); auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1); - const auto buffer1 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer1; bufferData.acquireFence = fence1; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture1 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX); @@ -371,14 +399,17 @@ public: sp fence2(new Fence()); auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2); - const auto buffer2 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); auto dropStartTime1 = systemTime(); - bufferData.buffer = buffer2; bufferData.acquireFence = fence2; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture2 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0}); auto dropEndTime1 = systemTime(); EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size()); @@ -387,14 +418,17 @@ public: sp fence3(new Fence()); auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3); - const auto buffer3 = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); auto dropStartTime2 = systemTime(); - bufferData.buffer = buffer3; bufferData.acquireFence = fence3; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture3 = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture3, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 2, /*inputEventId*/ 0}); auto dropEndTime2 = systemTime(); acquireFence3->signalForTest(12); @@ -432,14 +466,17 @@ public: std::vector> bufferlessSurfaceFrames; for (int i = 0; i < 10; i += 2) { sp fence(new Fence()); - const auto buffer = new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0); BufferData bufferData; - bufferData.buffer = buffer; bufferData.acquireFence = fence; bufferData.frameNumber = 1; bufferData.flags |= BufferData::BufferDataChange::fenceChanged; bufferData.flags |= BufferData::BufferDataChange::frameNumberChanged; - layer->setBuffer(bufferData, 10, 20, false, std::nullopt, + std::shared_ptr externalTexture = std::make_shared< + renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/, + 1ULL /* bufferId */, + HAL_PIXEL_FORMAT_RGBA_8888, + 0ULL /*usage*/); + layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, {/*vsyncId*/ 1, /*inputEventId*/ 0}); layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0}, -- cgit v1.2.3-59-g8ed1b From a339d0ad21f62253f234f2286a6cca7f30158830 Mon Sep 17 00:00:00 2001 From: Huihong Luo Date: Sat, 5 Feb 2022 09:42:42 -0800 Subject: Consolidate SpHash to a separate header file Remove duplicates and avoid circular dependency issues when migrating to AIDL. Bug: 211037638 Test: manual Change-Id: I37dd03d06e7bd6346d3b93e3acc61e7d481fda9f --- libs/gui/WindowInfosListenerReporter.cpp | 5 ++-- libs/gui/include/gui/ISurfaceComposer.h | 7 ++--- libs/gui/include/gui/LayerState.h | 3 ++- libs/gui/include/gui/SpHash.h | 31 ++++++++++++++++++++++ libs/gui/include/gui/WindowInfosListenerReporter.h | 6 ++--- services/surfaceflinger/RegionSamplingThread.cpp | 6 ++--- services/surfaceflinger/SurfaceFlinger.cpp | 7 +++-- services/surfaceflinger/SurfaceFlinger.h | 5 ++-- .../surfaceflinger/WindowInfosListenerInvoker.cpp | 3 +-- 9 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 libs/gui/include/gui/SpHash.h (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp index c32b9ab398..4112f74068 100644 --- a/libs/gui/WindowInfosListenerReporter.cpp +++ b/libs/gui/WindowInfosListenerReporter.cpp @@ -68,8 +68,7 @@ status_t WindowInfosListenerReporter::removeWindowInfosListener( binder::Status WindowInfosListenerReporter::onWindowInfosChanged( const std::vector& windowInfos, const std::vector& displayInfos, const sp& windowInfosReportedListener) { - std::unordered_set, ISurfaceComposer::SpHash> - windowInfosListeners; + std::unordered_set, SpHash> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); @@ -96,4 +95,4 @@ void WindowInfosListenerReporter::reconnect(const sp& composer } } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 4b5cee256a..90b2a0e05f 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +71,7 @@ enum class FrameEvent; using gui::IDisplayEventConnection; using gui::IRegionSamplingListener; using gui::IScreenCaptureListener; +using gui::SpHash; namespace ui { @@ -118,11 +120,6 @@ public: using EventRegistrationFlags = Flags; - template - struct SpHash { - size_t operator()(const sp& k) const { return std::hash()(k.get()); } - }; - /* * Create a connection with SurfaceFlinger. */ diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index cd6afd29a0..f7206193cd 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -412,7 +413,7 @@ struct DisplayCaptureArgs : CaptureArgs { struct LayerCaptureArgs : CaptureArgs { sp layerHandle; - std::unordered_set, ISurfaceComposer::SpHash> excludeHandles; + std::unordered_set, SpHash> excludeHandles; bool childrenOnly{false}; status_t write(Parcel& output) const override; diff --git a/libs/gui/include/gui/SpHash.h b/libs/gui/include/gui/SpHash.h new file mode 100644 index 0000000000..5162f01041 --- /dev/null +++ b/libs/gui/include/gui/SpHash.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include + +namespace android::gui { + +template +struct SpHash { + size_t operator()(const sp& k) const { return std::hash()(k.get()); } +}; + +}; // namespace android::gui diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h index 157a804264..96bd0b1db0 100644 --- a/libs/gui/include/gui/WindowInfosListenerReporter.h +++ b/libs/gui/include/gui/WindowInfosListenerReporter.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -41,8 +42,7 @@ public: private: std::mutex mListenersMutex; - std::unordered_set, - ISurfaceComposer::SpHash> + std::unordered_set, SpHash> mWindowInfosListeners GUARDED_BY(mListenersMutex); }; -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index ff30348151..e29e6ab05f 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,10 +47,7 @@ namespace android { using namespace std::chrono_literals; -template -struct SpHash { - size_t operator()(const sp& p) const { return std::hash()(p.get()); } -}; +using gui::SpHash; constexpr auto lumaSamplingStepTag = "LumaSamplingStep"; enum class samplingStep { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b3c3a4147b..4a5413b64a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3645,7 +3645,7 @@ bool SurfaceFlinger::flushTransactionQueues(int64_t vsyncId) { // states) around outside the scope of the lock std::vector transactions; // Layer handles that have transactions with buffers that are ready to be applied. - std::unordered_set, ISurfaceComposer::SpHash> bufferLayersReadyToPresent; + std::unordered_set, SpHash> bufferLayersReadyToPresent; { Mutex::Autolock _l(mStateLock); { @@ -3842,8 +3842,7 @@ bool SurfaceFlinger::frameIsEarly(nsecs_t expectedPresentTime, int64_t vsyncId) bool SurfaceFlinger::transactionIsReadyToBeApplied( const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector& states, - const std::unordered_set, ISurfaceComposer::SpHash>& - bufferLayersReadyToPresent, + const std::unordered_set, SpHash>& bufferLayersReadyToPresent, bool allowLatchUnsignaled) const { ATRACE_FORMAT("transactionIsReadyToBeApplied vsyncId: %" PRId64, info.vsyncId); const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); @@ -6291,7 +6290,7 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Size reqSize; sp parent; Rect crop(args.sourceCrop); - std::unordered_set, ISurfaceComposer::SpHash> excludeLayers; + std::unordered_set, SpHash> excludeLayers; ui::Dataspace dataspace; // Call this before holding mStateLock to avoid any deadlocking. diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 77193a6939..1b8f62aacf 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -752,8 +752,7 @@ private: bool transactionIsReadyToBeApplied( const FrameTimelineInfo& info, bool isAutoTimestamp, int64_t desiredPresentTime, uid_t originUid, const Vector& states, - const std::unordered_set, ISurfaceComposer::SpHash>& - bufferLayersReadyToPresent, + const std::unordered_set, SpHash>& bufferLayersReadyToPresent, bool allowLatchUnsignaled) const REQUIRES(mStateLock); static LatchUnsignaledConfig getLatchUnsignaledConfig(); bool latchUnsignaledIsAllowed(std::vector& transactions) REQUIRES(mStateLock); @@ -1155,7 +1154,7 @@ private: // Tracks layers that have pending frames which are candidates for being // latched. - std::unordered_set, ISurfaceComposer::SpHash> mLayersWithQueuedFrames; + std::unordered_set, SpHash> mLayersWithQueuedFrames; // Tracks layers that need to update a display's dirty region. std::vector> mLayersPendingRefresh; std::array mPreviousPresentFences; diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp index 72434e943a..23cd99336a 100644 --- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp +++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp @@ -67,8 +67,7 @@ void WindowInfosListenerInvoker::binderDied(const wp& who) { void WindowInfosListenerInvoker::windowInfosChanged(const std::vector& windowInfos, const std::vector& displayInfos, bool shouldSync) { - std::unordered_set, ISurfaceComposer::SpHash> - windowInfosListeners; + std::unordered_set, SpHash> windowInfosListeners; { std::scoped_lock lock(mListenersMutex); -- cgit v1.2.3-59-g8ed1b From bb448ce9aa521f9574d94c9ec2d57eb7d37382cb Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Sat, 7 May 2022 15:52:55 -0700 Subject: SF: Do not duplicate fences per layer per frame Convert the unique_fd of RenderEngineResult (and futures thereof) into sp such that postFramebuffer does not duplicate release/present fences. Remove a few copies of shared futures/pointers with std::move. Bug: 232436803 Test: simpleperf (-33% cycles in sys_dup) Change-Id: Ia7c6c8333a712441f3612fb5c720ea2932799636 --- services/surfaceflinger/BufferQueueLayer.cpp | 5 +- services/surfaceflinger/BufferQueueLayer.h | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 5 +- services/surfaceflinger/BufferStateLayer.h | 3 +- .../include/compositionengine/FenceResult.h | 49 +++++++++ .../include/compositionengine/LayerFE.h | 5 +- .../include/compositionengine/mock/LayerFE.h | 2 +- .../CompositionEngine/src/Output.cpp | 43 ++++---- .../CompositionEngine/src/planner/CachedSet.cpp | 15 +-- .../CompositionEngine/tests/OutputTest.cpp | 54 ++++------ services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RegionSamplingThread.cpp | 15 +-- services/surfaceflinger/SurfaceFlinger.cpp | 117 ++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 12 ++- .../surfaceflinger/TransactionCallbackInvoker.cpp | 13 +-- .../surfaceflinger/TransactionCallbackInvoker.h | 4 +- .../fuzzer/surfaceflinger_layer_fuzzer.cpp | 11 +- .../tests/unittests/CompositionTest.cpp | 13 ++- 19 files changed, 201 insertions(+), 174 deletions(-) create mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h (limited to 'services/surfaceflinger/RegionSamplingThread.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 926aa1dfb2..6a1a38b39c 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -48,9 +48,8 @@ BufferQueueLayer::~BufferQueueLayer() { // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferQueueLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { - sp releaseFence = new Fence(dup(futureRenderEngineResult.get().drawFence)); +void BufferQueueLayer::onLayerDisplayed(std::shared_future futureFenceResult) { + const sp releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE); mConsumer->setReleaseFence(releaseFence); // Prevent tracing the same release multiple times. diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index c6e0727806..4587b5e27c 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -42,8 +42,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferQueueLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c5d7a601c5..c88511049b 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -73,8 +73,7 @@ BufferStateLayer::~BufferStateLayer() { // ----------------------------------------------------------------------- // Interface implementation for Layer // ----------------------------------------------------------------------- -void BufferStateLayer::onLayerDisplayed( - std::shared_future futureRenderEngineResult) { +void BufferStateLayer::onLayerDisplayed(std::shared_future futureFenceResult) { // If we are displayed on multiple displays in a single composition cycle then we would // need to do careful tracking to enable the use of the mLastClientCompositionFence. // For example we can only use it if all the displays are client comp, and we need @@ -118,7 +117,7 @@ void BufferStateLayer::onLayerDisplayed( if (ch != nullptr) { ch->previousReleaseCallbackId = mPreviousReleaseCallbackId; - ch->previousReleaseFences.emplace_back(futureRenderEngineResult); + ch->previousReleaseFences.emplace_back(std::move(futureFenceResult)); ch->name = mName; } } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 8a696f11b4..cc510d8c74 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -39,8 +39,7 @@ public: // Implements Layer. const char* getType() const override { return "BufferStateLayer"; } - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; void releasePendingBuffer(nsecs_t dequeueReadyTime) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h new file mode 100644 index 0000000000..0ce263b930 --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/FenceResult.h @@ -0,0 +1,49 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +// TODO(b/232535621): Pull this file to so that RenderEngine::drawLayers returns +// FenceResult rather than RenderEngineResult. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" +#include +#pragma clang diagnostic pop + +namespace android { + +class Fence; + +using FenceResult = base::expected, status_t>; + +// TODO(b/232535621): Prevent base::unexpected(NO_ERROR) from being a valid FenceResult. +inline status_t fenceStatus(const FenceResult& fenceResult) { + return fenceResult.ok() ? NO_ERROR : fenceResult.error(); +} + +inline FenceResult toFenceResult(renderengine::RenderEngineResult&& result) { + if (auto [status, fence] = std::move(result); fence.ok()) { + return sp::make(std::move(fence)); + } else { + return base::unexpected(status); + } +} + +} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index e77e155cb8..b7fc62fd21 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -21,13 +21,14 @@ #include #include +#include + // 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 // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" @@ -156,7 +157,7 @@ public: ClientCompositionTargetSettings&) = 0; // Called after the layer is displayed to update the presentation fence - virtual void onLayerDisplayed(std::shared_future) = 0; + virtual void onLayerDisplayed(std::shared_future) = 0; // Gets some kind of identifier for the layer for debug purposes. virtual const char* getDebugName() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index ee0c53ded7..871599d2cd 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -49,7 +49,7 @@ public: std::vector( compositionengine::LayerFE::ClientCompositionTargetSettings&)); - MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); + MOCK_METHOD1(onLayerDisplayed, void(std::shared_future)); MOCK_CONST_METHOD0(getDebugName, const char*()); MOCK_CONST_METHOD0(getSequence, int32_t()); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 4c30f99610..742332ca24 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1245,34 +1245,31 @@ std::optional Output::composeSurfaces( // probably to encapsulate the output buffer into a structure that dispatches resource cleanup // over to RenderEngine, in which case this flag can be removed from the drawLayers interface. const bool useFramebufferCache = outputState.layerFilter.toInternalDisplay; - auto [status, drawFence] = - renderEngine - .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, tex, - useFramebufferCache, std::move(fd)) - .get(); - if (status != NO_ERROR && mClientCompositionRequestCache) { + auto fenceResult = + toFenceResult(renderEngine + .drawLayers(clientCompositionDisplay, clientRenderEngineLayers, + tex, useFramebufferCache, std::move(fd)) + .get()); + + if (mClientCompositionRequestCache && fenceStatus(fenceResult) != NO_ERROR) { // If rendering was not successful, remove the request from the cache. mClientCompositionRequestCache->remove(tex->getBuffer()->getId()); } - auto& timeStats = getCompositionEngine().getTimeStats(); - if (drawFence.get() < 0) { - timeStats.recordRenderEngineDuration(renderEngineStart, systemTime()); + const auto fence = std::move(fenceResult).value_or(Fence::NO_FENCE); + + if (auto& timeStats = getCompositionEngine().getTimeStats(); fence->isValid()) { + timeStats.recordRenderEngineDuration(renderEngineStart, std::make_shared(fence)); } else { - timeStats.recordRenderEngineDuration(renderEngineStart, - std::make_shared( - new Fence(dup(drawFence.get())))); + timeStats.recordRenderEngineDuration(renderEngineStart, systemTime()); } - if (clientCompositionLayersFE.size() > 0) { - sp clientCompFence = new Fence(dup(drawFence.get())); - for (auto clientComposedLayer : clientCompositionLayersFE) { - clientComposedLayer->setWasClientComposed(clientCompFence); - } + for (auto* clientComposedLayer : clientCompositionLayersFE) { + clientComposedLayer->setWasClientComposed(fence); } - return std::move(drawFence); + return base::unique_fd(fence->dup()); } std::vector Output::generateClientCompositionRequests( @@ -1429,19 +1426,15 @@ void Output::postFramebuffer() { Fence::merge("LayerRelease", releaseFence, frame.clientTargetAcquireFence); } layer->getLayerFE().onLayerDisplayed( - ftl::yield( - {NO_ERROR, base::unique_fd(releaseFence->dup())}) - .share()); + ftl::yield(std::move(releaseFence)).share()); } // We've got a list of layers needing fences, that are disjoint with // OutputLayersOrderedByZ. The best we can do is to // supply them with the present fence. for (auto& weakLayer : mReleasedLayers) { - if (auto layer = weakLayer.promote(); layer != nullptr) { - layer->onLayerDisplayed(ftl::yield( - {NO_ERROR, base::unique_fd(frame.presentFence->dup())}) - .share()); + if (const auto layer = weakLayer.promote()) { + layer->onLayerDisplayed(ftl::yield(frame.presentFence).share()); } } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index aaca4fe424..d15b0a7646 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -271,13 +271,16 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te bufferFence.reset(texture->getReadyFence()->dup()); } - auto [status, drawFence] = renderEngine - .drawLayers(displaySettings, layerSettings, texture->get(), - false, std::move(bufferFence)) - .get(); + constexpr bool kUseFramebufferCache = false; - if (status == NO_ERROR) { - mDrawFence = new Fence(drawFence.release()); + auto fenceResult = + toFenceResult(renderEngine + .drawLayers(displaySettings, layerSettings, texture->get(), + kUseFramebufferCache, std::move(bufferFence)) + .get()); + + if (fenceStatus(fenceResult) == NO_ERROR) { + mDrawFence = std::move(fenceResult).value_or(Fence::NO_FENCE); mOutputSpace = outputState.framebufferSpace; mTexture = texture; mTexture->setReadyFence(mDrawFence); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 3a3c91e518..784abeac29 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -3171,9 +3171,9 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { mOutput.mState.isEnabled = true; // Create three unique fence instances - sp layer1Fence = new Fence(); - sp layer2Fence = new Fence(); - sp layer3Fence = new Fence(); + sp layer1Fence = sp::make(); + sp layer2Fence = sp::make(); + sp layer3Fence = sp::make(); Output::FrameFences frameFences; frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); @@ -3188,23 +3188,17 @@ TEST_F(OutputPostFramebufferTest, releaseFencesAreSentToLayerFE) { // are passed. This happens to work with the current implementation, but // would not survive certain calls like Fence::merge() which would return a // new instance. - base::unique_fd layer1FD(layer1Fence->dup()); - base::unique_fd layer2FD(layer2Fence->dup()); - base::unique_fd layer3FD(layer3Fence->dup()); EXPECT_CALL(*mLayer1.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer1FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer1FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer1Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer1Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer2.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer2FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer2FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer2Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer2Fence), futureFenceResult.get()); }); EXPECT_CALL(*mLayer3.layerFE, onLayerDisplayed(_)) - .WillOnce([&layer3FD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layer3FD, futureRenderEngineResult.get().drawFence); + .WillOnce([&layer3Fence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(layer3Fence), futureFenceResult.get()); }); mOutput.postFramebuffer(); @@ -3214,15 +3208,11 @@ TEST_F(OutputPostFramebufferTest, releaseFencesIncludeClientTargetAcquireFence) mOutput.mState.isEnabled = true; mOutput.mState.usesClientComposition = true; - sp clientTargetAcquireFence = new Fence(); - sp layer1Fence = new Fence(); - sp layer2Fence = new Fence(); - sp layer3Fence = new Fence(); Output::FrameFences frameFences; - frameFences.clientTargetAcquireFence = clientTargetAcquireFence; - frameFences.layerFences.emplace(&mLayer1.hwc2Layer, layer1Fence); - frameFences.layerFences.emplace(&mLayer2.hwc2Layer, layer2Fence); - frameFences.layerFences.emplace(&mLayer3.hwc2Layer, layer3Fence); + frameFences.clientTargetAcquireFence = sp::make(); + frameFences.layerFences.emplace(&mLayer1.hwc2Layer, sp::make()); + frameFences.layerFences.emplace(&mLayer2.hwc2Layer, sp::make()); + frameFences.layerFences.emplace(&mLayer3.hwc2Layer, sp::make()); EXPECT_CALL(*mRenderSurface, flip()); EXPECT_CALL(mOutput, presentAndGetFrameFences()).WillOnce(Return(frameFences)); @@ -3256,7 +3246,7 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { mOutput.setReleasedLayers(std::move(layers)); // Set up a fake present fence - sp presentFence = new Fence(); + sp presentFence = sp::make(); Output::FrameFences frameFences; frameFences.presentFence = presentFence; @@ -3265,21 +3255,17 @@ TEST_F(OutputPostFramebufferTest, releasedLayersSentPresentFence) { EXPECT_CALL(*mRenderSurface, onPresentDisplayCompleted()); // Each released layer should be given the presentFence. - base::unique_fd layerFD(presentFence.get()->dup()); EXPECT_CALL(*releasedLayer1, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer2, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); EXPECT_CALL(*releasedLayer3, onLayerDisplayed(_)) - .WillOnce([&layerFD](std::shared_future - futureRenderEngineResult) { - EXPECT_EQ(layerFD, futureRenderEngineResult.get().drawFence); + .WillOnce([&presentFence](std::shared_future futureFenceResult) { + EXPECT_EQ(FenceResult(presentFence), futureFenceResult.get()); }); mOutput.postFramebuffer(); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e1eec8b97e..2298f038e9 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -213,8 +213,7 @@ LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp client, * Layer. So, the implementation is done in BufferLayer. When called on a * EffectLayer object, it's essentially a NOP. */ -void Layer::onLayerDisplayed( - std::shared_future /*futureRenderEngineResult*/) {} +void Layer::onLayerDisplayed(std::shared_future) {} void Layer::removeRelativeZ(const std::vector& layersInTree) { if (mDrawingState.zOrderRelativeOf == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ecea74413c..100704369e 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -620,8 +620,7 @@ public: void prepareCompositionState(compositionengine::LayerFE::StateSubset subset) override; std::vector prepareClientCompositionList( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - void onLayerDisplayed( - std::shared_future futureRenderEngineResult) override; + void onLayerDisplayed(std::shared_future) override; void setWasClientComposed(const sp& fence) override { mLastClientCompositionFence = fence; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index e29e6ab05f..2487dbd793 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -355,12 +355,15 @@ void RegionSamplingThread::captureSample() { WRITEABLE); } - auto captureScreenResultFuture = - mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, - true /* regionSampling */, false /* grayscale */, nullptr); - auto& captureScreenResult = captureScreenResultFuture.get(); - if (captureScreenResult.drawFence.ok()) { - sync_wait(captureScreenResult.drawFence.get(), -1); + constexpr bool kRegionSampling = true; + constexpr bool kGrayscale = false; + + if (const auto fenceResult = + mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, + kRegionSampling, kGrayscale, nullptr) + .get(); + fenceResult.ok()) { + fenceResult.value()->waitForever(LOG_TAG); } std::vector activeDescriptors; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e72e21ceb3..d8a2696ef0 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6410,10 +6410,10 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, traverseLayersInLayerStack(layerStack, args.uid, visitor); }; - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); + return fenceStatus(future.get()); } status_t SurfaceFlinger::captureDisplay(DisplayId displayId, @@ -6452,11 +6452,14 @@ status_t SurfaceFlinger::captureDisplay(DisplayId displayId, ALOGE("capture screen must provide a capture listener callback"); return BAD_VALUE; } - auto captureResultFuture = - captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, - ui::PixelFormat::RGBA_8888, false /* allowProtected */, - false /* grayscale */, captureListener); - return captureResultFuture.get().status; + + constexpr bool kAllowProtected = false; + constexpr bool kGrayscale = false; + + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size, + ui::PixelFormat::RGBA_8888, kAllowProtected, kGrayscale, + captureListener); + return fenceStatus(future.get()); } status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, @@ -6568,13 +6571,13 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return BAD_VALUE; } - auto captureResultFuture = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, - reqSize, args.pixelFormat, args.allowProtected, - args.grayscale, captureListener); - return captureResultFuture.get().status; + auto future = captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize, + args.pixelFormat, args.allowProtected, args.grayscale, + captureListener); + return fenceStatus(future.get()); } -std::shared_future SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp& captureListener) { @@ -6584,7 +6587,7 @@ std::shared_future SurfaceFlinger::captureScre ALOGE("Attempted to capture screen with size (%" PRId32 ", %" PRId32 ") that exceeds render target size limit.", bufferSize.getWidth(), bufferSize.getHeight()); - return ftl::yield({BAD_VALUE, base::unique_fd()}).share(); + return ftl::yield(base::unexpected(BAD_VALUE)).share(); } // Loop over all visible layers to see whether there's any protected layer. A protected layer is @@ -6626,7 +6629,7 @@ std::shared_future SurfaceFlinger::captureScre false /* regionSampling */, grayscale, captureListener); } -std::shared_future SurfaceFlinger::captureScreenCommon( +std::shared_future SurfaceFlinger::captureScreenCommon( RenderAreaFuture renderAreaFuture, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool regionSampling, bool grayscale, const sp& captureListener) { @@ -6634,59 +6637,53 @@ std::shared_future SurfaceFlinger::captureScre bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); - auto scheduleResultFuture = mScheduler->schedule([=, - renderAreaFuture = - std::move(renderAreaFuture)]() mutable - -> std::shared_future< - renderengine::RenderEngineResult> { + auto future = mScheduler->schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable + -> std::shared_future { ScreenCaptureResults captureResults; std::unique_ptr renderArea = renderAreaFuture.get(); if (!renderArea) { ALOGW("Skipping screen capture because of invalid render area."); captureResults.result = NO_MEMORY; captureListener->onScreenCaptureCompleted(captureResults); - return ftl::yield({NO_ERROR, base::unique_fd()}) - .share(); + return ftl::yield(base::unexpected(NO_ERROR)).share(); } - std::shared_future renderEngineResultFuture; - + std::shared_future renderFuture; renderArea->render([&] { - renderEngineResultFuture = - renderScreenImpl(*renderArea, traverseLayers, buffer, - canCaptureBlackoutContent, regionSampling, grayscale, - captureResults); + renderFuture = + renderScreenImpl(*renderArea, traverseLayers, buffer, canCaptureBlackoutContent, + regionSampling, grayscale, captureResults); }); - // spring up a thread to unblock SF main thread and wait for - // RenderEngineResult to be available - if (captureListener != nullptr) { + + if (captureListener) { + // TODO: The future returned by std::async blocks the main thread. Return a chain of + // futures to the Binder thread instead. std::async([=]() mutable { ATRACE_NAME("captureListener is nonnull!"); - auto& [status, drawFence] = renderEngineResultFuture.get(); - captureResults.result = status; - captureResults.fence = new Fence(dup(drawFence)); + auto fenceResult = renderFuture.get(); + // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult. + captureResults.result = fenceStatus(fenceResult); + captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE); captureListener->onScreenCaptureCompleted(captureResults); }); } - return renderEngineResultFuture; + return renderFuture; }); - // flatten scheduleResultFuture object to single shared_future object - if (captureListener == nullptr) { - std::future captureScreenResultFuture = - ftl::chain(std::move(scheduleResultFuture)) - .then([=](std::shared_future futureObject) - -> renderengine::RenderEngineResult { - auto& [status, drawFence] = futureObject.get(); - return {status, base::unique_fd(dup(drawFence))}; - }); - return captureScreenResultFuture.share(); - } else { - return ftl::yield({NO_ERROR, base::unique_fd()}).share(); + if (captureListener) { + return ftl::yield(base::unexpected(NO_ERROR)).share(); } + + // Flatten nested futures. + std::future chain = + ftl::chain(std::move(future)).then([](std::shared_future future) { + return future.get(); + }); + + return chain.share(); } -std::shared_future SurfaceFlinger::renderScreenImpl( +std::shared_future SurfaceFlinger::renderScreenImpl( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, const std::shared_ptr& buffer, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, @@ -6705,8 +6702,7 @@ std::shared_future SurfaceFlinger::renderScree // the impetus on WindowManager to not persist them. if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); - return ftl::yield({PERMISSION_DENIED, base::unique_fd()}) - .share(); + return ftl::yield(base::unexpected(PERMISSION_DENIED)).share(); } captureResults.buffer = buffer->getBuffer(); @@ -6827,23 +6823,22 @@ std::shared_future SurfaceFlinger::renderScree base::unique_fd bufferFence; getRenderEngine().useProtectedContext(useProtected); - const constexpr bool kUseFramebufferCache = false; - std::future drawLayersResult = - getRenderEngine().drawLayers(clientCompositionDisplay, clientRenderEngineLayers, buffer, - kUseFramebufferCache, std::move(bufferFence)); - - std::shared_future drawLayersResultFuture = - drawLayersResult.share(); // drawLayersResult will be moved to shared one + constexpr bool kUseFramebufferCache = false; + std::future chain = + ftl::chain(getRenderEngine().drawLayers(clientCompositionDisplay, + clientRenderEngineLayers, buffer, + kUseFramebufferCache, std::move(bufferFence))) + .then(&toFenceResult); + const auto future = chain.share(); for (auto* layer : renderedLayers) { - // make a copy of shared_future object for each layer - layer->onLayerDisplayed(drawLayersResultFuture); + layer->onLayerDisplayed(future); } // Always switch back to unprotected context. getRenderEngine().useProtectedContext(false); - return drawLayersResultFuture; + return future; } void SurfaceFlinger::windowInfosReported() { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c70e1749ff..dc54ac245b 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -867,14 +868,15 @@ private: // Boot animation, on/off animations and screen capture void startBootAnim(); - std::shared_future captureScreenCommon( - RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize, ui::PixelFormat, - bool allowProtected, bool grayscale, const sp&); - std::shared_future captureScreenCommon( + std::shared_future captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, + ui::Size bufferSize, ui::PixelFormat, + bool allowProtected, bool grayscale, + const sp&); + std::shared_future captureScreenCommon( RenderAreaFuture, TraverseLayersFunction, const std::shared_ptr&, bool regionSampling, bool grayscale, const sp&); - std::shared_future renderScreenImpl( + std::shared_future renderScreenImpl( const RenderArea&, TraverseLayersFunction, const std::shared_ptr&, bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, ScreenCaptureResults&) EXCLUDES(mStateLock); diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp index e1f348fdba..fa8cffc32a 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.cpp +++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp @@ -133,10 +133,10 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& if (surfaceControl) { sp prevFence = nullptr; - for (const auto& futureStruct : handle->previousReleaseFences) { - sp currentFence = sp::make(dup(futureStruct.get().drawFence)); + for (const auto& future : handle->previousReleaseFences) { + sp currentFence = future.get().value_or(Fence::NO_FENCE); if (prevFence == nullptr && currentFence->getStatus() != Fence::Status::Invalid) { - prevFence = currentFence; + prevFence = std::move(currentFence); handle->previousReleaseFence = prevFence; } else if (prevFence != nullptr) { // If both fences are signaled or both are unsignaled, we need to merge @@ -147,7 +147,7 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& snprintf(fenceName, 32, "%.28s", handle->name.c_str()); sp mergedFence = Fence::merge(fenceName, prevFence, currentFence); if (mergedFence->isValid()) { - handle->previousReleaseFence = mergedFence; + handle->previousReleaseFence = std::move(mergedFence); prevFence = handle->previousReleaseFence; } } else if (currentFence->getStatus() == Fence::Status::Unsignaled) { @@ -158,11 +158,12 @@ status_t TransactionCallbackInvoker::addCallbackHandle(const sp& // by this point, they will have both signaled and only the timestamp // will be slightly off; any dependencies after this point will // already have been met. - handle->previousReleaseFence = currentFence; + handle->previousReleaseFence = std::move(currentFence); } } } - handle->previousReleaseFences = {}; + handle->previousReleaseFences.clear(); + FrameEventHistoryStats eventStats(handle->frameNumber, handle->gpuCompositionDoneFence->getSnapshot().fence, handle->compositorTiming, handle->refreshStartTime, diff --git a/services/surfaceflinger/TransactionCallbackInvoker.h b/services/surfaceflinger/TransactionCallbackInvoker.h index a68cd87313..b96444dcfb 100644 --- a/services/surfaceflinger/TransactionCallbackInvoker.h +++ b/services/surfaceflinger/TransactionCallbackInvoker.h @@ -28,8 +28,8 @@ #include #include +#include #include -#include #include namespace android { @@ -46,7 +46,7 @@ public: bool releasePreviousBuffer = false; std::string name; sp previousReleaseFence; - std::vector> previousReleaseFences; + std::vector> previousReleaseFences; std::variant> acquireTimeOrFence = -1; nsecs_t latchTime = -1; uint32_t transformHint = 0; diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp index 46d52dd221..bd8081f863 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp +++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -117,11 +118,11 @@ void LayerFuzzer::invokeBufferStateLayer() { const CompositorTiming compositor = {mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral(), mFdp.ConsumeIntegral()}; - std::packaged_task renderResult([&] { - return renderengine::RenderEngineResult{mFdp.ConsumeIntegral(), - base::unique_fd(fence->get())}; - }); - layer->onLayerDisplayed(renderResult.get_future()); + + layer->onLayerDisplayed(ftl::yield(fence).share()); + layer->onLayerDisplayed( + ftl::yield(base::unexpected(mFdp.ConsumeIntegral())).share()); + layer->releasePendingBuffer(mFdp.ConsumeIntegral()); layer->finalizeFrameEventHistory(fenceTime, compositor); layer->onPostComposition(nullptr, fenceTime, fenceTime, compositor); diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index c541b9291f..bbfedc7685 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -245,15 +245,14 @@ void CompositionTest::captureScreenComposition() { HAL_PIXEL_FORMAT_RGBA_8888, 1, usage); - auto result = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer, + auto future = mFlinger.renderScreenImpl(*renderArea, traverseLayers, mCaptureScreenBuffer, forSystem, regionSampling); - EXPECT_TRUE(result.valid()); + ASSERT_TRUE(future.valid()); + const auto fenceResult = future.get(); - auto& [status, drawFence] = result.get(); - - EXPECT_EQ(NO_ERROR, status); - if (drawFence.ok()) { - sync_wait(drawFence.get(), -1); + EXPECT_EQ(NO_ERROR, fenceStatus(fenceResult)); + if (fenceResult.ok()) { + fenceResult.value()->waitForever(LOG_TAG); } LayerCase::cleanup(this); -- cgit v1.2.3-59-g8ed1b