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 /** 18 * Coordinates available to GrProcessor subclasses for requesting transformations. Transformed 19 * coordinates are made available in the the portion of fragment shader emitted by the effect. 20 * 21 * The precision of the shader var that interpolates the transformed coordinates can be specified. 22 */ 23 enum GrCoordSet { 24 /** 25 * The user-space coordinates that map to the fragment being rendered. This is the space in 26 * which SkShader operates. It is usually the space in which geometry passed to SkCanvas is 27 * specified (before the view matrix is applied). However, some draw calls take explicit local 28 * coords that map onto the geometry (e.g. drawVertices, drawBitmapRectToRect). 29 */ 30 kLocal_GrCoordSet, 31 32 /** 33 * The device space position of the fragment being shaded. 34 */ 35 kDevice_GrCoordSet, 36 }; 37 38 /** 39 * A class representing a linear transformation from one of the built-in coordinate sets (local or 40 * position). GrProcessors just define these transformations, and the framework does the rest of the 41 * work to make the transformed coordinates available in their fragment shader. 42 */ 43 class GrCoordTransform : SkNoncopyable { 44 public: GrCoordTransform()45 GrCoordTransform() : fSourceCoords(kLocal_GrCoordSet) { SkDEBUGCODE(fInProcessor = false); } 46 47 /** 48 * Create a transformation that maps [0, 1] to a texture's boundaries. The precision is inferred 49 * from the texture size and filter. The texture origin also implies whether a y-reversal should 50 * be performed. 51 */ GrCoordTransform(GrCoordSet sourceCoords,const GrTexture * texture,GrTextureParams::FilterMode filter)52 GrCoordTransform(GrCoordSet sourceCoords, 53 const GrTexture* texture, 54 GrTextureParams::FilterMode filter) { 55 SkASSERT(texture); 56 SkDEBUGCODE(fInProcessor = false); 57 this->reset(sourceCoords, texture, filter); 58 } 59 60 /** 61 * Create a transformation from a matrix. The precision is inferred from the texture size and 62 * filter. The texture origin also implies whether a y-reversal should be performed. 63 */ GrCoordTransform(GrCoordSet sourceCoords,const SkMatrix & m,const GrTexture * texture,GrTextureParams::FilterMode filter)64 GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, 65 const GrTexture* texture, GrTextureParams::FilterMode filter) { 66 SkDEBUGCODE(fInProcessor = false); 67 SkASSERT(texture); 68 this->reset(sourceCoords, m, texture, filter); 69 } 70 71 /** 72 * Create a transformation that applies the matrix to a coord set. 73 */ 74 GrCoordTransform(GrCoordSet sourceCoords, const SkMatrix& m, 75 GrSLPrecision precision = kDefault_GrSLPrecision) { 76 SkDEBUGCODE(fInProcessor = false); 77 this->reset(sourceCoords, m, precision); 78 } 79 reset(GrCoordSet sourceCoords,const GrTexture * texture,GrTextureParams::FilterMode filter)80 void reset(GrCoordSet sourceCoords, const GrTexture* texture, 81 GrTextureParams::FilterMode filter) { 82 SkASSERT(!fInProcessor); 83 SkASSERT(texture); 84 this->reset(sourceCoords, MakeDivByTextureWHMatrix(texture), texture, filter); 85 } 86 87 void reset(GrCoordSet, const SkMatrix&, const GrTexture*, GrTextureParams::FilterMode filter); 88 void reset(GrCoordSet sourceCoords, const SkMatrix& m, 89 GrSLPrecision precision = kDefault_GrSLPrecision); 90 91 GrCoordTransform& operator= (const GrCoordTransform& that) { 92 SkASSERT(!fInProcessor); 93 fSourceCoords = that.fSourceCoords; 94 fMatrix = that.fMatrix; 95 fReverseY = that.fReverseY; 96 fPrecision = that.fPrecision; 97 return *this; 98 } 99 100 /** 101 * Access the matrix for editing. Note, this must be done before adding the transform to an 102 * effect, since effects are immutable. 103 */ accessMatrix()104 SkMatrix* accessMatrix() { 105 SkASSERT(!fInProcessor); 106 return &fMatrix; 107 } 108 109 bool operator==(const GrCoordTransform& that) const { 110 return fSourceCoords == that.fSourceCoords && 111 fMatrix.cheapEqualTo(that.fMatrix) && 112 fReverseY == that.fReverseY && 113 fPrecision == that.fPrecision; 114 } 115 116 bool operator!=(const GrCoordTransform& that) const { return !(*this == that); } 117 sourceCoords()118 GrCoordSet sourceCoords() const { return fSourceCoords; } getMatrix()119 const SkMatrix& getMatrix() const { return fMatrix; } reverseY()120 bool reverseY() const { return fReverseY; } precision()121 GrSLPrecision precision() const { return fPrecision; } 122 123 /** Useful for effects that want to insert a texture matrix that is implied by the texture 124 dimensions */ MakeDivByTextureWHMatrix(const GrTexture * texture)125 static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) { 126 SkASSERT(texture); 127 SkMatrix mat; 128 (void)mat.setIDiv(texture->width(), texture->height()); 129 return mat; 130 } 131 132 private: 133 GrCoordSet fSourceCoords; 134 SkMatrix fMatrix; 135 bool fReverseY; 136 GrSLPrecision fPrecision; 137 typedef SkNoncopyable INHERITED; 138 139 #ifdef SK_DEBUG 140 public: setInProcessor()141 void setInProcessor() const { fInProcessor = true; } 142 private: 143 mutable bool fInProcessor; 144 #endif 145 }; 146 147 #endif 148