1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrColorSpaceXform_DEFINED
9#define GrColorSpaceXform_DEFINED
10
11#include "GrColor.h"
12#include "GrFragmentProcessor.h"
13#include "SkColorSpace.h"
14#include "SkMatrix44.h"
15#include "SkRefCnt.h"
16
17 /**
18  * Represents a color space transformation
19  */
20class GrColorSpaceXform : public SkRefCnt {
21public:
22    GrColorSpaceXform(const SkColorSpaceTransferFn&, const SkMatrix44&, uint32_t);
23
24    static sk_sp<GrColorSpaceXform> Make(const SkColorSpace* src,
25                                         GrPixelConfig srcConfig,
26                                         const SkColorSpace* dst);
27    static sk_sp<GrColorSpaceXform> MakeGamutXform(const SkColorSpace* src,
28                                                   const SkColorSpace* dst) {
29        auto result = Make(src, kUnknown_GrPixelConfig, dst);
30        SkASSERT(!result || 0 == (result->fFlags & ~kApplyGamutXform_Flag));
31        return result;
32    }
33
34    const SkColorSpaceTransferFn& transferFn() const { return fSrcTransferFn; }
35    const float* transferFnCoeffs() const {
36        static_assert(0 == offsetof(SkColorSpaceTransferFn, fG), "TransferFn layout");
37        return &fSrcTransferFn.fG;
38    }
39
40    const SkMatrix44& gamutXform() const { return fGamutXform; }
41
42    /**
43     * GrGLSLFragmentProcessor::GenKey() must call this and include the returned value in its
44     * computed key.
45     */
46    static uint32_t XformKey(const GrColorSpaceXform* xform) {
47        // Code generation depends on which steps we apply (as encoded by fFlags)
48        return SkToBool(xform) ? xform->fFlags : 0;
49    }
50
51    static bool Equals(const GrColorSpaceXform* a, const GrColorSpaceXform* b);
52
53    GrColor4f unclampedXform(const GrColor4f& srcColor);
54    GrColor4f clampedXform(const GrColor4f& srcColor);
55
56private:
57    friend class GrGLSLColorSpaceXformHelper;
58
59    enum Flags {
60        kApplyTransferFn_Flag = 0x1,
61        kApplyGamutXform_Flag = 0x2,
62
63        // Almost never used. This handles the case where the src data is sRGB pixel config,
64        // but the color space has a different transfer function. In that case, we first undo
65        // the HW sRGB -> Linear conversion, before applying any other steps.
66        kApplyInverseSRGB_Flag = 0x4,
67    };
68
69    SkColorSpaceTransferFn fSrcTransferFn;
70    SkMatrix44 fGamutXform;
71    uint32_t fFlags;
72};
73
74class GrColorSpaceXformEffect : public GrFragmentProcessor {
75public:
76    /**
77     *  Returns a fragment processor that calls the passed in fragment processor, and then converts
78     *  the color space of the output from src to dst.
79     */
80    static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child,
81                                                     const SkColorSpace* src,
82                                                     GrPixelConfig srcConfig,
83                                                     const SkColorSpace* dst);
84
85    const char* name() const override { return "ColorSpaceXform"; }
86    std::unique_ptr<GrFragmentProcessor> clone() const override;
87
88    const GrColorSpaceXform* colorXform() const { return fColorXform.get(); }
89
90private:
91    GrColorSpaceXformEffect(std::unique_ptr<GrFragmentProcessor> child,
92                            sk_sp<GrColorSpaceXform> colorXform);
93
94    static OptimizationFlags OptFlags(const GrFragmentProcessor* child);
95
96    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
97    void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
98    bool onIsEqual(const GrFragmentProcessor&) const override;
99
100    sk_sp<GrColorSpaceXform> fColorXform;
101
102    typedef GrFragmentProcessor INHERITED;
103};
104
105#endif
106