[graphite] Apply colorSpace to the SkPaint's color

Bug: b/239959460
Change-Id: Iee9ab67f813f5f863e255b189c2a2b6f1219faf5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/638977
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: James Godfrey-Kittle <jamesgk@google.com>
diff --git a/src/gpu/graphite/Device.cpp b/src/gpu/graphite/Device.cpp
index 02aee14..16f7ccf 100644
--- a/src/gpu/graphite/Device.cpp
+++ b/src/gpu/graphite/Device.cpp
@@ -105,16 +105,20 @@
 }
 
 /** If the paint can be reduced to a solid flood-fill, determine the correct color to fill with. */
-std::optional<SkColor4f> extract_paint_color(const SkPaint& paint) {
+std::optional<SkColor4f> extract_paint_color(const SkPaint& paint,
+                                             const SkColorInfo& dstColorInfo) {
     SkASSERT(!paint_depends_on_dst(paint));
     if (paint.getShader()) {
         return std::nullopt;
     }
+
+    SkColor4f dstPaintColor = PaintParams::Color4fPrepForDst(paint.getColor4f(), dstColorInfo);
+
     if (SkColorFilter* filter = paint.getColorFilter()) {
-        // TODO: SkColorSpace support
-        return filter->filterColor4f(paint.getColor4f(), sk_srgb_singleton(), sk_srgb_singleton());
+        SkColorSpace* dstCS = dstColorInfo.colorSpace();
+        return filter->filterColor4f(dstPaintColor, dstCS, dstCS);
     }
-    return paint.getColor4f();
+    return dstPaintColor;
 }
 
 SkIRect rect_to_pixelbounds(const Rect& r) {
@@ -601,7 +605,7 @@
     // entire final surface.
     if (this->clipIsWideOpen() && !fDC->target()->isFullyLazy()) {
         if (!paint_depends_on_dst(paint)) {
-            if (std::optional<SkColor4f> color = extract_paint_color(paint)) {
+            if (std::optional<SkColor4f> color = extract_paint_color(paint, fDC->colorInfo())) {
                 // do fullscreen clear
                 fDC->clear(*color);
                 return;
diff --git a/src/gpu/graphite/DrawContext.h b/src/gpu/graphite/DrawContext.h
index fed052a..dfc5292 100644
--- a/src/gpu/graphite/DrawContext.h
+++ b/src/gpu/graphite/DrawContext.h
@@ -55,7 +55,8 @@
 
     ~DrawContext() override;
 
-    const SkImageInfo&  imageInfo() const { return fImageInfo;    }
+    const SkImageInfo& imageInfo() const { return fImageInfo;    }
+    const SkColorInfo& colorInfo() const { return fImageInfo.colorInfo(); }
     TextureProxy* target()                { return fTarget.get(); }
     const TextureProxy* target()    const { return fTarget.get(); }
 
diff --git a/src/gpu/graphite/PaintParams.cpp b/src/gpu/graphite/PaintParams.cpp
index 2a59a96..8c79372 100644
--- a/src/gpu/graphite/PaintParams.cpp
+++ b/src/gpu/graphite/PaintParams.cpp
@@ -11,6 +11,7 @@
 #include "include/core/SkShader.h"
 #include "src/core/SkBlenderBase.h"
 #include "src/core/SkColorFilterBase.h"
+#include "src/core/SkColorSpacePriv.h"
 #include "src/gpu/graphite/KeyContext.h"
 #include "src/gpu/graphite/KeyHelpers.h"
 #include "src/gpu/graphite/PaintParamsKey.h"
@@ -60,13 +61,25 @@
 
 sk_sp<SkBlender> PaintParams::refPrimitiveBlender() const { return fPrimitiveBlender; }
 
+SkColor4f PaintParams::Color4fPrepForDst(SkColor4f srcColor, const SkColorInfo& dstColorInfo) {
+    // xform from sRGB to the destination colorspace
+    SkColorSpaceXformSteps steps(sk_srgb_singleton(),       kUnpremul_SkAlphaType,
+                                 dstColorInfo.colorSpace(), kUnpremul_SkAlphaType);
+
+    SkColor4f result = srcColor;
+    steps.apply(result.vec());
+    return result;
+}
+
 void PaintParams::toKey(const KeyContext& keyContext,
                         PaintParamsKeyBuilder* builder,
                         PipelineDataGatherer* gatherer) const {
 
+    SkColor4f dstPaintColor = Color4fPrepForDst(fColor, keyContext.dstColorInfo());
+
     // TODO: figure out how we can omit this block when the Paint's color isn't used.
     SolidColorShaderBlock::BeginBlock(keyContext, builder, gatherer,
-                                      fColor.makeOpaque().premul());
+                                      dstPaintColor.makeOpaque().premul());
     builder->endBlock();
 
     if (fShader) {
@@ -79,8 +92,8 @@
     }
 
     // Apply the paint's alpha value.
-    auto alphaColorFilter = SkColorFilters::Blend({0, 0, 0, fColor[3]},
-                                                  /*colorSpace*/nullptr,
+    auto alphaColorFilter = SkColorFilters::Blend({0, 0, 0, fColor.fA},
+                                                  /* colorSpace= */ nullptr,
                                                   SkBlendMode::kDstIn);
     if (alphaColorFilter) {
         as_CFB(alphaColorFilter)->addToKey(keyContext, builder, gatherer);
@@ -92,7 +105,7 @@
 
     if (fFinalBlender) {
         as_BB(fFinalBlender)->addToKey(keyContext, builder, gatherer,
-                                       /* primitiveColorBlender= */false);
+                                       /* primitiveColorBlender= */ false);
     } else {
         BlendModeBlock::BeginBlock(keyContext, builder, gatherer, SkBlendMode::kSrcOver);
         builder->endBlock();
diff --git a/src/gpu/graphite/PaintParams.h b/src/gpu/graphite/PaintParams.h
index 1d16f41..d0f5b89 100644
--- a/src/gpu/graphite/PaintParams.h
+++ b/src/gpu/graphite/PaintParams.h
@@ -11,6 +11,7 @@
 #include "include/core/SkColor.h"
 #include "include/core/SkPaint.h"
 
+class SkColorInfo;
 class SkShader;
 
 namespace skgpu::graphite {
@@ -59,6 +60,9 @@
 
     bool skipColorXform() const { return fSkipColorXform; }
 
+    /** Converts an SkColor4f to the destination color space. */
+    static SkColor4f Color4fPrepForDst(SkColor4f srgb, const SkColorInfo& dstColorInfo);
+
     void toKey(const KeyContext&,
                PaintParamsKeyBuilder*,
                PipelineDataGatherer*) const;