Merge "Support linear color transforms in Skia-RenderEngine."
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 74f342a..a0660fb 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -416,6 +416,11 @@
             sourceTransfer != destTransfer;
 }
 
+static bool needsLinearEffect(const mat4& colorTransform, ui::Dataspace sourceDataspace,
+                              ui::Dataspace destinationDataspace) {
+    return colorTransform != mat4() || needsToneMapping(sourceDataspace, destinationDataspace);
+}
+
 void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
     std::lock_guard<std::mutex> lock(mRenderingMutex);
     mTextureCache.erase(bufferId);
@@ -559,11 +564,13 @@
                                                                    false));
                 mTextureCache.insert({buffer->getId(), imageTextureRef});
             }
+
             sk_sp<SkImage> image =
                     imageTextureRef->getTexture()
                             ->makeImage(mUseColorManagement
-                                                ? (needsToneMapping(layer->sourceDataspace,
-                                                                    display.outputDataspace)
+                                                ? (needsLinearEffect(layer->colorTransform,
+                                                                     layer->sourceDataspace,
+                                                                     display.outputDataspace)
                                                            // If we need to map to linear space,
                                                            // then mark the source image with the
                                                            // same colorspace as the destination
@@ -633,7 +640,8 @@
             }
 
             if (mUseColorManagement &&
-                needsToneMapping(layer->sourceDataspace, display.outputDataspace)) {
+                needsLinearEffect(layer->colorTransform, layer->sourceDataspace,
+                                  display.outputDataspace)) {
                 LinearEffect effect = LinearEffect{.inputDataspace = layer->sourceDataspace,
                                                    .outputDataspace = display.outputDataspace,
                                                    .undoPremultipliedAlpha = !item.isOpaque &&
@@ -649,6 +657,7 @@
                 }
 
                 paint.setShader(createLinearEffectShader(shader, effect, runtimeEffect,
+                                                         layer->colorTransform,
                                                          display.maxLuminance,
                                                          layer->source.buffer.maxMasteringLuminance,
                                                          layer->source.buffer.maxContentLuminance));
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index b3d5d63..7680649 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -447,8 +447,8 @@
 
 sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader, const LinearEffect& linearEffect,
                                          sk_sp<SkRuntimeEffect> runtimeEffect,
-                                         float maxDisplayLuminance, float maxMasteringLuminance,
-                                         float maxContentLuminance) {
+                                         const mat4& colorTransform, float maxDisplayLuminance,
+                                         float maxMasteringLuminance, float maxContentLuminance) {
     ATRACE_CALL();
     SkRuntimeShaderBuilder effectBuilder(runtimeEffect);
 
@@ -458,7 +458,7 @@
     ColorSpace outputColorSpace = toColorSpace(linearEffect.outputDataspace);
 
     effectBuilder.uniform("in_rgbToXyz") = mat4(inputColorSpace.getRGBtoXYZ());
-    effectBuilder.uniform("in_xyzToRgb") = mat4(outputColorSpace.getXYZtoRGB());
+    effectBuilder.uniform("in_xyzToRgb") = colorTransform * mat4(outputColorSpace.getXYZtoRGB());
     effectBuilder.uniform("in_displayMaxLuminance") = maxDisplayLuminance;
     effectBuilder.uniform("in_inputMaxLuminance") =
             std::min(maxMasteringLuminance, maxContentLuminance);
diff --git a/libs/renderengine/skia/filters/LinearEffect.h b/libs/renderengine/skia/filters/LinearEffect.h
index dadba32..20b8338 100644
--- a/libs/renderengine/skia/filters/LinearEffect.h
+++ b/libs/renderengine/skia/filters/LinearEffect.h
@@ -16,9 +16,10 @@
 
 #pragma once
 
+#include <math/mat4.h>
+
 #include <optional>
 
-#include "SkColorMatrix.h"
 #include "SkRuntimeEffect.h"
 #include "SkShader.h"
 #include "ui/GraphicTypes.h"
@@ -84,8 +85,10 @@
 sk_sp<SkRuntimeEffect> buildRuntimeEffect(const LinearEffect& linearEffect);
 
 // Generates a shader resulting from applying the a linear effect created from
-// LinearEffectARgs::buildEffect to an inputShader. We also provide additional HDR metadata upon
-// creating the shader:
+// LinearEffectArgs::buildEffect to an inputShader.
+// Optionally, a color transform may also be provided, which combines with the
+// matrix transforming from linear XYZ to linear RGB immediately before OETF.
+// We also provide additional HDR metadata upon creating the shader:
 // * The max display luminance is the max luminance of the physical display in nits
 // * The max mastering luminance is provided as the max luminance from the SMPTE 2086
 // standard.
@@ -94,8 +97,8 @@
 sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> inputShader,
                                          const LinearEffect& linearEffect,
                                          sk_sp<SkRuntimeEffect> runtimeEffect,
-                                         float maxDisplayLuminance, float maxMasteringLuminance,
-                                         float maxContentLuminance);
+                                         const mat4& colorTransform, float maxDisplayLuminance,
+                                         float maxMasteringLuminance, float maxContentLuminance);
 } // namespace skia
 } // namespace renderengine
 } // namespace android