Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a704aa66 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: Handle multiple rounded corner settings" into sc-v2-dev

parents 4541ab50 9dbf8e89
Loading
Loading
Loading
Loading
+31 −10
Original line number Original line Diff line number Diff line
@@ -1915,27 +1915,48 @@ const std::vector<BlurRegion> Layer::getBlurRegions() const {
}
}


Layer::RoundedCornerState Layer::getRoundedCornerState() const {
Layer::RoundedCornerState Layer::getRoundedCornerState() const {
    const auto& p = mDrawingParent.promote();
    // Get parent settings
    if (p != nullptr) {
    RoundedCornerState parentSettings;
        RoundedCornerState parentState = p->getRoundedCornerState();
    const auto& parent = mDrawingParent.promote();
        if (parentState.radius > 0) {
    if (parent != nullptr) {
        parentSettings = parent->getRoundedCornerState();
        if (parentSettings.radius > 0) {
            ui::Transform t = getActiveTransform(getDrawingState());
            ui::Transform t = getActiveTransform(getDrawingState());
            t = t.inverse();
            t = t.inverse();
            parentState.cropRect = t.transform(parentState.cropRect);
            parentSettings.cropRect = t.transform(parentSettings.cropRect);
            // The rounded corners shader only accepts 1 corner radius for performance reasons,
            // The rounded corners shader only accepts 1 corner radius for performance reasons,
            // but a transform matrix can define horizontal and vertical scales.
            // but a transform matrix can define horizontal and vertical scales.
            // Let's take the average between both of them and pass into the shader, practically we
            // Let's take the average between both of them and pass into the shader, practically we
            // never do this type of transformation on windows anyway.
            // never do this type of transformation on windows anyway.
            auto scaleX = sqrtf(t[0][0] * t[0][0] + t[0][1] * t[0][1]);
            auto scaleX = sqrtf(t[0][0] * t[0][0] + t[0][1] * t[0][1]);
            auto scaleY = sqrtf(t[1][0] * t[1][0] + t[1][1] * t[1][1]);
            auto scaleY = sqrtf(t[1][0] * t[1][0] + t[1][1] * t[1][1]);
            parentState.radius *= (scaleX + scaleY) / 2.0f;
            parentSettings.radius *= (scaleX + scaleY) / 2.0f;
            return parentState;
        }
        }
    }
    }

    // Get layer settings
    Rect layerCropRect = getCroppedBufferSize(getDrawingState());
    const float radius = getDrawingState().cornerRadius;
    const float radius = getDrawingState().cornerRadius;
    return radius > 0 && getCroppedBufferSize(getDrawingState()).isValid()
    RoundedCornerState layerSettings(layerCropRect.toFloatRect(), radius);
            ? RoundedCornerState(getCroppedBufferSize(getDrawingState()).toFloatRect(), radius)

            : RoundedCornerState();
    if (layerSettings.radius > 0 && parentSettings.radius > 0) {
        // If the parent and the layer have rounded corner settings, use the parent settings if the
        // parent crop is entirely inside the layer crop.
        // This has limitations and cause rendering artifacts. See b/200300845 for correct fix.
        if (parentSettings.cropRect.left > layerCropRect.left &&
            parentSettings.cropRect.top > layerCropRect.top &&
            parentSettings.cropRect.right < layerCropRect.right &&
            parentSettings.cropRect.bottom < layerCropRect.bottom) {
            return parentSettings;
        } else {
            return layerSettings;
        }
    } else if (layerSettings.radius > 0) {
        return layerSettings;
    } else if (parentSettings.radius > 0) {
        return parentSettings;
    }
    return {};
}
}


void Layer::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
void Layer::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
+2 −4
Original line number Original line Diff line number Diff line
@@ -606,10 +606,8 @@ public:
    virtual bool getTransformToDisplayInverse() const { return false; }
    virtual bool getTransformToDisplayInverse() const { return false; }


    // Returns how rounded corners should be drawn for this layer.
    // Returns how rounded corners should be drawn for this layer.
    // This will traverse the hierarchy until it reaches its root, finding topmost rounded
    // A layer can override its parent's rounded corner settings if the parent's rounded
    // corner definition and converting it into current layer's coordinates.
    // corner crop does not intersect with its own rounded corner crop.
    // As of now, only 1 corner radius per display list is supported. Subsequent ones will be
    // ignored.
    virtual RoundedCornerState getRoundedCornerState() const;
    virtual RoundedCornerState getRoundedCornerState() const;


    bool hasRoundedCorners() const override { return getRoundedCornerState().radius > .0f; }
    bool hasRoundedCorners() const override { return getRoundedCornerState().radius > .0f; }
