1 /*
2  * Copyright 2013 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 GrCoordTransform_DEFINED
9 #define GrCoordTransform_DEFINED
10 
11 #include "GrProcessor.h"
12 #include "SkMatrix.h"
13 #include "GrTexture.h"
14 #include "GrTypes.h"
15 #include "GrShaderVar.h"
16 
17 class GrTextureProxy;
18 
19 /**
20  * A class representing a linear transformation of local coordinates. GrFragnentProcessors
21  * these transformations, and the GrGeometryProcessor implements the transformation.
22  */
23 class GrCoordTransform : SkNoncopyable {
24 public:
GrCoordTransform()25     GrCoordTransform()
26         : fTexture(nullptr)
27         , fNormalize(false)
28         , fReverseY(false)
29         , fPrecision(kDefault_GrSLPrecision) {
30         SkDEBUGCODE(fInProcessor = false);
31     }
32 
33     /**
34      * Create a transformation that maps [0, 1] to a texture's boundaries. The precision is inferred
35      * from the texture size and filter. The texture origin also implies whether a y-reversal should
36      * be performed.
37      */
GrCoordTransform(const GrTexture * texture,GrSamplerParams::FilterMode filter)38     GrCoordTransform(const GrTexture* texture, GrSamplerParams::FilterMode filter) {
39         SkASSERT(texture);
40         SkDEBUGCODE(fInProcessor = false);
41         this->reset(SkMatrix::I(), texture, filter);
42     }
43 
GrCoordTransform(GrResourceProvider * resourceProvider,GrTextureProxy * proxy,GrSamplerParams::FilterMode filter)44     GrCoordTransform(GrResourceProvider* resourceProvider, GrTextureProxy* proxy,
45                      GrSamplerParams::FilterMode filter) {
46         SkASSERT(proxy);
47         SkDEBUGCODE(fInProcessor = false);
48         this->reset(resourceProvider, SkMatrix::I(), proxy, filter);
49     }
50 
51     /**
52      * Create a transformation from a matrix. The precision is inferred from the texture size and
53      * filter. The texture origin also implies whether a y-reversal should be performed.
54      */
GrCoordTransform(const SkMatrix & m,const GrTexture * texture,GrSamplerParams::FilterMode filter)55     GrCoordTransform(const SkMatrix& m, const GrTexture* texture,
56                      GrSamplerParams::FilterMode filter) {
57         SkASSERT(texture);
58         SkDEBUGCODE(fInProcessor = false);
59         this->reset(m, texture, filter);
60     }
61 
GrCoordTransform(GrResourceProvider * resourceProvider,const SkMatrix & m,GrTextureProxy * proxy,GrSamplerParams::FilterMode filter)62     GrCoordTransform(GrResourceProvider* resourceProvider, const SkMatrix& m,
63                      GrTextureProxy* proxy, GrSamplerParams::FilterMode filter) {
64         SkASSERT(proxy);
65         SkDEBUGCODE(fInProcessor = false);
66         this->reset(resourceProvider, m, proxy, filter);
67     }
68 
69     /**
70      * Create a transformation that applies the matrix to a coord set.
71      */
72     GrCoordTransform(const SkMatrix& m, GrSLPrecision precision = kDefault_GrSLPrecision) {
73         SkDEBUGCODE(fInProcessor = false);
74         this->reset(m, precision);
75     }
76 
77     // MDB TODO: rm the GrTexture* flavor of reset
78     void reset(const SkMatrix&, const GrTexture*, GrSamplerParams::FilterMode filter,
79                bool normalize = true);
80 
81     void reset(GrResourceProvider*, const SkMatrix&, GrTextureProxy*,
82                GrSamplerParams::FilterMode filter, bool normalize = true);
83 
84     void reset(const SkMatrix& m, GrSLPrecision precision = kDefault_GrSLPrecision) {
85         SkASSERT(!fInProcessor);
86         fMatrix = m;
87         fTexture = nullptr;
88         fNormalize = false;
89         fReverseY = false;
90         fPrecision = precision;
91     }
92 
93     GrCoordTransform& operator= (const GrCoordTransform& that) {
94         SkASSERT(!fInProcessor);
95         fMatrix = that.fMatrix;
96         fTexture = that.fTexture;
97         fNormalize = that.fNormalize;
98         fReverseY = that.fReverseY;
99         fPrecision = that.fPrecision;
100         return *this;
101     }
102 
103     /**
104      * Access the matrix for editing. Note, this must be done before adding the transform to an
105      * effect, since effects are immutable.
106      */
accessMatrix()107     SkMatrix* accessMatrix() {
108         SkASSERT(!fInProcessor);
109         return &fMatrix;
110     }
111 
hasSameEffectAs(const GrCoordTransform & that)112     bool hasSameEffectAs(const GrCoordTransform& that) const {
113         if (fNormalize != that.fNormalize ||
114             fReverseY != that.fReverseY ||
115             fPrecision != that.fPrecision ||
116             !fMatrix.cheapEqualTo(that.fMatrix)) {
117             return false;
118         }
119 
120         if (fNormalize) {
121             SkASSERT(fTexture && that.fTexture);
122             return fTexture->width() == that.fTexture->width() &&
123                    fTexture->height() == that.fTexture->height();
124         }
125 
126         return true;
127     }
128 
getMatrix()129     const SkMatrix& getMatrix() const { return fMatrix; }
texture()130     const GrTexture* texture() const { return fTexture; }
normalize()131     bool normalize() const { return fNormalize; }
reverseY()132     bool reverseY() const { return fReverseY; }
precision()133     GrSLPrecision precision() const { return fPrecision; }
134 
135 private:
136     // The textures' effect is to optionally normalize the final matrix, so a blind
137     // equality check could be misleading
138     bool operator==(const GrCoordTransform& that) const;
139     bool operator!=(const GrCoordTransform& that) const;
140 
141     SkMatrix                fMatrix;
142     const GrTexture*        fTexture;
143     bool                    fNormalize;
144     bool                    fReverseY;
145     GrSLPrecision           fPrecision;
146     typedef SkNoncopyable INHERITED;
147 
148 #ifdef SK_DEBUG
149 public:
setInProcessor()150     void setInProcessor() const { fInProcessor = true; }
151 private:
152     mutable bool fInProcessor;
153 #endif
154 };
155 
156 #endif
157