154f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman/* 254f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman * Copyright 2016 Google Inc. 354f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman * 454f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman * Use of this source code is governed by a BSD-style license that can be 554f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman * found in the LICENSE file. 654f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman */ 754f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 854f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman#ifndef GrColorSpaceXform_DEFINED 954f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman#define GrColorSpaceXform_DEFINED 1054f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 115a7ae7e337a68dc42723fce80752c93b7d26d469brianosman#include "GrColor.h" 12c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman#include "GrFragmentProcessor.h" 13f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman#include "SkColorSpace.h" 145192475bd8cb98e8e0c1192ab5ece7b8595701d6brianosman#include "SkMatrix44.h" 1554f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman#include "SkRefCnt.h" 1654f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 1754f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman /** 18f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman * Represents a color space transformation 1954f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman */ 2054f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosmanclass GrColorSpaceXform : public SkRefCnt { 2154f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosmanpublic: 22f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman GrColorSpaceXform(const SkColorSpaceTransferFn&, const SkMatrix44&, uint32_t); 23f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman 24f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman static sk_sp<GrColorSpaceXform> Make(const SkColorSpace* src, 25f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman GrPixelConfig srcConfig, 26f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman const SkColorSpace* dst); 27f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman static sk_sp<GrColorSpaceXform> MakeGamutXform(const SkColorSpace* src, 28f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman const SkColorSpace* dst) { 29f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman auto result = Make(src, kUnknown_GrPixelConfig, dst); 30f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman SkASSERT(!result || 0 == (result->fFlags & ~kApplyGamutXform_Flag)); 31f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman return result; 32f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman } 3354f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 34f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman const SkColorSpaceTransferFn& transferFn() const { return fSrcTransferFn; } 35f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman const float* transferFnCoeffs() const { 36f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman static_assert(0 == offsetof(SkColorSpaceTransferFn, fG), "TransferFn layout"); 37f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman return &fSrcTransferFn.fG; 38f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman } 3954f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 40f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman const SkMatrix44& gamutXform() const { return fGamutXform; } 4177320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman 4277320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman /** 4377320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in its 4477320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman * computed key. 4577320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman */ 46e411a077ec2cc018351d92e668def5da6905e4ecBrian Osman static uint32_t XformKey(const GrColorSpaceXform* xform) { 47f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman // Code generation depends on which steps we apply (as encoded by fFlags) 48f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman return SkToBool(xform) ? xform->fFlags : 0; 4977320dbabcddf05c0a1489eaf1f496729dc8de0ebrianosman } 5054f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 51b9c5137a1cedbe8a3641db0b7c081881a2d5d58cbrianosman static bool Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b); 52b9c5137a1cedbe8a3641db0b7c081881a2d5d58cbrianosman 53fe3e858e751609c3a9cbf7ad710ed415ea7213fcBrian Osman GrColor4f unclampedXform(const GrColor4f& srcColor); 54fe3e858e751609c3a9cbf7ad710ed415ea7213fcBrian Osman GrColor4f clampedXform(const GrColor4f& srcColor); 555a7ae7e337a68dc42723fce80752c93b7d26d469brianosman 5654f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosmanprivate: 57f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman friend class GrGLSLColorSpaceXformHelper; 58f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman 59f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman enum Flags { 60f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman kApplyTransferFn_Flag = 0x1, 61f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman kApplyGamutXform_Flag = 0x2, 62f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman 63f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman // Almost never used. This handles the case where the src data is sRGB pixel config, 64f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman // but the color space has a different transfer function. In that case, we first undo 65f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman // the HW sRGB -> Linear conversion, before applying any other steps. 66f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman kApplyInverseSRGB_Flag = 0x4, 67f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman }; 68f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman 69f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman SkColorSpaceTransferFn fSrcTransferFn; 70f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman SkMatrix44 fGamutXform; 71f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman uint32_t fFlags; 7254f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman}; 7354f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman 74c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osmanclass GrColorSpaceXformEffect : public GrFragmentProcessor { 75c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osmanpublic: 76c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman /** 77c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman * Returns a fragment processor that calls the passed in fragment processor, and then converts 78c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman * the color space of the output from src to dst. 79c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman */ 80c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child, 81c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman const SkColorSpace* src, 82f06ead925c631c42fae734de1e7c72237a2e91f4Brian Osman GrPixelConfig srcConfig, 83c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman const SkColorSpace* dst); 84c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 85c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman const char* name() const override { return "ColorSpaceXform"; } 86c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman std::unique_ptr<GrFragmentProcessor> clone() const override; 87c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 88c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman const GrColorSpaceXform* colorXform() const { return fColorXform.get(); } 89c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 90c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osmanprivate: 91c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child, 92c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman sk_sp<GrColorSpaceXform> colorXform); 93c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 94c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman static OptimizationFlags OptFlags(const GrFragmentProcessor* child); 95c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 96c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman GrGLSLFragmentProcessor* onCreateGLSLInstance() const override; 97c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override; 98c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman bool onIsEqual(const GrFragmentProcessor&) const override; 99c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 100c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman sk_sp<GrColorSpaceXform> fColorXform; 101c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 102c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman typedef GrFragmentProcessor INHERITED; 103c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman}; 104c4f93cab667b022bbaa196bddcbca23592ad2e6cBrian Osman 10554f30c13fc0a5d89797fc9be5f0fb1050d96b6f4brianosman#endif 106