+89 −0
Original line number Original line Diff line number Diff line
@@ -465,6 +465,95 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildBufferRotation
    }
    }
}
}


TEST_P(LayerTypeAndRenderTypeTransactionTest, ChildCornerRadiusTakesPrecedence) {
    sp<SurfaceControl> parent;
    sp<SurfaceControl> child;
    const uint32_t size = 64;
    const uint32_t parentSize = size * 3;
    const uint32_t testLength = 4;
    const float cornerRadius = 20.0f;
    ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize));
    ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, parentSize, parentSize));
    ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size));
    ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size));

    Transaction()
            .setCornerRadius(parent, cornerRadius)
            .setCornerRadius(child, cornerRadius)
            .reparent(child, parent)
            .setPosition(child, size, size)
            .apply();

    {
        const uint32_t top = size - 1;
        const uint32_t left = size - 1;
        const uint32_t bottom = size * 2 - 1;
        const uint32_t right = size * 2 - 1;
        auto shot = getScreenCapture();
        // Edges are transparent
        // TL
        shot->expectColor(Rect(left, top, testLength, testLength), Color::RED);
        // TR
        shot->expectColor(Rect(right - testLength, top, right, testLength), Color::RED);
        // BL
        shot->expectColor(Rect(left, bottom - testLength, testLength, bottom - testLength),
                          Color::RED);
        // BR
        shot->expectColor(Rect(right - testLength, bottom - testLength, right, bottom), Color::RED);
        // Solid center
        shot->expectColor(Rect(parentSize / 2 - testLength / 2, parentSize / 2 - testLength / 2,
                               parentSize / 2 + testLength / 2, parentSize / 2 + testLength / 2),
                          Color::GREEN);
    }
}

// Test if ParentCornerRadiusTakesPrecedence if the parent corner radius crop is fully contained by
// the child corner radius crop.
TEST_P(LayerTypeAndRenderTypeTransactionTest, ParentCornerRadiusTakesPrecedence) {
    sp<SurfaceControl> parent;
    sp<SurfaceControl> child;
    const uint32_t size = 64;
    const uint32_t parentSize = size * 3;
    const Rect parentCrop(size + 1, size + 1, size * 2 - 1, size * 2 - 1);
    const uint32_t testLength = 4;
    const float cornerRadius = 20.0f;
    ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", parentSize, parentSize));
    ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, parentSize, parentSize));
    ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size));
    ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size));

    Transaction()
            .setCornerRadius(parent, cornerRadius)
            .setCrop(parent, parentCrop)
            .setCornerRadius(child, cornerRadius)
            .reparent(child, parent)
            .setPosition(child, size, size)
            .apply();

    {
        const uint32_t top = size - 1;
        const uint32_t left = size - 1;
        const uint32_t bottom = size * 2 - 1;
        const uint32_t right = size * 2 - 1;
        auto shot = getScreenCapture();
        // Edges are transparent
        // TL
        shot->expectColor(Rect(left, top, testLength, testLength), Color::BLACK);
        // TR
        shot->expectColor(Rect(right - testLength, top, right, testLength), Color::BLACK);
        // BL
        shot->expectColor(Rect(left, bottom - testLength, testLength, bottom - testLength),
                          Color::BLACK);
        // BR
        shot->expectColor(Rect(right - testLength, bottom - testLength, right, bottom),
                          Color::BLACK);
        // Solid center
        shot->expectColor(Rect(parentSize / 2 - testLength / 2, parentSize / 2 - testLength / 2,
                               parentSize / 2 + testLength / 2, parentSize / 2 + testLength / 2),
                          Color::GREEN);
    }
}

TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) {
TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBackgroundBlurRadiusSimple) {
    if (!deviceSupportsBlurs()) GTEST_SKIP();
    if (!deviceSupportsBlurs()) GTEST_SKIP();
    if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();
    if (!deviceUsesSkiaRenderEngine()) GTEST_SKIP();