Loading libs/renderengine/include/renderengine/DisplaySettings.h +4 −2 Original line number Diff line number Diff line Loading @@ -57,8 +57,10 @@ struct DisplaySettings { // orientation. uint32_t orientation = ui::Transform::ROT_0; // SDR white point, -1f if unknown float sdrWhitePointNits = -1.f; // Target luminance of the display. -1f if unknown. // All layers will be dimmed by (max(layer white points) / targetLuminanceNits). // If the target luminance is unknown, then no display-level dimming occurs. float targetLuminanceNits = -1.f; }; static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) { Loading libs/renderengine/include/renderengine/LayerSettings.h +6 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,12 @@ struct LayerSettings { // Name associated with the layer for debugging purposes. std::string name; // Luminance of the white point for this layer. Used for linear dimming. // Individual layers will be dimmed by (whitePointNits / maxWhitePoint). // If white point nits are unknown, then this layer is assumed to have the // same luminance as the brightest layer in the scene. float whitePointNits = -1.f; }; // Keep in sync with custom comparison function in Loading libs/renderengine/skia/SkiaGLRenderEngine.cpp +69 −33 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <cmath> #include <cstdint> #include <memory> #include <numeric> #include "../gl/GLExtensions.h" #include "Cache.h" Loading Loading @@ -612,33 +613,33 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect) { const auto stretchEffect = layer.stretchEffect; sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader( const RuntimeEffectShaderParameters& parameters) { // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger const auto& stretchEffect = parameters.layer.stretchEffect; auto shader = parameters.shader; if (stretchEffect.hasEffect()) { const auto targetBuffer = layer.source.buffer.buffer; const auto targetBuffer = parameters.layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { if (graphicBuffer && parameters.shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); } } if (requiresLinearEffect) { const ui::Dataspace inputDataspace = mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; if (parameters.requiresLinearEffect) { const ui::Dataspace inputDataspace = mUseColorManagement ? parameters.layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? parameters.display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; auto effect = shaders::LinearEffect{.inputDataspace = inputDataspace, auto effect = shaders::LinearEffect{.inputDataspace = inputDataspace, .outputDataspace = outputDataspace, .undoPremultipliedAlpha = undoPremultipliedAlpha}; .undoPremultipliedAlpha = parameters.undoPremultipliedAlpha}; auto effectIter = mRuntimeEffects.find(effect); sk_sp<SkRuntimeEffect> runtimeEffect = nullptr; Loading @@ -648,16 +649,16 @@ sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> sh } else { runtimeEffect = effectIter->second; } float maxLuminance = layer.source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, display.maxLuminance, maxLuminance); mat4 colorTransform = parameters.layer.colorTransform; colorTransform *= mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio, parameters.layerDimmingRatio, 1.f)); return createLinearEffectShader(parameters.shader, effect, runtimeEffect, colorTransform, parameters.display.maxLuminance, parameters.layer.source.buffer.maxLuminanceNits); } return shader; return parameters.shader; } void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) { Loading Loading @@ -730,6 +731,11 @@ static SkRRect getBlurRRect(const BlurRegion& region) { return roundedRect; } static bool equalsWithinMargin(float expected, float value, float margin) { LOG_ALWAYS_FATAL_IF(margin < 0.f, "Margin is negative!"); return std::abs(expected - value) < margin; } void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, Loading Loading @@ -791,6 +797,18 @@ void SkiaGLRenderEngine::drawLayersInternal( const bool ctModifiesAlpha = displayColorTransform && !displayColorTransform->isAlphaUnchanged(); // Find the max layer white point to determine the max luminance of the scene... const float maxLayerWhitePoint = std::transform_reduce( layers.cbegin(), layers.cend(), 0.f, [](float left, float right) { return std::max(left, right); }, [&](const auto& l) { return l.whitePointNits; }); // ...and compute the dimming ratio if dimming is requested const float displayDimmingRatio = display.targetLuminanceNits > 0.f && maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint ? maxLayerWhitePoint / display.targetLuminanceNits : 1.f; // Find if any layers have requested blur, we'll use that info to decide when to render to an // offscreen buffer and when to render to the native buffer. sk_sp<SkSurface> activeSurface(dstSurface); Loading Loading @@ -964,11 +982,14 @@ void SkiaGLRenderEngine::drawLayersInternal( drawShadow(canvas, rrect, layer.shadow); } const float layerDimmingRatio = layer.whitePointNits <= 0.f ? displayDimmingRatio : (layer.whitePointNits / maxLayerWhitePoint) * displayDimmingRatio; const bool requiresLinearEffect = layer.colorTransform != mat4() || (mUseColorManagement && needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); !equalsWithinMargin(1.f, layerDimmingRatio, 0.001f); // quick abort from drawing the remaining portion of the layer if (layer.skipContentDraw || Loading Loading @@ -1067,9 +1088,20 @@ void SkiaGLRenderEngine::drawLayersInternal( toSkColorSpace(layerDataspace))); } paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); paint.setShader(createRuntimeEffectShader( RuntimeEffectShaderParameters{.shader = shader, .layer = layer, .display = display, .undoPremultipliedAlpha = !item.isOpaque && item.usePremultipliedAlpha, .requiresLinearEffect = requiresLinearEffect, .layerDimmingRatio = layerDimmingRatio})); // Turn on dithering when dimming beyond this threshold. static constexpr float kDimmingThreshold = 0.2f; if (layerDimmingRatio <= kDimmingThreshold) { paint.setDither(true); } paint.setAlphaf(layer.alpha); } else { ATRACE_NAME("DrawColor"); Loading @@ -1079,9 +1111,13 @@ void SkiaGLRenderEngine::drawLayersInternal( .fB = color.b, .fA = layer.alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); paint.setShader(createRuntimeEffectShader( RuntimeEffectShaderParameters{.shader = shader, .layer = layer, .display = display, .undoPremultipliedAlpha = false, .requiresLinearEffect = requiresLinearEffect, .layerDimmingRatio = layerDimmingRatio})); } if (layer.disableBlending) { Loading libs/renderengine/skia/SkiaGLRenderEngine.h +10 −4 Original line number Diff line number Diff line Loading @@ -106,12 +106,18 @@ private: void initCanvas(SkCanvas* canvas, const DisplaySettings& display); void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect, const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. sk_sp<SkShader> createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); struct RuntimeEffectShaderParameters { sk_sp<SkShader> shader; const LayerSettings& layer; const DisplaySettings& display; bool undoPremultipliedAlpha; bool requiresLinearEffect; float layerDimmingRatio; }; sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&); EGLDisplay mEGLDisplay; EGLContext mEGLContext; Loading libs/renderengine/tests/RenderEngineTest.cpp +142 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,21 @@ public: renderengine::ExternalTexture::Usage::WRITEABLE); } std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width, uint32_t height, ubyte4 color) { const auto buffer = allocateSourceBuffer(width, height); 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; buffer->getBuffer()->unlock(); return buffer; } RenderEngineTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); Loading Loading @@ -2195,6 +2210,133 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { expectBufferColor(rect, 0, 128, 0, 128); } TEST_P(RenderEngineTest, testDimming) { if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) { return; } initializeRenderEngine(); const auto displayRect = Rect(3, 1); const renderengine::DisplaySettings display{ .physicalDisplay = displayRect, .clip = displayRect, .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, .targetLuminanceNits = 1000.f, }; const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255)); const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255)); const auto redBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(255, 0, 0, 255)); const renderengine::LayerSettings greenLayer{ .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = greenBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 200.f, }; const renderengine::LayerSettings blueLayer{ .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = blueBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 1000.f / 51.f, }; const renderengine::LayerSettings redLayer{ .geometry.boundaries = FloatRect(2.f, 0.f, 3.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = redBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, // When the white point is not set for a layer, just ignore it and treat it as the same // as the max layer .whitePointNits = -1.f, }; std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer, redLayer}; invokeDraw(display, layers); expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1); expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 5, 255, 1); expectBufferColor(Rect(2, 0, 3, 1), 51, 0, 0, 255, 1); } TEST_P(RenderEngineTest, testDimming_withoutTargetLuminance) { initializeRenderEngine(); if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) { return; } const auto displayRect = Rect(2, 1); const renderengine::DisplaySettings display{ .physicalDisplay = displayRect, .clip = displayRect, .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, .targetLuminanceNits = -1.f, }; const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255)); const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255)); const renderengine::LayerSettings greenLayer{ .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = greenBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 200.f, }; const renderengine::LayerSettings blueLayer{ .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = blueBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 1000.f, }; std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer}; invokeDraw(display, layers); expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1); expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 255, 255); } TEST_P(RenderEngineTest, test_isOpaque) { initializeRenderEngine(); Loading Loading
libs/renderengine/include/renderengine/DisplaySettings.h +4 −2 Original line number Diff line number Diff line Loading @@ -57,8 +57,10 @@ struct DisplaySettings { // orientation. uint32_t orientation = ui::Transform::ROT_0; // SDR white point, -1f if unknown float sdrWhitePointNits = -1.f; // Target luminance of the display. -1f if unknown. // All layers will be dimmed by (max(layer white points) / targetLuminanceNits). // If the target luminance is unknown, then no display-level dimming occurs. float targetLuminanceNits = -1.f; }; static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) { Loading
libs/renderengine/include/renderengine/LayerSettings.h +6 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,12 @@ struct LayerSettings { // Name associated with the layer for debugging purposes. std::string name; // Luminance of the white point for this layer. Used for linear dimming. // Individual layers will be dimmed by (whitePointNits / maxWhitePoint). // If white point nits are unknown, then this layer is assumed to have the // same luminance as the brightest layer in the scene. float whitePointNits = -1.f; }; // Keep in sync with custom comparison function in Loading
libs/renderengine/skia/SkiaGLRenderEngine.cpp +69 −33 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ #include <cmath> #include <cstdint> #include <memory> #include <numeric> #include "../gl/GLExtensions.h" #include "Cache.h" Loading Loading @@ -612,33 +613,33 @@ private: AutoBackendTexture::CleanupManager& mMgr; }; sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect) { const auto stretchEffect = layer.stretchEffect; sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader( const RuntimeEffectShaderParameters& parameters) { // The given surface will be stretched by HWUI via matrix transformation // which gets similar results for most surfaces // Determine later on if we need to leverage the stertch shader within // surface flinger const auto& stretchEffect = parameters.layer.stretchEffect; auto shader = parameters.shader; if (stretchEffect.hasEffect()) { const auto targetBuffer = layer.source.buffer.buffer; const auto targetBuffer = parameters.layer.source.buffer.buffer; const auto graphicBuffer = targetBuffer ? targetBuffer->getBuffer() : nullptr; if (graphicBuffer && shader) { if (graphicBuffer && parameters.shader) { shader = mStretchShaderFactory.createSkShader(shader, stretchEffect); } } if (requiresLinearEffect) { const ui::Dataspace inputDataspace = mUseColorManagement ? layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; if (parameters.requiresLinearEffect) { const ui::Dataspace inputDataspace = mUseColorManagement ? parameters.layer.sourceDataspace : ui::Dataspace::V0_SRGB_LINEAR; const ui::Dataspace outputDataspace = mUseColorManagement ? parameters.display.outputDataspace : ui::Dataspace::V0_SRGB_LINEAR; auto effect = shaders::LinearEffect{.inputDataspace = inputDataspace, auto effect = shaders::LinearEffect{.inputDataspace = inputDataspace, .outputDataspace = outputDataspace, .undoPremultipliedAlpha = undoPremultipliedAlpha}; .undoPremultipliedAlpha = parameters.undoPremultipliedAlpha}; auto effectIter = mRuntimeEffects.find(effect); sk_sp<SkRuntimeEffect> runtimeEffect = nullptr; Loading @@ -648,16 +649,16 @@ sk_sp<SkShader> SkiaGLRenderEngine::createRuntimeEffectShader(sk_sp<SkShader> sh } else { runtimeEffect = effectIter->second; } float maxLuminance = layer.source.buffer.maxLuminanceNits; // If the buffer doesn't have a max luminance, treat it as SDR & use the display's SDR // white point if (maxLuminance <= 0.f) { maxLuminance = display.sdrWhitePointNits; } return createLinearEffectShader(shader, effect, runtimeEffect, layer.colorTransform, display.maxLuminance, maxLuminance); mat4 colorTransform = parameters.layer.colorTransform; colorTransform *= mat4::scale(vec4(parameters.layerDimmingRatio, parameters.layerDimmingRatio, parameters.layerDimmingRatio, 1.f)); return createLinearEffectShader(parameters.shader, effect, runtimeEffect, colorTransform, parameters.display.maxLuminance, parameters.layer.source.buffer.maxLuminanceNits); } return shader; return parameters.shader; } void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) { Loading Loading @@ -730,6 +731,11 @@ static SkRRect getBlurRRect(const BlurRegion& region) { return roundedRect; } static bool equalsWithinMargin(float expected, float value, float margin) { LOG_ALWAYS_FATAL_IF(margin < 0.f, "Margin is negative!"); return std::abs(expected - value) < margin; } void SkiaGLRenderEngine::drawLayersInternal( const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise, const DisplaySettings& display, const std::vector<LayerSettings>& layers, Loading Loading @@ -791,6 +797,18 @@ void SkiaGLRenderEngine::drawLayersInternal( const bool ctModifiesAlpha = displayColorTransform && !displayColorTransform->isAlphaUnchanged(); // Find the max layer white point to determine the max luminance of the scene... const float maxLayerWhitePoint = std::transform_reduce( layers.cbegin(), layers.cend(), 0.f, [](float left, float right) { return std::max(left, right); }, [&](const auto& l) { return l.whitePointNits; }); // ...and compute the dimming ratio if dimming is requested const float displayDimmingRatio = display.targetLuminanceNits > 0.f && maxLayerWhitePoint > 0.f && display.targetLuminanceNits > maxLayerWhitePoint ? maxLayerWhitePoint / display.targetLuminanceNits : 1.f; // Find if any layers have requested blur, we'll use that info to decide when to render to an // offscreen buffer and when to render to the native buffer. sk_sp<SkSurface> activeSurface(dstSurface); Loading Loading @@ -964,11 +982,14 @@ void SkiaGLRenderEngine::drawLayersInternal( drawShadow(canvas, rrect, layer.shadow); } const float layerDimmingRatio = layer.whitePointNits <= 0.f ? displayDimmingRatio : (layer.whitePointNits / maxLayerWhitePoint) * displayDimmingRatio; const bool requiresLinearEffect = layer.colorTransform != mat4() || (mUseColorManagement && needsToneMapping(layer.sourceDataspace, display.outputDataspace)) || (display.sdrWhitePointNits > 0.f && display.sdrWhitePointNits != display.maxLuminance); !equalsWithinMargin(1.f, layerDimmingRatio, 0.001f); // quick abort from drawing the remaining portion of the layer if (layer.skipContentDraw || Loading Loading @@ -1067,9 +1088,20 @@ void SkiaGLRenderEngine::drawLayersInternal( toSkColorSpace(layerDataspace))); } paint.setShader(createRuntimeEffectShader(shader, layer, display, !item.isOpaque && item.usePremultipliedAlpha, requiresLinearEffect)); paint.setShader(createRuntimeEffectShader( RuntimeEffectShaderParameters{.shader = shader, .layer = layer, .display = display, .undoPremultipliedAlpha = !item.isOpaque && item.usePremultipliedAlpha, .requiresLinearEffect = requiresLinearEffect, .layerDimmingRatio = layerDimmingRatio})); // Turn on dithering when dimming beyond this threshold. static constexpr float kDimmingThreshold = 0.2f; if (layerDimmingRatio <= kDimmingThreshold) { paint.setDither(true); } paint.setAlphaf(layer.alpha); } else { ATRACE_NAME("DrawColor"); Loading @@ -1079,9 +1111,13 @@ void SkiaGLRenderEngine::drawLayersInternal( .fB = color.b, .fA = layer.alpha}, toSkColorSpace(layerDataspace)); paint.setShader(createRuntimeEffectShader(shader, layer, display, /* undoPremultipliedAlpha */ false, requiresLinearEffect)); paint.setShader(createRuntimeEffectShader( RuntimeEffectShaderParameters{.shader = shader, .layer = layer, .display = display, .undoPremultipliedAlpha = false, .requiresLinearEffect = requiresLinearEffect, .layerDimmingRatio = layerDimmingRatio})); } if (layer.disableBlending) { Loading
libs/renderengine/skia/SkiaGLRenderEngine.h +10 −4 Original line number Diff line number Diff line Loading @@ -106,12 +106,18 @@ private: void initCanvas(SkCanvas* canvas, const DisplaySettings& display); void drawShadow(SkCanvas* canvas, const SkRRect& casterRRect, const ShadowSettings& shadowSettings); // If requiresLinearEffect is true or the layer has a stretchEffect a new shader is returned. // Otherwise it returns the input shader. sk_sp<SkShader> createRuntimeEffectShader(sk_sp<SkShader> shader, const LayerSettings& layer, const DisplaySettings& display, bool undoPremultipliedAlpha, bool requiresLinearEffect); struct RuntimeEffectShaderParameters { sk_sp<SkShader> shader; const LayerSettings& layer; const DisplaySettings& display; bool undoPremultipliedAlpha; bool requiresLinearEffect; float layerDimmingRatio; }; sk_sp<SkShader> createRuntimeEffectShader(const RuntimeEffectShaderParameters&); EGLDisplay mEGLDisplay; EGLContext mEGLContext; Loading
libs/renderengine/tests/RenderEngineTest.cpp +142 −0 Original line number Diff line number Diff line Loading @@ -208,6 +208,21 @@ public: renderengine::ExternalTexture::Usage::WRITEABLE); } std::shared_ptr<renderengine::ExternalTexture> allocateAndFillSourceBuffer(uint32_t width, uint32_t height, ubyte4 color) { const auto buffer = allocateSourceBuffer(width, height); 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; buffer->getBuffer()->unlock(); return buffer; } RenderEngineTest() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); Loading Loading @@ -2195,6 +2210,133 @@ TEST_P(RenderEngineTest, testDisableBlendingBuffer) { expectBufferColor(rect, 0, 128, 0, 128); } TEST_P(RenderEngineTest, testDimming) { if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) { return; } initializeRenderEngine(); const auto displayRect = Rect(3, 1); const renderengine::DisplaySettings display{ .physicalDisplay = displayRect, .clip = displayRect, .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, .targetLuminanceNits = 1000.f, }; const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255)); const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255)); const auto redBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(255, 0, 0, 255)); const renderengine::LayerSettings greenLayer{ .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = greenBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 200.f, }; const renderengine::LayerSettings blueLayer{ .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = blueBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 1000.f / 51.f, }; const renderengine::LayerSettings redLayer{ .geometry.boundaries = FloatRect(2.f, 0.f, 3.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = redBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, // When the white point is not set for a layer, just ignore it and treat it as the same // as the max layer .whitePointNits = -1.f, }; std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer, redLayer}; invokeDraw(display, layers); expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1); expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 5, 255, 1); expectBufferColor(Rect(2, 0, 3, 1), 51, 0, 0, 255, 1); } TEST_P(RenderEngineTest, testDimming_withoutTargetLuminance) { initializeRenderEngine(); if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) { return; } const auto displayRect = Rect(2, 1); const renderengine::DisplaySettings display{ .physicalDisplay = displayRect, .clip = displayRect, .outputDataspace = ui::Dataspace::V0_SRGB_LINEAR, .targetLuminanceNits = -1.f, }; const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255)); const auto blueBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 0, 255, 255)); const renderengine::LayerSettings greenLayer{ .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = greenBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 200.f, }; const renderengine::LayerSettings blueLayer{ .geometry.boundaries = FloatRect(1.f, 0.f, 2.f, 1.f), .source = renderengine::PixelSource{ .buffer = renderengine::Buffer{ .buffer = blueBuffer, .usePremultipliedAlpha = true, }, }, .alpha = 1.0f, .sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR, .whitePointNits = 1000.f, }; std::vector<renderengine::LayerSettings> layers{greenLayer, blueLayer}; invokeDraw(display, layers); expectBufferColor(Rect(1, 1), 0, 51, 0, 255, 1); expectBufferColor(Rect(1, 0, 2, 1), 0, 0, 255, 255); } TEST_P(RenderEngineTest, test_isOpaque) { initializeRenderEngine(); Loading