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

Commit 6452f12c authored by Robert Carr's avatar Robert Carr
Browse files

SurfaceFlinger: Inherit Alpha for child surfaces.

Necessary for various animations to work correctly and
for the general goal of treating child surfaces like
pixels in the parent surface.

Test: Includes new test in SurfaceFlinger_test
Bug: None yet ;)
Change-Id: Ic8309518bd327bbba6ad2f79f265e24cf37898e7
parent 8b71dc3c
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -595,7 +595,7 @@ void Layer::setGeometry(
    const State& s(getDrawingState());
#ifdef USE_HWC2
    auto blendMode = HWC2::BlendMode::None;
    if (!isOpaque(s) || s.alpha != 1.0f) {
    if (!isOpaque(s) || getAlpha() != 1.0f) {
        blendMode = mPremultipliedAlpha ?
                HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
    }
@@ -604,7 +604,7 @@ void Layer::setGeometry(
             " %s (%d)", mName.string(), to_string(blendMode).c_str(),
             to_string(error).c_str(), static_cast<int32_t>(error));
#else
    if (!isOpaque(s) || s.alpha != 0xFF) {
    if (!isOpaque(s) || getAlpha() != 0xFF) {
        layer.setBlending(mPremultipliedAlpha ?
                HWC_BLENDING_PREMULT :
                HWC_BLENDING_COVERAGE);
@@ -678,9 +678,10 @@ void Layer::setGeometry(
        hwcInfo.sourceCrop = sourceCrop;
    }

    error = hwcLayer->setPlaneAlpha(s.alpha);
    float alpha = getAlpha();
    error = hwcLayer->setPlaneAlpha(alpha);
    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
            "%s (%d)", mName.string(), s.alpha, to_string(error).c_str(),
            "%s (%d)", mName.string(), alpha, to_string(error).c_str(),
            static_cast<int32_t>(error));

    error = hwcLayer->setZOrder(z);
@@ -698,7 +699,7 @@ void Layer::setGeometry(
    const Transform& tr(hw->getTransform());
    layer.setFrame(tr.transform(frame));
    layer.setCrop(computeCrop(hw));
    layer.setPlaneAlpha(s.alpha);
    layer.setPlaneAlpha(getAlpha());
#endif

    /*
@@ -1147,7 +1148,7 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw,
    texCoords[3] = vec2(right, 1.0f - top);

    RenderEngine& engine(mFlinger->getRenderEngine());
    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
    engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
    engine.drawMesh(mMesh);
    engine.disableBlending();
}
@@ -1961,12 +1962,11 @@ bool Layer::isHiddenByPolicy() const {
}

bool Layer::isVisible() const {
    const Layer::State& s(mDrawingState);
#ifdef USE_HWC2
    return !(isHiddenByPolicy()) && s.alpha > 0.0f
    return !(isHiddenByPolicy()) && getAlpha() > 0.0f
            && (mActiveBuffer != NULL || mSidebandStream != NULL);
#else
    return !(isHiddenByPolicy()) && s.alpha
    return !(isHiddenByPolicy()) && getAlpha()
            && (mActiveBuffer != NULL || mSidebandStream != NULL);
#endif
}
@@ -2523,6 +2523,24 @@ Transform Layer::getTransform() const {
    return t * getDrawingState().active.transform;
}

#ifdef USE_HWC2
float Layer::getAlpha() const {
    const auto& p = getParent();

    float parentAlpha = (p != nullptr) ? p->getAlpha() : 1.0;
    return parentAlpha * getDrawingState().alpha;
}
#else
uint8_t Layer::getAlpha() const {
    const auto& p = getParent();

    float parentAlpha = (p != nullptr) ? (p->getAlpha() / 255.0f) : 1.0;
    float drawingAlpha = getDrawingState().alpha / 255.0f;
    drawingAlpha = drawingAlpha * parentAlpha;
    return static_cast<uint8_t>(std::round(drawingAlpha * 255));
}
#endif

void Layer::commitChildList() {
    for (size_t i = 0; i < mCurrentChildren.size(); i++) {
        const auto& child = mCurrentChildren[i];
+9 −0
Original line number Diff line number Diff line
@@ -459,6 +459,15 @@ public:

    Transform getTransform() const;

    // Returns the Alpha of the Surface, accounting for the Alpha
    // of parent Surfaces in the hierarchy (alpha's will be multiplied
    // down the hierarchy).
#ifdef USE_HWC2
    float getAlpha() const;
#else
    uint8_t getAlpha() const;
#endif

    void traverseInReverseZOrder(const std::function<void(Layer*)>& exec);
    void traverseInZOrder(const std::function<void(Layer*)>& exec);

+39 −0
Original line number Diff line number Diff line
@@ -764,6 +764,45 @@ TEST_F(ChildLayerTest, ChildLayerScaling) {
    }
}

TEST_F(ChildLayerTest, ChildLayerAlpha) {
    fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254);
    fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0);
    fillSurfaceRGBA8(mChild, 0, 254, 0);
    waitForPostedBuffers();

    SurfaceComposerClient::openGlobalTransaction();
    mChild->show();
    mChild->setPosition(0, 0);
    mFGSurfaceControl->setPosition(0, 0);
    SurfaceComposerClient::closeGlobalTransaction(true);

    {
        ScreenCapture::captureScreen(&mCapture);
        // Unblended child color
        mCapture->checkPixel(0, 0, 0, 254, 0);
    }

    SurfaceComposerClient::openGlobalTransaction();
    ASSERT_EQ(NO_ERROR, mChild->setAlpha(0.5));
    SurfaceComposerClient::closeGlobalTransaction(true);

    {
        ScreenCapture::captureScreen(&mCapture);
        // Child and BG blended.
        mCapture->checkPixel(0, 0, 127, 127, 0);
    }

    SurfaceComposerClient::openGlobalTransaction();
    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.5));
    SurfaceComposerClient::closeGlobalTransaction(true);

    {
        ScreenCapture::captureScreen(&mCapture);
        // Child and BG blended.
        mCapture->checkPixel(0, 0, 95, 64, 95);
    }
}

TEST_F(ChildLayerTest, ReparentChildren) {
    SurfaceComposerClient::openGlobalTransaction();
    mChild->show();