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 GrDistanceFieldGeoProc_DEFINED 9 #define GrDistanceFieldGeoProc_DEFINED 10 11 #if !defined(SK_DISABLE_SDF_TEXT) 12 13 #include "include/core/SkMatrix.h" 14 #include "include/core/SkScalar.h" 15 #include "include/core/SkSize.h" 16 #include "src/base/SkArenaAlloc.h" 17 #include "src/gpu/ganesh/GrGeometryProcessor.h" 18 #include "src/gpu/ganesh/GrProcessorUnitTest.h" 19 #include "src/gpu/ganesh/GrSamplerState.h" 20 21 #include <cstdint> 22 #include <memory> 23 24 class GrSurfaceProxyView; 25 namespace skgpu { class KeyBuilder; } 26 struct GrShaderCaps; 27 28 enum GrDistanceFieldEffectFlags { 29 kSimilarity_DistanceFieldEffectFlag = 0x001, // ctm is similarity matrix 30 kScaleOnly_DistanceFieldEffectFlag = 0x002, // ctm has only scale and translate 31 kPerspective_DistanceFieldEffectFlag = 0x004, // ctm has perspective (and positions are x,y,w) 32 kUseLCD_DistanceFieldEffectFlag = 0x008, // use lcd text 33 kBGR_DistanceFieldEffectFlag = 0x010, // lcd display has bgr order 34 kPortrait_DistanceFieldEffectFlag = 0x020, // lcd display is in portrait mode 35 kGammaCorrect_DistanceFieldEffectFlag = 0x040, // assume gamma-correct output (linear blending) 36 kAliased_DistanceFieldEffectFlag = 0x080, // monochrome output 37 kWideColor_DistanceFieldEffectFlag = 0x100, // use wide color (only for path) 38 39 kInvalid_DistanceFieldEffectFlag = 0x200, // invalid state (for initialization) 40 41 kUniformScale_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | 42 kScaleOnly_DistanceFieldEffectFlag, 43 // The subset of the flags relevant to GrDistanceFieldA8TextGeoProc 44 kNonLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | 45 kScaleOnly_DistanceFieldEffectFlag | 46 kPerspective_DistanceFieldEffectFlag | 47 kGammaCorrect_DistanceFieldEffectFlag | 48 kAliased_DistanceFieldEffectFlag, 49 // The subset of the flags relevant to GrDistanceFieldPathGeoProc 50 kPath_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | 51 kScaleOnly_DistanceFieldEffectFlag | 52 kPerspective_DistanceFieldEffectFlag | 53 kGammaCorrect_DistanceFieldEffectFlag | 54 kAliased_DistanceFieldEffectFlag | 55 kWideColor_DistanceFieldEffectFlag, 56 // The subset of the flags relevant to GrDistanceFieldLCDTextGeoProc 57 kLCD_DistanceFieldEffectMask = kSimilarity_DistanceFieldEffectFlag | 58 kScaleOnly_DistanceFieldEffectFlag | 59 kPerspective_DistanceFieldEffectFlag | 60 kUseLCD_DistanceFieldEffectFlag | 61 kBGR_DistanceFieldEffectFlag | 62 kPortrait_DistanceFieldEffectFlag | 63 kGammaCorrect_DistanceFieldEffectFlag, 64 }; 65 66 /** 67 * The output color of this effect is a modulation of the input color and a sample from a 68 * distance field texture (using a smoothed step function near 0.5). 69 * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input 70 * coords are a custom attribute. Gamma correction is handled via a texture LUT. 71 */ 72 class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor { 73 public: 74 #ifdef SK_ENABLE_SMALL_PAGE 75 inline static constexpr int kMaxTextures = 16; 76 #else 77 inline static constexpr int kMaxTextures = 4; 78 #endif 79 80 /** The local matrix should be identity if local coords are not required by the GrPipeline. */ 81 #ifdef SK_GAMMA_APPLY_TO_A8 Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,float lum,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)82 static GrGeometryProcessor* Make(SkArenaAlloc* arena, 83 const GrShaderCaps& caps, 84 const GrSurfaceProxyView* views, 85 int numActiveViews, 86 GrSamplerState params, 87 float lum, 88 uint32_t flags, 89 const SkMatrix& localMatrixIfUsesLocalCoords) { 90 return arena->make([&](void* ptr) { 91 return new (ptr) GrDistanceFieldA8TextGeoProc( 92 caps, views, numActiveViews, params, lum, flags, localMatrixIfUsesLocalCoords); 93 }); 94 } 95 #else Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)96 static GrGeometryProcessor* Make(SkArenaAlloc* arena, 97 const GrShaderCaps& caps, 98 const GrSurfaceProxyView* views, 99 int numActiveViews, 100 GrSamplerState params, 101 uint32_t flags, 102 const SkMatrix& localMatrixIfUsesLocalCoords) { 103 return arena->make([&](void* ptr) { 104 return new (ptr) GrDistanceFieldA8TextGeoProc( 105 caps, views, numActiveViews, params, flags, localMatrixIfUsesLocalCoords); 106 }); 107 } 108 #endif 109 ~GrDistanceFieldA8TextGeoProc()110 ~GrDistanceFieldA8TextGeoProc() override {} 111 name()112 const char* name() const override { return "DistanceFieldA8Text"; } 113 114 void addNewViews(const GrSurfaceProxyView* views, int numViews, GrSamplerState); 115 116 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override; 117 118 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override; 119 120 private: 121 class Impl; 122 123 GrDistanceFieldA8TextGeoProc(const GrShaderCaps& caps, 124 const GrSurfaceProxyView* views, 125 int numActiveViews, 126 GrSamplerState params, 127 #ifdef SK_GAMMA_APPLY_TO_A8 128 float distanceAdjust, 129 #endif 130 uint32_t flags, 131 const SkMatrix& localMatrix); 132 onTextureSampler(int i)133 const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; } 134 135 TextureSampler fTextureSamplers[kMaxTextures]; 136 SkISize fAtlasDimensions; // dimensions for all textures used with fTextureSamplers[]. 137 SkMatrix fLocalMatrix; 138 Attribute fInPosition; 139 Attribute fInColor; 140 Attribute fInTextureCoords; 141 uint32_t fFlags; 142 #ifdef SK_GAMMA_APPLY_TO_A8 143 float fDistanceAdjust; 144 #endif 145 146 GR_DECLARE_GEOMETRY_PROCESSOR_TEST 147 148 using INHERITED = GrGeometryProcessor; 149 }; 150 151 /** 152 * The output color of this effect is a modulation of the input color and a sample from a 153 * distance field texture (using a smoothed step function near 0.5). 154 * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input 155 * coords are a custom attribute. No gamma correct blending is applied. Used for paths only. 156 */ 157 class GrDistanceFieldPathGeoProc : public GrGeometryProcessor { 158 public: 159 #ifdef SK_ENABLE_SMALL_PAGE 160 inline static constexpr int kMaxTextures = 16; 161 #else 162 inline static constexpr int kMaxTextures = 4; 163 #endif 164 165 /** The local matrix should be identity if local coords are not required by the GrPipeline. */ Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,const SkMatrix & localMatrix,uint32_t flags)166 static GrGeometryProcessor* Make(SkArenaAlloc* arena, const GrShaderCaps& caps, 167 const GrSurfaceProxyView* views, int numActiveViews, 168 GrSamplerState params, const SkMatrix& localMatrix, 169 uint32_t flags) { 170 return arena->make([&](void* ptr) { 171 return new (ptr) GrDistanceFieldPathGeoProc(caps, views, numActiveViews, 172 params, localMatrix, flags); 173 }); 174 } 175 ~GrDistanceFieldPathGeoProc()176 ~GrDistanceFieldPathGeoProc() override {} 177 name()178 const char* name() const override { return "DistanceFieldPath"; } 179 180 void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState); 181 182 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override; 183 184 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override; 185 186 private: 187 class Impl; 188 189 GrDistanceFieldPathGeoProc(const GrShaderCaps& caps, 190 const GrSurfaceProxyView* views, 191 int numActiveViews, 192 GrSamplerState, 193 const SkMatrix& localMatrix, 194 uint32_t flags); 195 onTextureSampler(int i)196 const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; } 197 198 SkMatrix fLocalMatrix; 199 TextureSampler fTextureSamplers[kMaxTextures]; 200 SkISize fAtlasDimensions; // dimensions for all textures used with fTextureSamplers[]. 201 Attribute fInPosition; 202 Attribute fInColor; 203 Attribute fInTextureCoords; 204 uint32_t fFlags; 205 206 GR_DECLARE_GEOMETRY_PROCESSOR_TEST 207 208 using INHERITED = GrGeometryProcessor; 209 }; 210 211 /** 212 * The output color of this effect is a modulation of the input color and samples from a 213 * distance field texture (using a smoothed step function near 0.5), adjusted for LCD displays. 214 * It allows explicit specification of the filtering and wrap modes (GrSamplerState). The input 215 * coords are a custom attribute. Gamma correction is handled via a texture LUT. 216 */ 217 class GrDistanceFieldLCDTextGeoProc : public GrGeometryProcessor { 218 public: 219 #ifdef SK_ENABLE_SMALL_PAGE 220 inline static constexpr int kMaxTextures = 16; 221 #else 222 inline static constexpr int kMaxTextures = 4; 223 #endif 224 225 struct DistanceAdjust { 226 SkScalar fR, fG, fB; MakeDistanceAdjust227 static DistanceAdjust Make(SkScalar r, SkScalar g, SkScalar b) { 228 DistanceAdjust result; 229 result.fR = r; result.fG = g; result.fB = b; 230 return result; 231 } 232 bool operator==(const DistanceAdjust& wa) const { 233 return (fR == wa.fR && fG == wa.fG && fB == wa.fB); 234 } 235 bool operator!=(const DistanceAdjust& wa) const { 236 return !(*this == wa); 237 } 238 }; 239 Make(SkArenaAlloc * arena,const GrShaderCaps & caps,const GrSurfaceProxyView * views,int numActiveViews,GrSamplerState params,DistanceAdjust distanceAdjust,uint32_t flags,const SkMatrix & localMatrixIfUsesLocalCoords)240 static GrGeometryProcessor* Make(SkArenaAlloc* arena, 241 const GrShaderCaps& caps, 242 const GrSurfaceProxyView* views, 243 int numActiveViews, 244 GrSamplerState params, 245 DistanceAdjust distanceAdjust, 246 uint32_t flags, 247 const SkMatrix& localMatrixIfUsesLocalCoords) { 248 return arena->make([&](void* ptr) { 249 return new (ptr) GrDistanceFieldLCDTextGeoProc(caps, views, numActiveViews, params, 250 distanceAdjust, flags, 251 localMatrixIfUsesLocalCoords); 252 }); 253 } 254 ~GrDistanceFieldLCDTextGeoProc()255 ~GrDistanceFieldLCDTextGeoProc() override {} 256 name()257 const char* name() const override { return "DistanceFieldLCDText"; } 258 259 void addNewViews(const GrSurfaceProxyView*, int numActiveViews, GrSamplerState); 260 261 void addToKey(const GrShaderCaps&, skgpu::KeyBuilder*) const override; 262 263 std::unique_ptr<ProgramImpl> makeProgramImpl(const GrShaderCaps&) const override; 264 265 private: 266 class Impl; 267 268 GrDistanceFieldLCDTextGeoProc(const GrShaderCaps& caps, const GrSurfaceProxyView* views, 269 int numActiveViews, GrSamplerState params, DistanceAdjust wa, 270 uint32_t flags, const SkMatrix& localMatrix); 271 onTextureSampler(int i)272 const TextureSampler& onTextureSampler(int i) const override { return fTextureSamplers[i]; } 273 274 TextureSampler fTextureSamplers[kMaxTextures]; 275 SkISize fAtlasDimensions; // dimensions for all textures used with fTextureSamplers[]. 276 const SkMatrix fLocalMatrix; 277 DistanceAdjust fDistanceAdjust; 278 Attribute fInPosition; 279 Attribute fInColor; 280 Attribute fInTextureCoords; 281 uint32_t fFlags; 282 283 GR_DECLARE_GEOMETRY_PROCESSOR_TEST 284 285 using INHERITED = GrGeometryProcessor; 286 }; 287 288 #endif // !defined(SK_DISABLE_SDF_TEXT) 289 290 #endif 291