Merge "RenderEngine: draw A8 buffers with a color filter"
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 063ce67..763b82d 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -1104,6 +1104,15 @@
paint.setDither(true);
}
paint.setAlphaf(layer.alpha);
+
+ if (imageTextureRef->colorType() == kAlpha_8_SkColorType) {
+ LOG_ALWAYS_FATAL_IF(layer.disableBlending, "Cannot disableBlending with A8");
+ float matrix[] = { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, -1, 1 };
+ paint.setColorFilter(SkColorFilters::Matrix(matrix));
+ }
} else {
ATRACE_NAME("DrawColor");
const auto color = layer.source.solidColor;
@@ -1125,7 +1134,11 @@
paint.setBlendMode(SkBlendMode::kSrc);
}
- paint.setColorFilter(displayColorTransform);
+ // A color filter will have been set for an A8 buffer. Do not replace
+ // it with the displayColorTransform, which shouldn't affect A8.
+ if (!paint.getColorFilter()) {
+ paint.setColorFilter(displayColorTransform);
+ }
if (!roundRectClip.isEmpty()) {
canvas->clipRRect(roundRectClip, true);
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 2a25b0b..612a0aa 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -218,14 +218,35 @@
uint8_t* pixels;
buffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
reinterpret_cast<void**>(&pixels));
- pixels[0] = color.r;
- pixels[1] = color.g;
- pixels[2] = color.b;
- pixels[3] = color.a;
+ for (uint32_t j = 0; j < height; j++) {
+ uint8_t* dst = pixels + (buffer->getBuffer()->getStride() * j * 4);
+ for (uint32_t i = 0; i < width; i++) {
+ dst[0] = color.r;
+ dst[1] = color.g;
+ dst[2] = color.b;
+ dst[3] = color.a;
+ dst += 4;
+ }
+ }
buffer->getBuffer()->unlock();
return buffer;
}
+ std::shared_ptr<renderengine::ExternalTexture> allocateR8Buffer(int width, int height) {
+ auto buffer = new GraphicBuffer(width, height, android::PIXEL_FORMAT_R_8, 1,
+ GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_TEXTURE,
+ "r8");
+ if (buffer->initCheck() != 0) {
+ // Devices are not required to support R8.
+ return nullptr;
+ }
+ return std::make_shared<
+ renderengine::impl::ExternalTexture>(std::move(buffer), *mRE,
+ renderengine::impl::ExternalTexture::Usage::
+ READABLE);
+ }
+
RenderEngineTest() {
const ::testing::TestInfo* const test_info =
::testing::UnitTest::GetInstance()->current_test_info();
@@ -2541,6 +2562,66 @@
expectBufferColor(Rect(kGreyLevels, 1), generator, 2);
}
+
+TEST_P(RenderEngineTest, r8_behaves_as_mask) {
+ if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+ return;
+ }
+
+ initializeRenderEngine();
+
+ const auto r8Buffer = allocateR8Buffer(2, 1);
+ if (!r8Buffer) {
+ return;
+ }
+ {
+ uint8_t* pixels;
+ r8Buffer->getBuffer()->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+ // This will be drawn on top of a green buffer. We'll verify that 255
+ // results in keeping the original green and 0 results in black.
+ pixels[0] = 0;
+ pixels[1] = 255;
+ r8Buffer->getBuffer()->unlock();
+ }
+
+ const auto rect = Rect(0, 0, 2, 1);
+ const renderengine::DisplaySettings display{
+ .physicalDisplay = rect,
+ .clip = rect,
+ .outputDataspace = ui::Dataspace::SRGB,
+ };
+
+ const auto greenBuffer = allocateAndFillSourceBuffer(2, 1, ubyte4(0, 255, 0, 255));
+ const renderengine::LayerSettings greenLayer{
+ .geometry.boundaries = rect.toFloatRect(),
+ .source =
+ renderengine::PixelSource{
+ .buffer =
+ renderengine::Buffer{
+ .buffer = greenBuffer,
+ },
+ },
+ .alpha = 1.0f,
+ };
+ const renderengine::LayerSettings r8Layer{
+ .geometry.boundaries = rect.toFloatRect(),
+ .source =
+ renderengine::PixelSource{
+ .buffer =
+ renderengine::Buffer{
+ .buffer = r8Buffer,
+ },
+ },
+ .alpha = 1.0f,
+ };
+
+ std::vector<renderengine::LayerSettings> layers{greenLayer, r8Layer};
+ invokeDraw(display, layers);
+
+ expectBufferColor(Rect(0, 0, 1, 1), 0, 0, 0, 255);
+ expectBufferColor(Rect(1, 0, 2, 1), 0, 255, 0, 255);
+}
} // namespace renderengine
} // namespace android