Adding setColor, setColorAlpha, and setColorDataspace to
BufferStateLayer
Bug: 122326454
Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTests
Change-Id: If426541757a58d0fc63d744270bbae1b022f105a
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2132f59..83b9585 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -20,6 +20,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "BufferStateLayer.h"
+#include "ColorLayer.h"
#include "TimeStats/TimeStats.h"
@@ -302,6 +303,48 @@
return true;
}
+bool BufferStateLayer::setColor(const half3& color) {
+ // create color layer if one does not yet exist
+ if (!mCurrentState.bgColorLayer) {
+ uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
+ const String8& name = mName + "BackgroundColorLayer";
+ mCurrentState.bgColorLayer =
+ new ColorLayer(LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags));
+
+ // add to child list
+ addChild(mCurrentState.bgColorLayer);
+ mFlinger->mLayersAdded = true;
+ // set up SF to handle added color layer
+ if (isRemovedFromCurrentState()) {
+ mCurrentState.bgColorLayer->onRemovedFromCurrentState();
+ }
+ mFlinger->setTransactionFlags(eTransactionNeeded);
+ }
+
+ mCurrentState.bgColorLayer->setColor(color);
+ mCurrentState.bgColorLayer->setLayer(std::numeric_limits<int32_t>::min());
+
+ return true;
+}
+
+bool BufferStateLayer::setColorAlpha(float alpha) {
+ if (!mCurrentState.bgColorLayer) {
+ ALOGE("Attempting to set color alpha on a buffer state layer with no background color");
+ return false;
+ }
+ mCurrentState.bgColorLayer->setAlpha(alpha);
+ return true;
+}
+
+bool BufferStateLayer::setColorDataspace(ui::Dataspace dataspace) {
+ if (!mCurrentState.bgColorLayer) {
+ ALOGE("Attempting to set color dataspace on a buffer state layer with no background color");
+ return false;
+ }
+ mCurrentState.bgColorLayer->setDataspace(dataspace);
+ return true;
+}
+
Rect BufferStateLayer::getBufferSize(const State& s) const {
// for buffer state layers we use the display frame size as the buffer size.
if (getActiveWidth(s) < UINT32_MAX && getActiveHeight(s) < UINT32_MAX) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3f891d3..64d6a85 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -82,6 +82,9 @@
}
bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; }
bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; }
+ bool setColor(const half3& color) override;
+ bool setColorAlpha(float alpha) override;
+ bool setColorDataspace(ui::Dataspace dataspace) override;
void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
uint64_t /*frameNumber*/) override {}
void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index d30961a..b3979e2 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -201,6 +201,10 @@
mat4 colorTransform;
bool hasColorTransform;
+ // pointer to background color layer that, if set, appears below the buffer state layer
+ // and the buffer state layer's children. Z order will be set to
+ // INT_MIN
+ sp<Layer> bgColorLayer;
ui::Dataspace colorDataspace; // The dataspace of the background color layer
// The deque of callback handles for this frame. The back of the deque contains the most
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 72c75bb..56d3bd4 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1330,6 +1330,92 @@
getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
}
+TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_Color_NoEffect) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 0, 0, ISurfaceComposerClient::eFXSurfaceColor));
+
+ half3 color;
+ color.r = 1.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ Transaction()
+ .setCrop_legacy(layer, Rect(0, 0, 32, 32))
+ .setAlpha(layer, 1.0f)
+ .setColor(layer, color)
+ .setColorAlpha(layer, 0.5f)
+ .apply();
+
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferQueue_NoEffect) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setAlpha(layer, 1.0f).setColorAlpha(layer, 0.5f).apply();
+
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferState_ColorLayer) {
+ sp<SurfaceControl> bgLayer;
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(bgLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bgLayer, Color::RED, 32, 32));
+
+ // create color layer
+ half3 color;
+ color.r = 0.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ Transaction().setFrame(layer, Rect(0, 0, 32, 32)).setColor(layer, color).apply();
+
+ {
+ SCOPED_TRACE("before alpha");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ // apply alpha
+ Transaction().setAlpha(layer, 0.0f).apply();
+ {
+ SCOPED_TRACE("set alpha");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorAlpha_BufferState_NoColorLayer) {
+ sp<SurfaceControl> bgLayer;
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(bgLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bgLayer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("before alpha");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ // setting alpha without creating color layer should have no effect
+ Transaction().setFrame(layer, Rect(0, 0, 32, 32)).setAlpha(layer, 0.5f).apply();
+ {
+ SCOPED_TRACE("alpha");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) {
sp<SurfaceControl> layer1;
sp<SurfaceControl> layer2;
@@ -1481,6 +1567,77 @@
}
}
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferState_NoPriorColor) {
+ sp<SurfaceControl> bufferQueueLayer;
+ sp<SurfaceControl> bufferStateLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferQueueLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ bufferStateLayer =
+ createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferQueueLayer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("default color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ half3 color;
+ color.r = 0.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ Transaction()
+ .setFrame(bufferStateLayer, Rect(0, 0, 32, 32))
+ .setLayer(bufferStateLayer, mLayerZBase + 1)
+ .setColor(bufferStateLayer, color)
+ .apply();
+
+ {
+ SCOPED_TRACE("set color");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferState_PriorColor) {
+ sp<SurfaceControl> bufferQueueLayer;
+ sp<SurfaceControl> bufferStateLayer;
+ ASSERT_NO_FATAL_FAILURE(bufferQueueLayer = createLayer("test bg", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(
+ bufferStateLayer =
+ createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferQueueLayer, Color::RED, 32, 32));
+
+ half3 color;
+ color.r = 0.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ Transaction()
+ .setFrame(bufferStateLayer, Rect(0, 0, 32, 32))
+ .setLayer(bufferStateLayer, mLayerZBase + 1)
+ .setColor(bufferStateLayer, color)
+ .apply();
+ {
+ SCOPED_TRACE("default color");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 1.0f;
+ Transaction().setColor(bufferStateLayer, color).apply();
+ {
+ SCOPED_TRACE("new color");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) {
sp<SurfaceControl> colorLayer;
ASSERT_NO_FATAL_FAILURE(colorLayer =
@@ -2334,6 +2491,71 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
+TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_ColorLayer_NoEffect) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 0, 0, ISurfaceComposerClient::eFXSurfaceColor));
+ half3 color;
+ color.r = 1.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ Transaction()
+ .setCrop_legacy(layer, Rect(0, 0, 32, 32))
+ .setColor(layer, color)
+ .setDataspace(layer, ui::Dataspace::UNKNOWN)
+ .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
+ .apply();
+
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferQueue_NoEffect) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction()
+ .setDataspace(layer, ui::Dataspace::UNKNOWN)
+ .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
+ .apply();
+
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferState_ColorLayer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ half3 color;
+ color.r = 1.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setColor(layer, color)
+ .setColorDataspace(layer, ui::Dataspace::BT2020_ITU)
+ .apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_P(LayerRenderTypeTransactionTest, SetColorDataspace_BufferState_NoColorLayer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction()
+ .setFrame(layer, Rect(0, 0, 32, 32))
+ .setDataspace(layer, ui::Dataspace::UNKNOWN)
+ .setColorDataspace(layer, ui::Dataspace::DCI_P3)
+ .apply();
+
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(