Merge "Make sure ANATIVEWINDOW_QUERY_BUFFER_AGE is identified as VNDK API." into sc-dev
diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp
index 8ae69de..8356005 100644
--- a/libs/renderengine/skia/AutoBackendTexture.cpp
+++ b/libs/renderengine/skia/AutoBackendTexture.cpp
@@ -87,8 +87,15 @@
mUpdateProc(mImageCtx, context);
}
+ auto colorType = mColorType;
+ if (alphaType == kOpaque_SkAlphaType) {
+ if (colorType == kRGBA_8888_SkColorType) {
+ colorType = kRGB_888x_SkColorType;
+ }
+ }
+
sk_sp<SkImage> image =
- SkImage::MakeFromTexture(context, mBackendTexture, kTopLeft_GrSurfaceOrigin, mColorType,
+ SkImage::MakeFromTexture(context, mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType,
alphaType, toSkColorSpace(dataspace), releaseImageProc, this);
if (image.get()) {
// The following ref will be counteracted by releaseProc, when SkImage is discarded.
diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h
index 3133de6..a9e8430 100644
--- a/libs/renderengine/skia/AutoBackendTexture.h
+++ b/libs/renderengine/skia/AutoBackendTexture.h
@@ -65,6 +65,8 @@
return mTexture->getOrCreateSurface(dataspace, context);
}
+ SkColorType colorType() const { return mTexture->mColorType; }
+
DISALLOW_COPY_AND_ASSIGN(LocalRef);
private:
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 47c330f..2d80c46 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -971,11 +971,28 @@
false);
}
- sk_sp<SkImage> image =
- imageTextureRef->makeImage(layerDataspace,
- item.usePremultipliedAlpha ? kPremul_SkAlphaType
- : kUnpremul_SkAlphaType,
- grContext);
+ // isOpaque means we need to ignore the alpha in the image,
+ // replacing it with the alpha specified by the LayerSettings. See
+ // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
+ // The proper way to do this is to use an SkColorType that ignores
+ // alpha, like kRGB_888x_SkColorType, and that is used if the
+ // incoming image is kRGBA_8888_SkColorType. However, the incoming
+ // image may be kRGBA_F16_SkColorType, for which there is no RGBX
+ // SkColorType, or kRGBA_1010102_SkColorType, for which we have
+ // kRGB_101010x_SkColorType, but it is not yet supported as a source
+ // on the GPU. (Adding both is tracked in skbug.com/12048.) In the
+ // meantime, we'll use a workaround that works unless we need to do
+ // any color conversion. The workaround requires that we pretend the
+ // image is already premultiplied, so that we do not premultiply it
+ // before applying SkBlendMode::kPlus.
+ const bool useIsOpaqueWorkaround = item.isOpaque &&
+ (imageTextureRef->colorType() == kRGBA_1010102_SkColorType ||
+ imageTextureRef->colorType() == kRGBA_F16_SkColorType);
+ const auto alphaType = useIsOpaqueWorkaround ? kPremul_SkAlphaType
+ : item.isOpaque ? kOpaque_SkAlphaType
+ : item.usePremultipliedAlpha ? kPremul_SkAlphaType
+ : kUnpremul_SkAlphaType;
+ sk_sp<SkImage> image = imageTextureRef->makeImage(layerDataspace, alphaType, grContext);
auto texMatrix = getSkM44(item.textureTransform).asM33();
// textureTansform was intended to be passed directly into a shader, so when
@@ -1004,27 +1021,7 @@
shader = image->makeShader(SkSamplingOptions(), matrix);
}
- // Handle opaque images - it's a little nonstandard how we do this.
- // Fundamentally we need to support SurfaceControl.Builder#setOpaque:
- // https://developer.android.com/reference/android/view/SurfaceControl.Builder#setOpaque(boolean)
- // The important language is that when isOpaque is set, opacity is not sampled from the
- // alpha channel, but blending may still be supported on a transaction via setAlpha. So,
- // here's the conundrum:
- // 1. We can't force the SkImage alpha type to kOpaque_SkAlphaType, because it's treated
- // as an internal hint - composition is undefined when there are alpha bits present.
- // 2. We can try to lie about the pixel layout, but that only works for RGBA8888
- // buffers, i.e., treating them as RGBx8888 instead. But we can't do the same for
- // RGBA1010102 because RGBx1010102 is not supported as a pixel layout for SkImages. It's
- // also not clear what to use for F16 either, and lying about the pixel layout is a bit
- // of a hack anyways.
- // 3. We can't change the blendmode to src, because while this satisfies the requirement
- // for ignoring the alpha channel, it doesn't quite satisfy the blending requirement
- // because src always clobbers the destination content.
- //
- // So, what we do here instead is an additive blend mode where we compose the input
- // image with a solid black. This might need to be reassess if this does not support
- // FP16 incredibly well, but FP16 end-to-end isn't well supported anyway at the moment.
- if (item.isOpaque) {
+ if (useIsOpaqueWorkaround) {
shader = SkShaders::Blend(SkBlendMode::kPlus, shader,
SkShaders::Color(SkColors::kBlack,
toSkColorSpace(layerDataspace)));
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 1ca7a16..dfab6e8 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -54,6 +54,7 @@
virtual std::unique_ptr<renderengine::gl::GLESRenderEngine> createGLESRenderEngine() {
return nullptr;
}
+ virtual bool useColorManagement() const = 0;
};
class GLESRenderEngineFactory : public RenderEngineFactory {
@@ -82,6 +83,8 @@
.build();
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
}
+
+ bool useColorManagement() const override { return false; }
};
class GLESCMRenderEngineFactory : public RenderEngineFactory {
@@ -110,6 +113,8 @@
.build();
return renderengine::gl::GLESRenderEngine::create(reCreationArgs);
}
+
+ bool useColorManagement() const override { return true; }
};
class SkiaGLESRenderEngineFactory : public RenderEngineFactory {
@@ -130,9 +135,16 @@
.setSupportsBackgroundBlur(true)
.setContextPriority(renderengine::RenderEngine::ContextPriority::MEDIUM)
.setRenderEngineType(type())
+ // FIXME (b/189935602): This version is currently color managed.
+ // We should change it and fix the tests that fail.
+ //.setUseColorManagerment(false)
.build();
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
}
+
+ // FIXME (b/189935602): This version is currently color managed.
+ // We should change it and fix the tests that fail.
+ bool useColorManagement() const override { return true; }
};
class SkiaGLESCMRenderEngineFactory : public RenderEngineFactory {
@@ -157,6 +169,8 @@
.build();
return renderengine::skia::SkiaGLRenderEngine::create(reCreationArgs);
}
+
+ bool useColorManagement() const override { return true; }
};
class RenderEngineTest : public ::testing::TestWithParam<std::shared_ptr<RenderEngineFactory>> {
@@ -295,6 +309,7 @@
const uint8_t expected[4] = {r, g, b, a};
bool equal = colorCompare(src, expected);
EXPECT_TRUE(equal)
+ << GetParam()->name().c_str() << ": "
<< "pixel @ (" << region.left + i << ", " << region.top + j << "): "
<< "expected (" << static_cast<uint32_t>(r) << ", "
<< static_cast<uint32_t>(g) << ", " << static_cast<uint32_t>(b) << ", "
@@ -2015,6 +2030,56 @@
expectBufferColor(rect, 0, 128, 0, 128);
}
+TEST_P(RenderEngineTest, test_isOpaque) {
+ initializeRenderEngine();
+
+ const auto rect = Rect(0, 0, 1, 1);
+ const renderengine::DisplaySettings display{
+ .physicalDisplay = rect,
+ .clip = rect,
+ .outputDataspace = ui::Dataspace::DISPLAY_P3,
+ };
+
+ // Create an unpremul buffer that is green with no alpha. Using isOpaque
+ // should make the green show.
+ const auto buf = allocateSourceBuffer(1, 1);
+ {
+ uint8_t* pixels;
+ buf->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+ pixels[0] = 0;
+ pixels[1] = 255;
+ pixels[2] = 0;
+ pixels[3] = 0;
+ buf->getBuffer()->unlock();
+ }
+
+ const renderengine::LayerSettings greenLayer{
+ .geometry.boundaries = rect.toFloatRect(),
+ .source =
+ renderengine::PixelSource{
+ .buffer =
+ renderengine::Buffer{
+ .buffer = buf,
+ // Although the pixels are not
+ // premultiplied in practice, this
+ // matches the input we see.
+ .usePremultipliedAlpha = true,
+ .isOpaque = true,
+ },
+ },
+ .alpha = 1.0f,
+ };
+
+ std::vector<const renderengine::LayerSettings*> layers{&greenLayer};
+ invokeDraw(display, layers);
+
+ if (GetParam()->useColorManagement()) {
+ expectBufferColor(rect, 117, 251, 76, 255);
+ } else {
+ expectBufferColor(rect, 0, 255, 0, 255);
+ }
+}
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 91d2d58..3f958ba 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -128,8 +128,9 @@
}
// Ensure that layerCount is valid.
- if (layerCount < 1)
+ if (layerCount < 1) {
layerCount = 1;
+ }
// TODO(b/72323293, b/72703005): Remove these invalid bits from callers
usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
@@ -140,7 +141,7 @@
ALOGE("Failed to allocate (%u x %u) layerCount %u format %d "
"usage %" PRIx64 ": %d",
width, height, layerCount, format, usage, error);
- return NO_MEMORY;
+ return error;
}
if (!importBuffer) {
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index 791e7db..e51019a 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -78,6 +78,30 @@
virtual void prepareCompositionState(StateSubset) = 0;
struct ClientCompositionTargetSettings {
+ enum class BlurSetting {
+ Disabled,
+ BackgroundBlurOnly,
+ BlurRegionsOnly,
+ Enabled,
+ };
+
+ friend std::string toString(BlurSetting blurSetting) {
+ switch (blurSetting) {
+ case BlurSetting::Enabled:
+ return "Enabled";
+ case BlurSetting::BlurRegionsOnly:
+ return "BlurRegionsOnly";
+ case BlurSetting::BackgroundBlurOnly:
+ return "BackgroundBlurOnly";
+ case BlurSetting::Disabled:
+ return "Disabled";
+ }
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const BlurSetting& setting) {
+ return os << toString(setting);
+ }
+
// The clip region, or visible region that is being rendered to
const Region& clip;
@@ -110,8 +134,8 @@
// This may be requested by the HWC
const bool clearContent;
- // If set to true, change the layer settings to not use any blurs.
- const bool disableBlurs;
+ // Configure layer settings for using blurs
+ BlurSetting blurSetting;
};
// A superset of LayerSettings required by RenderEngine to compose a layer
@@ -186,6 +210,7 @@
PrintTo(settings.dataspace, os);
*os << "\n .realContentIsVisible = " << settings.realContentIsVisible;
*os << "\n .clearContent = " << settings.clearContent;
+ *os << "\n .blurSetting = " << settings.blurSetting;
*os << "\n}";
}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
index 3f670a1..7564c54 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -103,6 +103,13 @@
// be visible through it. Unowned - the OutputLayer's lifetime will
// outlast this.)
compositionengine::OutputLayer* peekThroughLayer = nullptr;
+ // True when this layer's blur has been cached with a previous layer, so that this layer
+ // does not need to request blurring.
+ // TODO(b/188816867): support blur regions too, which are less likely to be common if a
+ // device supports cross-window blurs. Blur region support should be doable, but we would
+ // need to make sure that layer caching works well with the blur region transform passed
+ // into RenderEngine
+ bool disableBackgroundBlur = false;
} overrideInfo;
/*
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index fdcd6ab..269ddd5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -39,6 +39,7 @@
const LayerState* getState() const { return mState; }
const std::string& getName() const { return mState->getName(); }
+ int32_t getBackgroundBlurRadius() const { return mState->getBackgroundBlurRadius(); }
Rect getDisplayFrame() const { return mState->getDisplayFrame(); }
const Region& getVisibleRegion() const { return mState->getVisibleRegion(); }
const sp<GraphicBuffer>& getBuffer() const {
@@ -91,6 +92,7 @@
mTexture = nullptr;
mOutputDataspace = ui::Dataspace::UNKNOWN;
mDrawFence = nullptr;
+ mBlurLayer = nullptr;
mLayers.insert(mLayers.end(), other.mLayers.cbegin(), other.mLayers.cend());
Region boundingRegion;
@@ -123,9 +125,13 @@
// nothing (besides the hole punch layer) will be drawn behind it.
void addHolePunchLayerIfFeasible(const CachedSet&, bool isFirstLayer);
+ void addBackgroundBlurLayer(const CachedSet&);
+
// Retrieve the layer that will be drawn behind this one.
compositionengine::OutputLayer* getHolePunchLayer() const;
+ compositionengine::OutputLayer* getBlurLayer() const;
+
private:
CachedSet() = default;
@@ -135,6 +141,7 @@
// Unowned.
const LayerState* mHolePunchLayer = nullptr;
+ const LayerState* mBlurLayer = nullptr;
Rect mBounds = Rect::EMPTY_RECT;
Region mVisibleRegion;
size_t mAge = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
index 213c55e..ca1d69d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
@@ -51,6 +51,11 @@
void dump(std::string& result) const;
void dumpLayers(std::string& result) const;
+ const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; }
+
+protected:
+ std::optional<CachedSet> mNewCachedSet;
+
private:
size_t calculateDisplayCost(const std::vector<const LayerState*>& layers) const;
@@ -72,6 +77,7 @@
std::vector<CachedSet>::const_iterator mStart;
std::vector<size_t> mLengths;
const CachedSet* mHolePunchCandidate = nullptr;
+ const CachedSet* mBlurringLayer = nullptr;
public:
// Initializes a Builder a CachedSet to start from.
@@ -90,6 +96,10 @@
mHolePunchCandidate = holePunchCandidate;
}
+ void setBlurringLayer(const CachedSet* blurringLayer) {
+ mBlurringLayer = blurringLayer;
+ }
+
// Builds a Run instance, if a valid Run may be built.
std::optional<Run> validateAndBuild() {
if (mLengths.size() <= 1) {
@@ -99,7 +109,7 @@
return Run(mStart,
std::reduce(mLengths.cbegin(), mLengths.cend(), 0u,
[](size_t left, size_t right) { return left + right; }),
- mHolePunchCandidate);
+ mHolePunchCandidate, mBlurringLayer);
}
void reset() { *this = {}; }
@@ -112,14 +122,19 @@
size_t getLayerLength() const { return mLength; }
// Gets the hole punch candidate for this Run.
const CachedSet* getHolePunchCandidate() const { return mHolePunchCandidate; }
+ const CachedSet* getBlurringLayer() const { return mBlurringLayer; }
private:
Run(std::vector<CachedSet>::const_iterator start, size_t length,
- const CachedSet* holePunchCandidate)
- : mStart(start), mLength(length), mHolePunchCandidate(holePunchCandidate) {}
+ const CachedSet* holePunchCandidate, const CachedSet* blurringLayer)
+ : mStart(start),
+ mLength(length),
+ mHolePunchCandidate(holePunchCandidate),
+ mBlurringLayer(blurringLayer) {}
const std::vector<CachedSet>::const_iterator mStart;
const size_t mLength;
const CachedSet* const mHolePunchCandidate;
+ const CachedSet* const mBlurringLayer;
friend class Builder;
};
@@ -138,7 +153,6 @@
std::chrono::steady_clock::time_point mLastGeometryUpdate;
std::vector<CachedSet> mLayers;
- std::optional<CachedSet> mNewCachedSet;
// Statistics
size_t mUnflattenedDisplayCost = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index fef0dfb..0b78cb8 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -231,6 +231,7 @@
bool hasBlurBehind() const {
return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty();
}
+ int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); }
hardware::graphics::composer::hal::Composition getCompositionType() const {
return mCompositionType.get();
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 953eb76..3d49183 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -344,8 +344,8 @@
if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
return;
}
- auto outputState = editState();
- outputState.dataspace = clientTargetProperty.dataspace;
+
+ editState().dataspace = clientTargetProperty.dataspace;
getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
}
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 088a400..e9a8b91 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -1188,19 +1188,6 @@
!layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty();
if (clientComposition || clearClientComposition) {
- compositionengine::LayerFE::ClientCompositionTargetSettings
- targetSettings{.clip = clip,
- .needsFiltering =
- layer->needsFiltering() || outputState.needsFiltering,
- .isSecure = outputState.isSecure,
- .supportsProtectedContent = supportsProtectedContent,
- .clearRegion = clientComposition ? clearRegion : stubRegion,
- .viewport = outputState.layerStackSpace.content,
- .dataspace = outputDataspace,
- .realContentIsVisible = realContentIsVisible,
- .clearContent = !clientComposition,
- .disableBlurs = disableBlurs};
-
std::vector<LayerFE::LayerSettings> results;
if (layer->getState().overrideInfo.buffer != nullptr) {
if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) {
@@ -1212,6 +1199,25 @@
layer->getLayerFE().getDebugName());
}
} else {
+ LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs
+ ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled
+ : (layer->getState().overrideInfo.disableBackgroundBlur
+ ? LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ BlurRegionsOnly
+ : LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ Enabled);
+ compositionengine::LayerFE::ClientCompositionTargetSettings
+ targetSettings{.clip = clip,
+ .needsFiltering = layer->needsFiltering() ||
+ outputState.needsFiltering,
+ .isSecure = outputState.isSecure,
+ .supportsProtectedContent = supportsProtectedContent,
+ .clearRegion = clientComposition ? clearRegion : stubRegion,
+ .viewport = outputState.layerStackSpace.content,
+ .dataspace = outputDataspace,
+ .realContentIsVisible = realContentIsVisible,
+ .clearContent = !clientComposition,
+ .blurSetting = blurSetting};
results = layerFE.prepareClientCompositionList(targetSettings);
if (realContentIsVisible && !results.empty()) {
layer->editState().clientCompositionTimestamp = systemTime();
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
index b4c314c..cfa740e 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp
@@ -78,6 +78,8 @@
std::string visibleRegionString;
overrideInfo.visibleRegion.dump(visibleRegionString, "");
dumpVal(out, "override visible region", visibleRegionString);
+ dumpVal(out, "override peekThroughLayer", overrideInfo.peekThroughLayer);
+ dumpVal(out, "override disableBackgroundBlur", overrideInfo.disableBackgroundBlur);
if (hwc) {
dumpHwc(*hwc, out);
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index b61daeb..3cfb211 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -25,6 +25,7 @@
#include <math/HashCombine.h>
#include <renderengine/DisplaySettings.h>
#include <renderengine/RenderEngine.h>
+#include <utils/Trace.h>
#include <utils/Trace.h>
@@ -184,7 +185,7 @@
.dataspace = outputDataspace,
.realContentIsVisible = true,
.clearContent = false,
- .disableBlurs = false,
+ .blurSetting = LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
std::vector<renderengine::LayerSettings> layerSettings;
@@ -201,6 +202,24 @@
std::transform(layerSettings.cbegin(), layerSettings.cend(),
std::back_inserter(layerSettingsPointers),
[](const renderengine::LayerSettings& settings) { return &settings; });
+
+ renderengine::LayerSettings blurLayerSettings;
+ if (mBlurLayer) {
+ auto blurSettings = targetSettings;
+ blurSettings.blurSetting =
+ LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly;
+ auto clientCompositionList =
+ mBlurLayer->getOutputLayer()->getLayerFE().prepareClientCompositionList(
+ blurSettings);
+ blurLayerSettings = clientCompositionList.back();
+ // This mimics Layer::prepareClearClientComposition
+ blurLayerSettings.skipContentDraw = true;
+ blurLayerSettings.name = std::string("blur layer");
+ // Clear out the shadow settings
+ blurLayerSettings.shadow = {};
+ layerSettingsPointers.push_back(&blurLayerSettings);
+ }
+
renderengine::LayerSettings holePunchSettings;
if (mHolePunchLayer) {
auto clientCompositionList =
@@ -315,10 +334,18 @@
}
}
+void CachedSet::addBackgroundBlurLayer(const CachedSet& blurLayer) {
+ mBlurLayer = blurLayer.getFirstLayer().getState();
+}
+
compositionengine::OutputLayer* CachedSet::getHolePunchLayer() const {
return mHolePunchLayer ? mHolePunchLayer->getOutputLayer() : nullptr;
}
+compositionengine::OutputLayer* CachedSet::getBlurLayer() const {
+ return mBlurLayer ? mBlurLayer->getOutputLayer() : nullptr;
+}
+
void CachedSet::dump(std::string& result) const {
const auto now = std::chrono::steady_clock::now();
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index 2def99d..ef46335 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -245,6 +245,12 @@
auto currentLayerIter = mLayers.begin();
auto incomingLayerIter = layers.begin();
+
+ // If not null, this represents the layer that is blurring the layer before
+ // currentLayerIter. The blurring was stored in the override buffer, so the
+ // layer that requests the blur no longer needs to do any blurring.
+ compositionengine::OutputLayer* priorBlurLayer = nullptr;
+
while (incomingLayerIter != layers.end()) {
if (mNewCachedSet &&
mNewCachedSet->getFirstLayer().getState()->getId() == (*incomingLayerIter)->getId()) {
@@ -259,6 +265,8 @@
auto* peekThroughLayer = mNewCachedSet->getHolePunchLayer();
const size_t layerCount = currentLayerIter->getLayerCount();
for (size_t i = 0; i < layerCount; ++i) {
+ bool disableBlur = priorBlurLayer &&
+ priorBlurLayer == (*incomingLayerIter)->getOutputLayer();
OutputLayer::CompositionState& state =
(*incomingLayerIter)->getOutputLayer()->editState();
state.overrideInfo = {
@@ -270,6 +278,7 @@
.damageRegion = Region::INVALID_REGION,
.visibleRegion = mNewCachedSet->getVisibleRegion(),
.peekThroughLayer = peekThroughLayer,
+ .disableBackgroundBlur = disableBlur,
};
++incomingLayerIter;
}
@@ -281,6 +290,7 @@
skipCount -= layerCount;
}
+ priorBlurLayer = mNewCachedSet->getBlurLayer();
merged.emplace_back(std::move(*mNewCachedSet));
mNewCachedSet = std::nullopt;
continue;
@@ -295,6 +305,8 @@
const size_t layerCount = currentLayerIter->getLayerCount();
auto* peekThroughLayer = currentLayerIter->getHolePunchLayer();
for (size_t i = 0; i < layerCount; ++i) {
+ bool disableBlur =
+ priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer();
OutputLayer::CompositionState& state =
(*incomingLayerIter)->getOutputLayer()->editState();
state.overrideInfo = {
@@ -306,6 +318,7 @@
.damageRegion = Region(),
.visibleRegion = currentLayerIter->getVisibleRegion(),
.peekThroughLayer = peekThroughLayer,
+ .disableBackgroundBlur = disableBlur,
};
++incomingLayerIter;
}
@@ -313,15 +326,26 @@
// Break the current layer into its constituent layers
++mInvalidatedCachedSetAges[currentLayerIter->getAge()];
for (CachedSet& layer : currentLayerIter->decompose()) {
+ bool disableBlur =
+ priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer();
+ OutputLayer::CompositionState& state =
+ (*incomingLayerIter)->getOutputLayer()->editState();
+ state.overrideInfo.disableBackgroundBlur = disableBlur;
layer.updateAge(now);
merged.emplace_back(layer);
++incomingLayerIter;
}
} else {
+ bool disableBlur =
+ priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer();
+ OutputLayer::CompositionState& state =
+ (*incomingLayerIter)->getOutputLayer()->editState();
+ state.overrideInfo.disableBackgroundBlur = disableBlur;
currentLayerIter->updateAge(now);
merged.emplace_back(*currentLayerIter);
++incomingLayerIter;
}
+ priorBlurLayer = currentLayerIter->getBlurLayer();
++currentLayerIter;
}
@@ -361,6 +385,15 @@
}
} else if (isPartOfRun) {
builder.setHolePunchCandidate(&(*currentSet));
+
+ // If we're here then this blur layer recently had an active buffer updating, meaning
+ // that there is exactly one layer. Blur radius currently is part of layer stack
+ // geometry, so we're also guaranteed that the background blur radius hasn't changed for
+ // at least as long as this new inactive cached set.
+ if (runHasFirstLayer && layerHasBlur &&
+ currentSet->getFirstLayer().getBackgroundBlurRadius() > 0) {
+ builder.setBlurringLayer(&(*currentSet));
+ }
if (auto run = builder.validateAndBuild(); run) {
runs.push_back(*run);
}
@@ -422,6 +455,10 @@
mNewCachedSet->append(*currentSet);
}
+ if (bestRun->getBlurringLayer()) {
+ mNewCachedSet->addBackgroundBlurLayer(*bestRun->getBlurringLayer());
+ }
+
if (mEnableHolePunch && bestRun->getHolePunchCandidate() &&
bestRun->getHolePunchCandidate()->requiresHolePunch()) {
// Add the pip layer to mNewCachedSet, but in a special way - it should
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index e12cb57..ac3ba0d 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -847,6 +847,29 @@
}
/*
+ * Display::applyClientTargetRequests()
+ */
+
+using DisplayApplyClientTargetRequests = DisplayWithLayersTestCommon;
+
+TEST_F(DisplayApplyLayerRequestsToLayersTest, applyClientTargetRequests) {
+ Display::ClientTargetProperty clientTargetProperty = {
+ .pixelFormat = hal::PixelFormat::RGB_565,
+ .dataspace = hal::Dataspace::STANDARD_BT470M,
+ };
+
+ mock::RenderSurface* renderSurface = new StrictMock<mock::RenderSurface>();
+ mDisplay->setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(renderSurface));
+
+ EXPECT_CALL(*renderSurface, setBufferPixelFormat(clientTargetProperty.pixelFormat));
+ EXPECT_CALL(*renderSurface, setBufferDataspace(clientTargetProperty.dataspace));
+ mDisplay->applyClientTargetRequests(clientTargetProperty);
+
+ auto& state = mDisplay->getState();
+ EXPECT_EQ(clientTargetProperty.dataspace, state.dataspace);
+}
+
+/*
* Display::presentAndGetFrameFences()
*/
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 6677f40..52e0428 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3784,6 +3784,46 @@
EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
}
+MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
+ *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
+ *result_listener << "expected " << expectedBlurSetting << "\n";
+ *result_listener << "actual " << arg.blurSetting << "\n";
+
+ return expectedBlurSetting == arg.blurSetting;
+}
+
+TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, overridesBlur) {
+ LayerFE::LayerSettings mShadowSettings;
+ mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f};
+
+ mLayers[2].mOutputLayerState.overrideInfo.disableBackgroundBlur = true;
+
+ EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(_))
+ .WillOnce(Return(std::vector<LayerFE::LayerSettings>()));
+ EXPECT_CALL(*mLayers[1].mLayerFE, prepareClientCompositionList(_))
+ .WillOnce(Return(std::vector<LayerFE::LayerSettings>({mLayers[1].mLayerSettings})));
+ EXPECT_CALL(*mLayers[2].mLayerFE,
+ prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+ LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly)))
+ .WillOnce(Return(std::vector<LayerFE::LayerSettings>(
+ {mShadowSettings, mLayers[2].mLayerSettings})));
+
+ Region accumClearRegion(Rect(10, 11, 12, 13));
+ auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */,
+ accumClearRegion, kDisplayDataspace);
+ ASSERT_EQ(3u, requests.size());
+ EXPECT_EQ(mLayers[1].mLayerSettings, requests[0]);
+ EXPECT_EQ(mShadowSettings, requests[1]);
+ EXPECT_EQ(mLayers[2].mLayerSettings, requests[2]);
+
+ EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13))));
+
+ // Check that a timestamp was set for the layers that generated requests
+ EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp);
+ EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp);
+ EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp);
+}
+
TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers,
onlyClientComposesClientComposedLayersIfNoClearingNeeded) {
EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
@@ -3867,7 +3907,7 @@
kDisplayDataspace,
false /* realContentIsVisible */,
true /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(kDisplayFrame),
@@ -3879,7 +3919,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
LayerFE::LayerSettings mBlackoutSettings = mLayers[1].mLayerSettings;
@@ -3923,7 +3963,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
Region(Rect(0, 0, 30, 30)),
@@ -3935,7 +3975,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(Rect(0, 0, 40, 201)),
@@ -3947,7 +3987,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -3979,7 +4019,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
Region(kDisplayFrame),
@@ -3991,7 +4031,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(kDisplayFrame),
@@ -4003,7 +4043,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4035,7 +4075,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
@@ -4048,7 +4088,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(kDisplayFrame),
@@ -4060,7 +4100,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4091,7 +4131,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
Region(kDisplayFrame),
@@ -4103,7 +4143,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(kDisplayFrame),
@@ -4115,7 +4155,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4144,7 +4184,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{
Region(kDisplayFrame),
@@ -4156,7 +4196,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{
Region(kDisplayFrame),
@@ -4168,7 +4208,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings))))
@@ -4306,7 +4346,7 @@
kOutputDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4324,7 +4364,7 @@
kOutputDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true));
@@ -4358,7 +4398,7 @@
kDisplayDataspace,
false /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
LayerFE::LayerSettings mShadowSettings;
@@ -4404,7 +4444,7 @@
kDisplayDataspace,
true /* realContentIsVisible */,
false /* clearContent */,
- false /* disabledBlurs */,
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled,
};
EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false));
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 8f44677..591f981 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -24,6 +24,7 @@
#include <renderengine/ExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/GraphicTypes.h>
+#include <utils/Errors.h>
#include <memory>
namespace android::compositionengine {
@@ -42,6 +43,14 @@
namespace {
+MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
+ *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
+ *result_listener << "expected " << expectedBlurSetting << "\n";
+ *result_listener << "actual " << arg.blurSetting << "\n";
+
+ return expectedBlurSetting == arg.blurSetting;
+}
+
class CachedSetTest : public testing::Test {
public:
CachedSetTest() = default;
@@ -593,5 +602,78 @@
EXPECT_TRUE(cachedSet4.hasBlurBehind());
}
+TEST_F(CachedSetTest, addBackgroundBlurLayer) {
+ CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
+ CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
+ CachedSet cachedSet(layer1);
+
+ EXPECT_EQ(nullptr, cachedSet.getBlurLayer());
+
+ cachedSet.addBackgroundBlurLayer(layer2);
+ EXPECT_EQ(layer2.getState()->getOutputLayer(), cachedSet.getBlurLayer());
+}
+
+TEST_F(CachedSetTest, addBlur) {
+ mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
+ CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
+ sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
+
+ CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
+ sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
+
+ CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
+ sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
+
+ CachedSet cachedSet(layer1);
+ cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
+
+ cachedSet.addBackgroundBlurLayer(layer3);
+
+ std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
+ clientCompList1.push_back({});
+ std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
+ clientCompList2.push_back({});
+ std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3;
+ clientCompList3.push_back({});
+
+ clientCompList3[0].source.buffer.buffer = std::make_shared<
+ renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine,
+ renderengine::ExternalTexture::READABLE);
+
+ EXPECT_CALL(*layerFE1,
+ prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ Enabled)))
+ .WillOnce(Return(clientCompList1));
+ EXPECT_CALL(*layerFE2,
+ prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ Enabled)))
+ .WillOnce(Return(clientCompList2));
+ EXPECT_CALL(*layerFE3,
+ prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq(
+ compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
+ BackgroundBlurOnly)))
+ .WillOnce(Return(clientCompList3));
+
+ const auto drawLayers = [&](const renderengine::DisplaySettings&,
+ const std::vector<const renderengine::LayerSettings*>& layers,
+ const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
+ base::unique_fd&&, base::unique_fd*) -> int32_t {
+ // 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);
+
+ return NO_ERROR;
+ };
+
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
+ cachedSet.render(mRenderEngine, mOutputState);
+}
+
} // namespace
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 7ec2c98..8b03964 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -27,6 +27,7 @@
namespace android::compositionengine {
using namespace std::chrono_literals;
+using impl::planner::CachedSet;
using impl::planner::Flattener;
using impl::planner::LayerState;
using impl::planner::NonBufferHash;
@@ -43,9 +44,15 @@
namespace {
+class TestableFlattener : public Flattener {
+public:
+ TestableFlattener(bool enableHolePunch) : Flattener(enableHolePunch) {}
+ const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; }
+};
+
class FlattenerTest : public testing::Test {
public:
- FlattenerTest() : mFlattener(std::make_unique<Flattener>(true)) {}
+ FlattenerTest() : mFlattener(std::make_unique<TestableFlattener>(true)) {}
void SetUp() override;
protected:
@@ -55,7 +62,7 @@
// mRenderEngine may be held as a pointer to mFlattener, so mFlattener must be destroyed first.
renderengine::mock::RenderEngine mRenderEngine;
- std::unique_ptr<Flattener> mFlattener;
+ std::unique_ptr<TestableFlattener> mFlattener;
const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
std::chrono::steady_clock::time_point mTime = kStartTime;
@@ -786,6 +793,56 @@
EXPECT_EQ(overrideBuffer3, overrideBuffer4);
}
+TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiveBehindLayers) {
+ auto& layerState1 = mTestLayers[0]->layerState;
+ auto& layerState2 = mTestLayers[1]->layerState;
+
+ auto& layerStateWithBlurBehind = mTestLayers[2]->layerState;
+ mTestLayers[2]->layerFECompositionState.backgroundBlurRadius = 1;
+ layerStateWithBlurBehind->update(&mTestLayers[2]->outputLayer);
+ const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+ const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
+ const auto& blurOverrideBuffer =
+ layerStateWithBlurBehind->getOutputLayer()->getState().overrideInfo.buffer;
+
+ const std::vector<const LayerState*> layers = {
+ layerState1.get(),
+ layerState2.get(),
+ layerStateWithBlurBehind.get(),
+ };
+
+ initializeFlattener(layers);
+
+ // Mark the first two layers inactive, but update the blur layer
+ mTime += 200ms;
+ layerStateWithBlurBehind->resetFramesSinceBufferUpdate();
+
+ // layers would be flattened but the buffer would not be overridden
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR));
+
+ initializeOverrideBuffer(layers);
+ EXPECT_EQ(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+
+ const auto& cachedSet = mFlattener->getNewCachedSetForTesting();
+ ASSERT_NE(std::nullopt, cachedSet);
+ EXPECT_EQ(&mTestLayers[2]->outputLayer, cachedSet->getBlurLayer());
+
+ for (const auto layer : layers) {
+ EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
+ }
+
+ // the new flattened layer is replaced
+ initializeOverrideBuffer(layers);
+ EXPECT_NE(getNonBufferHash(layers),
+ mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
+ mFlattener->renderCachedSets(mRenderEngine, mOutputState);
+ EXPECT_NE(nullptr, overrideBuffer1);
+ EXPECT_EQ(overrideBuffer2, overrideBuffer1);
+ EXPECT_EQ(nullptr, blurOverrideBuffer);
+}
+
TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) {
auto& layerState1 = mTestLayers[0]->layerState;
auto& layerState2 = mTestLayers[1]->layerState;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d720bcb..9fcc17c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -587,11 +587,24 @@
layerSettings.alpha = alpha;
layerSettings.sourceDataspace = getDataSpace();
- if (!targetSettings.disableBlurs) {
- layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
- layerSettings.blurRegions = getBlurRegions();
- layerSettings.blurRegionTransform =
- getActiveTransform(getDrawingState()).inverse().asMatrix4();
+ switch (targetSettings.blurSetting) {
+ case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
+ layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
+ layerSettings.blurRegions = getBlurRegions();
+ layerSettings.blurRegionTransform =
+ getActiveTransform(getDrawingState()).inverse().asMatrix4();
+ break;
+ case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
+ layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
+ break;
+ case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
+ layerSettings.blurRegions = getBlurRegions();
+ layerSettings.blurRegionTransform =
+ getActiveTransform(getDrawingState()).inverse().asMatrix4();
+ break;
+ case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
+ default:
+ break;
}
layerSettings.stretchEffect = getStretchEffect();
// Record the name of the layer for debugging further down the stack.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a86e061..d76c274 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1029,10 +1029,6 @@
updatePhaseConfiguration(refreshRate.getFps());
mScheduler->setModeChangePending(true);
}
-
- if (mRefreshRateOverlay) {
- mRefreshRateOverlay->changeRefreshRate(refreshRate.getFps());
- }
}
status_t SurfaceFlinger::setActiveMode(const sp<IBinder>& displayToken, int modeId) {
@@ -1190,6 +1186,10 @@
}
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
+ if (mRefreshRateOverlay) {
+ mRefreshRateOverlay->changeRefreshRate(desiredMode->getFps());
+ }
+
// Scheduler will submit an empty frame to HWC if needed.
mSetActiveModePending = true;
}
@@ -6202,9 +6202,12 @@
clearRegion,
layerStackSpaceRect,
clientCompositionDisplay.outputDataspace,
- true, /* realContentIsVisible */
+ true, /* realContentIsVisible */
false, /* clearContent */
- disableBlurs,
+ disableBlurs ? compositionengine::LayerFE::ClientCompositionTargetSettings::
+ BlurSetting::Disabled
+ : compositionengine::LayerFE::ClientCompositionTargetSettings::
+ BlurSetting::Enabled,
};
std::vector<compositionengine::LayerFE::LayerSettings> results =
layer->prepareClientCompositionList(targetSettings);