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

Commit cf3d95cd authored by Leon Scroggins III's avatar Leon Scroggins III Committed by Leon Scroggins
Browse files

SkiaRE: respect disableBlending

Fixes: 182617606
Test: atest librenderengine_test
      RenderEngineTest#testClear
      RenderEngineTest#testDisableBlendingBuffer

When drawing an image or a solid color, use SkBlendMode::kSrc to
avoid blending with other layers. Assert that disableBlending is not
combined with a shadow, since our existing API does not support that.
Continue to ignore disableBlending with blur, which we do not expect
to see as input.

Add RenderEngineTest#testClear and #testDisableBlendingBuffer to verify
the fix.

Change-Id: Ie12cbf497ecb6b71a9b4b625710161fce2b06ee4
parent d5ecb64e
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -797,6 +797,8 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
            const auto rect = layer->geometry.roundedCornersRadius > 0
                    ? getSkRect(layer->geometry.roundedCornersCrop)
                    : bounds;
            // This would require a new parameter/flag to SkShadowUtils::DrawShadow
            LOG_ALWAYS_FATAL_IF(layer->disableBlending, "Cannot disableBlending with a shadow");
            drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
            continue;
        }
@@ -806,7 +808,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                 needsToneMapping(layer->sourceDataspace, display.outputDataspace));

        // quick abort from drawing the remaining portion of the layer
        if (layer->alpha == 0 && !requiresLinearEffect &&
        if (layer->alpha == 0 && !requiresLinearEffect && !layer->disableBlending &&
            (!displayColorTransform || displayColorTransform->isAlphaUnchanged())) {
            continue;
        }
@@ -912,6 +914,10 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
                                                      requiresLinearEffect));
        }

        if (layer->disableBlending) {
            paint.setBlendMode(SkBlendMode::kSrc);
        }

        paint.setColorFilter(displayColorTransform);

        if (layer->geometry.roundedCornersRadius > 0) {
+77 −0
Original line number Diff line number Diff line
@@ -1920,6 +1920,83 @@ TEST_P(RenderEngineTest, testRoundedCornersCrop) {
                      0, 255, 0, 255);
}

TEST_P(RenderEngineTest, testClear) {
    initializeRenderEngine();

    const auto rect = fullscreenRect();
    const renderengine::DisplaySettings display{
            .physicalDisplay = rect,
            .clip = rect,
    };

    const renderengine::LayerSettings redLayer{
            .geometry.boundaries = rect.toFloatRect(),
            .source.solidColor = half3(1.0f, 0.0f, 0.0f),
            .alpha = 1.0f,
    };

    // This mimics prepareClearClientComposition. This layer should overwrite
    // the redLayer, so that the buffer is transparent, rather than red.
    const renderengine::LayerSettings clearLayer{
            .geometry.boundaries = rect.toFloatRect(),
            .source.solidColor = half3(0.0f, 0.0f, 0.0f),
            .alpha = 0.0f,
            .disableBlending = true,
    };

    std::vector<const renderengine::LayerSettings*> layers{&redLayer, &clearLayer};
    invokeDraw(display, layers);
    expectBufferColor(rect, 0, 0, 0, 0);
}

TEST_P(RenderEngineTest, testDisableBlendingBuffer) {
    initializeRenderEngine();

    const auto rect = Rect(0, 0, 1, 1);
    const renderengine::DisplaySettings display{
            .physicalDisplay = rect,
            .clip = rect,
    };

    const renderengine::LayerSettings redLayer{
            .geometry.boundaries = rect.toFloatRect(),
            .source.solidColor = half3(1.0f, 0.0f, 0.0f),
            .alpha = 1.0f,
    };

    // The next layer will overwrite redLayer with a GraphicBuffer that is green
    // applied with a translucent alpha.
    auto buf = allocateSourceBuffer(1, 1);
    {
        uint8_t* pixels;
        buf->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] = 255;
        buf->unlock();
    }

    const renderengine::LayerSettings greenLayer{
            .geometry.boundaries = rect.toFloatRect(),
            .source =
                    renderengine::PixelSource{
                            .buffer =
                                    renderengine::Buffer{
                                            .buffer = buf,
                                            .usePremultipliedAlpha = true,
                                    },
                    },
            .alpha = 0.5f,
            .disableBlending = true,
    };

    std::vector<const renderengine::LayerSettings*> layers{&redLayer, &greenLayer};
    invokeDraw(display, layers);
    expectBufferColor(rect, 0, 128, 0, 128);
}

} // namespace android

// TODO(b/129481165): remove the #pragma below and fix conversion issues