Tonemap everywhere in PixelCopy
* Hookup tonemap support for PixelCopying a SurfaceView
* Fix issue in PixelCopying a SurfaceView where the wrong dataspace was
retrieved from the last queued buffer, since the bufferqueue dataspace
may drift due to another process like camera setting the dataspace
without being propagated to the app process
* Cleanup LayerDrawable to share code
Bug: 238395777
Test: Switching HDR cameras doesn't color shift
Test: TextureView playback in Photos
Change-Id: I0fd1bd86410630acfbb7de72339874a3d0ecac58
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 3ba5409..99f54c1 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -25,6 +25,7 @@
#include "SkColorFilter.h"
#include "SkRuntimeEffect.h"
#include "SkSurface.h"
+#include "Tonemapper.h"
#include "gl/GrGLTypes.h"
#include "math/mat4.h"
#include "system/graphics-base-v1.0.h"
@@ -76,37 +77,6 @@
isIntegerAligned(dstDevRect.y()));
}
-static sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader,
- const shaders::LinearEffect& linearEffect,
- float maxDisplayLuminance,
- float currentDisplayLuminanceNits,
- float maxLuminance) {
- auto shaderString = SkString(shaders::buildLinearEffectSkSL(linearEffect));
- auto [runtimeEffect, error] = SkRuntimeEffect::MakeForShader(std::move(shaderString));
- if (!runtimeEffect) {
- LOG_ALWAYS_FATAL("LinearColorFilter construction error: %s", error.c_str());
- }
-
- SkRuntimeShaderBuilder effectBuilder(std::move(runtimeEffect));
-
- effectBuilder.child("child") = std::move(shader);
-
- const auto uniforms = shaders::buildLinearEffectUniforms(
- linearEffect, mat4(), maxDisplayLuminance, currentDisplayLuminanceNits, maxLuminance);
-
- for (const auto& uniform : uniforms) {
- effectBuilder.uniform(uniform.name.c_str()).set(uniform.value.data(), uniform.value.size());
- }
-
- return effectBuilder.makeShader();
-}
-
-static bool isHdrDataspace(ui::Dataspace dataspace) {
- const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
-
- return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
-}
-
static void adjustCropForYUV(uint32_t format, int bufferWidth, int bufferHeight, SkRect* cropRect) {
// Chroma channels of YUV420 images are subsampled we may need to shrink the crop region by
// a whole texel on each side. Since skia still adds its own 0.5 inset, we apply an
@@ -215,31 +185,10 @@
sampling = SkSamplingOptions(SkFilterMode::kLinear);
}
- const auto sourceDataspace = static_cast<ui::Dataspace>(
- ColorSpaceToADataSpace(layerImage->colorSpace(), layerImage->colorType()));
- const SkImageInfo& imageInfo = canvas->imageInfo();
- const auto destinationDataspace = static_cast<ui::Dataspace>(
- ColorSpaceToADataSpace(imageInfo.colorSpace(), imageInfo.colorType()));
-
- if (isHdrDataspace(sourceDataspace) || isHdrDataspace(destinationDataspace)) {
- const auto effect = shaders::LinearEffect{
- .inputDataspace = sourceDataspace,
- .outputDataspace = destinationDataspace,
- .undoPremultipliedAlpha = layerImage->alphaType() == kPremul_SkAlphaType,
- .fakeInputDataspace = destinationDataspace};
- auto shader = layerImage->makeShader(sampling,
- SkMatrix::RectToRect(skiaSrcRect, skiaDestRect));
- constexpr float kMaxDisplayBrightess = 1000.f;
- constexpr float kCurrentDisplayBrightness = 500.f;
- shader = createLinearEffectShader(std::move(shader), effect, kMaxDisplayBrightess,
- kCurrentDisplayBrightness,
- layer->getMaxLuminanceNits());
- paint.setShader(shader);
- canvas->drawRect(skiaDestRect, paint);
- } else {
- canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
- constraint);
- }
+ tonemapPaint(layerImage->imageInfo(), canvas->imageInfo(), layer->getMaxLuminanceNits(),
+ paint);
+ canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
+ constraint);
canvas->restore();
// restore the original matrix