Loading libs/gui/aidl/android/gui/ISurfaceComposer.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -503,7 +503,7 @@ interface ISurfaceComposer { * lightRadius * Radius of the light casting the shadow. */ oneway void setGlobalShadowSettings(in Color ambientColor, in Color spotColor, float lightPosY, float lightPosZ, float lightRadius); void setGlobalShadowSettings(in Color ambientColor, in Color spotColor, float lightPosY, float lightPosZ, float lightRadius); /** * Gets whether a display supports DISPLAY_DECORATION layers. Loading libs/renderengine/skia/SkiaRenderEngine.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -238,6 +238,7 @@ static inline SkM44 getSkM44(const android::mat4& matrix) { matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]); } [[maybe_unused]] static inline SkPoint3 getSkPoint3(const android::vec3& vector) { return SkPoint3::Make(vector.x, vector.y, vector.z); } Loading Loading @@ -1370,10 +1371,16 @@ void SkiaRenderEngine::drawShadow(SkCanvas* canvas, const auto flags = settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag; // DrawShadow expects the light pos in device space. // Shadow settings is in layer space (which is our current canvas transform). SkMatrix deviceFromLayer = canvas->getTotalMatrix(); SkPoint lightPos = {settings.lightPos.x, settings.lightPos.y}; // lightPos is in layer space deviceFromLayer.mapPoints(&lightPos, 1); // lightPos is in device space SkShadowUtils::DrawShadow(canvas, SkPath::RRect(casterRRect), SkPoint3::Make(0, 0, casterZ), getSkPoint3(settings.lightPos), settings.lightRadius, getSkColor(settings.ambientColor), getSkColor(settings.spotColor), flags); SkPoint3{lightPos.fX, lightPos.fY, settings.lightPos.z}, settings.lightRadius, getSkColor(settings.ambientColor), getSkColor(settings.spotColor), flags); } void SkiaRenderEngine::onActiveDisplaySizeChanged(ui::Size size) { Loading services/surfaceflinger/LayerFE.cpp +13 −5 Original line number Diff line number Diff line Loading @@ -343,11 +343,19 @@ void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster, return; } // Shift the spot light x-position to the middle of the display and then // offset it by casting layer's screen pos. state.lightPos.x = (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left; state.lightPos.y -= mSnapshot->transformedBounds.top; // The light source should be at (screenWidth/2, globalShadowSettings.lightPos.y) in // screenspace. vec2 lightPosScreenSpace = { (static_cast<float>(layerStackRect.width()) / 2.f), state.lightPos.y, }; // Skia expects light pos in layer space. vec2 lightPosLayerSpace = mSnapshot->geomInverseLayerTransform.transform(lightPosScreenSpace); state.lightPos.x = lightPosLayerSpace.x; state.lightPos.y = lightPosLayerSpace.y; caster.shadow = state; } Loading services/surfaceflinger/SurfaceFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -8304,6 +8304,9 @@ status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, cons // these values are overridden when calculating the shadow settings for a layer. mCurrentState.globalShadowSettings.lightPos.x = 0.f; mCurrentState.globalShadowSettings.length = 0.f; setTransactionFlags(eTransactionNeeded); return NO_ERROR; } Loading services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +76 −6 Original line number Diff line number Diff line Loading @@ -876,18 +876,24 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, CropElevationShadowByParent) { ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::WHITE, parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::BLUE, size, size)); // TODO(b/377194534): This test fails on Tangor because global shadow // settings seem to not respect rotation. SurfaceComposerClient::getDefault()->setGlobalShadowSettings({1, 0, 0, 0.5f}, {0, 1, 0, 0.5f}, 0, 500.0f, 800.0f); 0, 250.0f, 800.0f); // Global shadow settings are committed after snapshot updates so we have to perform a commit // before enabling layer shadows. Transaction().apply(true); std::this_thread::sleep_for(std::chrono::seconds(1)); ui::Size resolution = mRenderPathHarness.getRotatedResolution(); int x = resolution.width / 2; int y = 500; Transaction() .setPosition(parent, x, y) .setCrop(parent, Rect(0, 0, parentSize / 2, parentSize)) .reparent(child, parent) .setPosition(child, size, size) .setCrop(child, Rect(0, 0, size, size)) .setPosition(child, size, size) .setCornerRadius(child, 20.0f) Loading @@ -896,7 +902,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, CropElevationShadowByParent) { auto shot = getScreenCapture(); shot->expectBufferMatchesImageFromFile(Rect(0, 0, parentSize, parentSize), shot->expectBufferMatchesImageFromFile(Rect(x, y, x + parentSize, y + parentSize), "testdata/CropElevationShadowByParent.png"); } Loading Loading @@ -1146,6 +1152,70 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) { shot->expectColor(crop, Color::RED); } } class RotatedVirtualDisplayTest : public LayerTypeTransactionHarness, public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath, ui::Rotation>> { public: RotatedVirtualDisplayTest() : LayerTypeTransactionHarness(std::get<0>(GetParam())), mRenderPathHarness(this, std::get<1>(GetParam()), std::get<2>(GetParam())) {} std::unique_ptr<ScreenCapture> getScreenCapture() { return mRenderPathHarness.getScreenCapture(); } protected: LayerRenderPathTestHarness mRenderPathHarness; }; INSTANTIATE_TEST_CASE_P(RotatedVirtualDisplayTests, RotatedVirtualDisplayTest, ::testing::Combine(::testing::Values(static_cast<uint32_t>( ISurfaceComposerClient::eFXSurfaceBufferState)), ::testing::Values(RenderPath::VIRTUAL_DISPLAY), ::testing::Values(ui::Rotation::Rotation0, ui::Rotation::Rotation90, ui::Rotation::Rotation180, ui::Rotation::Rotation270))); TEST_P(RotatedVirtualDisplayTest, ElevationShadowHasCorrectOrientation) { sp<SurfaceControl> parent; sp<SurfaceControl> child; const uint32_t size = 64; const uint32_t parentSize = size * 3; ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::WHITE, parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); SurfaceComposerClient::getDefault()->setGlobalShadowSettings({1, 0, 0, 1.0f}, {0, 1, 0, 1.0f}, 0, 500.0f, 800.0f); // Global shadow settings are committed after snapshot updates so we have to perform a commit // before enabling layer shadows. Transaction().apply(true); ui::Size resolution = mRenderPathHarness.getRotatedResolution(); int x = resolution.width / 2; int y = 500; Transaction() .setPosition(parent, x, y) .setCrop(parent, Rect(0, 0, parentSize, parentSize)) .reparent(child, parent) .setCrop(child, Rect(0, 0, size, size)) .setPosition(child, size, size) .setCornerRadius(child, 20.0f) .setShadowRadius(child, 20.0f) .apply(true); auto shot = getScreenCapture(); shot->expectBufferMatchesImageFromFile(mRenderPathHarness.rotateRect( Rect(x, y, x + parentSize, y + parentSize)), "testdata/Shadow_" + mRenderPathHarness.getRotationName() + ".png"); } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading Loading
libs/gui/aidl/android/gui/ISurfaceComposer.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -503,7 +503,7 @@ interface ISurfaceComposer { * lightRadius * Radius of the light casting the shadow. */ oneway void setGlobalShadowSettings(in Color ambientColor, in Color spotColor, float lightPosY, float lightPosZ, float lightRadius); void setGlobalShadowSettings(in Color ambientColor, in Color spotColor, float lightPosY, float lightPosZ, float lightRadius); /** * Gets whether a display supports DISPLAY_DECORATION layers. Loading
libs/renderengine/skia/SkiaRenderEngine.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -238,6 +238,7 @@ static inline SkM44 getSkM44(const android::mat4& matrix) { matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]); } [[maybe_unused]] static inline SkPoint3 getSkPoint3(const android::vec3& vector) { return SkPoint3::Make(vector.x, vector.y, vector.z); } Loading Loading @@ -1370,10 +1371,16 @@ void SkiaRenderEngine::drawShadow(SkCanvas* canvas, const auto flags = settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag; // DrawShadow expects the light pos in device space. // Shadow settings is in layer space (which is our current canvas transform). SkMatrix deviceFromLayer = canvas->getTotalMatrix(); SkPoint lightPos = {settings.lightPos.x, settings.lightPos.y}; // lightPos is in layer space deviceFromLayer.mapPoints(&lightPos, 1); // lightPos is in device space SkShadowUtils::DrawShadow(canvas, SkPath::RRect(casterRRect), SkPoint3::Make(0, 0, casterZ), getSkPoint3(settings.lightPos), settings.lightRadius, getSkColor(settings.ambientColor), getSkColor(settings.spotColor), flags); SkPoint3{lightPos.fX, lightPos.fY, settings.lightPos.z}, settings.lightRadius, getSkColor(settings.ambientColor), getSkColor(settings.spotColor), flags); } void SkiaRenderEngine::onActiveDisplaySizeChanged(ui::Size size) { Loading
services/surfaceflinger/LayerFE.cpp +13 −5 Original line number Diff line number Diff line Loading @@ -343,11 +343,19 @@ void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster, return; } // Shift the spot light x-position to the middle of the display and then // offset it by casting layer's screen pos. state.lightPos.x = (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left; state.lightPos.y -= mSnapshot->transformedBounds.top; // The light source should be at (screenWidth/2, globalShadowSettings.lightPos.y) in // screenspace. vec2 lightPosScreenSpace = { (static_cast<float>(layerStackRect.width()) / 2.f), state.lightPos.y, }; // Skia expects light pos in layer space. vec2 lightPosLayerSpace = mSnapshot->geomInverseLayerTransform.transform(lightPosScreenSpace); state.lightPos.x = lightPosLayerSpace.x; state.lightPos.y = lightPosLayerSpace.y; caster.shadow = state; } Loading
services/surfaceflinger/SurfaceFlinger.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -8304,6 +8304,9 @@ status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, cons // these values are overridden when calculating the shadow settings for a layer. mCurrentState.globalShadowSettings.lightPos.x = 0.f; mCurrentState.globalShadowSettings.length = 0.f; setTransactionFlags(eTransactionNeeded); return NO_ERROR; } Loading
services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +76 −6 Original line number Diff line number Diff line Loading @@ -876,18 +876,24 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, CropElevationShadowByParent) { ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::WHITE, parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::BLUE, size, size)); // TODO(b/377194534): This test fails on Tangor because global shadow // settings seem to not respect rotation. SurfaceComposerClient::getDefault()->setGlobalShadowSettings({1, 0, 0, 0.5f}, {0, 1, 0, 0.5f}, 0, 500.0f, 800.0f); 0, 250.0f, 800.0f); // Global shadow settings are committed after snapshot updates so we have to perform a commit // before enabling layer shadows. Transaction().apply(true); std::this_thread::sleep_for(std::chrono::seconds(1)); ui::Size resolution = mRenderPathHarness.getRotatedResolution(); int x = resolution.width / 2; int y = 500; Transaction() .setPosition(parent, x, y) .setCrop(parent, Rect(0, 0, parentSize / 2, parentSize)) .reparent(child, parent) .setPosition(child, size, size) .setCrop(child, Rect(0, 0, size, size)) .setPosition(child, size, size) .setCornerRadius(child, 20.0f) Loading @@ -896,7 +902,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, CropElevationShadowByParent) { auto shot = getScreenCapture(); shot->expectBufferMatchesImageFromFile(Rect(0, 0, parentSize, parentSize), shot->expectBufferMatchesImageFromFile(Rect(x, y, x + parentSize, y + parentSize), "testdata/CropElevationShadowByParent.png"); } Loading Loading @@ -1146,6 +1152,70 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) { shot->expectColor(crop, Color::RED); } } class RotatedVirtualDisplayTest : public LayerTypeTransactionHarness, public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath, ui::Rotation>> { public: RotatedVirtualDisplayTest() : LayerTypeTransactionHarness(std::get<0>(GetParam())), mRenderPathHarness(this, std::get<1>(GetParam()), std::get<2>(GetParam())) {} std::unique_ptr<ScreenCapture> getScreenCapture() { return mRenderPathHarness.getScreenCapture(); } protected: LayerRenderPathTestHarness mRenderPathHarness; }; INSTANTIATE_TEST_CASE_P(RotatedVirtualDisplayTests, RotatedVirtualDisplayTest, ::testing::Combine(::testing::Values(static_cast<uint32_t>( ISurfaceComposerClient::eFXSurfaceBufferState)), ::testing::Values(RenderPath::VIRTUAL_DISPLAY), ::testing::Values(ui::Rotation::Rotation0, ui::Rotation::Rotation90, ui::Rotation::Rotation180, ui::Rotation::Rotation270))); TEST_P(RotatedVirtualDisplayTest, ElevationShadowHasCorrectOrientation) { sp<SurfaceControl> parent; sp<SurfaceControl> child; const uint32_t size = 64; const uint32_t parentSize = size * 3; ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::WHITE, parentSize, parentSize)); ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size)); ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size)); SurfaceComposerClient::getDefault()->setGlobalShadowSettings({1, 0, 0, 1.0f}, {0, 1, 0, 1.0f}, 0, 500.0f, 800.0f); // Global shadow settings are committed after snapshot updates so we have to perform a commit // before enabling layer shadows. Transaction().apply(true); ui::Size resolution = mRenderPathHarness.getRotatedResolution(); int x = resolution.width / 2; int y = 500; Transaction() .setPosition(parent, x, y) .setCrop(parent, Rect(0, 0, parentSize, parentSize)) .reparent(child, parent) .setCrop(child, Rect(0, 0, size, size)) .setPosition(child, size, size) .setCornerRadius(child, 20.0f) .setShadowRadius(child, 20.0f) .apply(true); auto shot = getScreenCapture(); shot->expectBufferMatchesImageFromFile(mRenderPathHarness.rotateRect( Rect(x, y, x + parentSize, y + parentSize)), "testdata/Shadow_" + mRenderPathHarness.getRotationName() + ".png"); } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading