1 /* 2 * Copyright 2012 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 SkGradientShaderPriv_DEFINED 9 #define SkGradientShaderPriv_DEFINED 10 11 #include "SkGradientBitmapCache.h" 12 #include "SkGradientShader.h" 13 14 #include "SkArenaAlloc.h" 15 #include "SkAutoMalloc.h" 16 #include "SkClampRange.h" 17 #include "SkColorPriv.h" 18 #include "SkColorSpace.h" 19 #include "SkOnce.h" 20 #include "SkPM4fPriv.h" 21 #include "SkRasterPipeline.h" 22 #include "SkReadBuffer.h" 23 #include "SkShaderBase.h" 24 #include "SkUtils.h" 25 #include "SkWriteBuffer.h" 26 27 #if SK_SUPPORT_GPU 28 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1 29 #endif 30 31 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1, 32 int count) { 33 if (count > 0) { 34 if (v0 == v1) { 35 sk_memset32(dst, v0, count); 36 } else { 37 int pairs = count >> 1; 38 for (int i = 0; i < pairs; i++) { 39 *dst++ = v0; 40 *dst++ = v1; 41 } 42 if (count & 1) { 43 *dst = v0; 44 } 45 } 46 } 47 } 48 49 // Clamp 50 51 static inline SkFixed clamp_tileproc(SkFixed x) { 52 return SkClampMax(x, 0xFFFF); 53 } 54 55 // Repeat 56 57 static inline SkFixed repeat_tileproc(SkFixed x) { 58 return x & 0xFFFF; 59 } 60 61 // Mirror 62 63 static inline SkFixed mirror_tileproc(SkFixed x) { 64 int s = SkLeftShift(x, 15) >> 31; 65 return (x ^ s) & 0xFFFF; 66 } 67 68 /////////////////////////////////////////////////////////////////////////////// 69 70 typedef SkFixed (*TileProc)(SkFixed); 71 72 /////////////////////////////////////////////////////////////////////////////// 73 74 static const TileProc gTileProcs[] = { 75 clamp_tileproc, 76 repeat_tileproc, 77 mirror_tileproc 78 }; 79 80 /////////////////////////////////////////////////////////////////////////////// 81 82 class SkGradientShaderBase : public SkShaderBase { 83 public: 84 struct Descriptor { 85 Descriptor() { 86 sk_bzero(this, sizeof(*this)); 87 fTileMode = SkShader::kClamp_TileMode; 88 } 89 90 const SkMatrix* fLocalMatrix; 91 const SkColor4f* fColors; 92 sk_sp<SkColorSpace> fColorSpace; 93 const SkScalar* fPos; 94 int fCount; 95 SkShader::TileMode fTileMode; 96 uint32_t fGradFlags; 97 98 void flatten(SkWriteBuffer&) const; 99 }; 100 101 class DescriptorScope : public Descriptor { 102 public: 103 DescriptorScope() {} 104 105 bool unflatten(SkReadBuffer&); 106 107 // fColors and fPos always point into local memory, so they can be safely mutated 108 // 109 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); } 110 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); } 111 112 private: 113 enum { 114 kStorageCount = 16 115 }; 116 SkColor4f fColorStorage[kStorageCount]; 117 SkScalar fPosStorage[kStorageCount]; 118 SkMatrix fLocalMatrixStorage; 119 SkAutoMalloc fDynamicStorage; 120 }; 121 122 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit); 123 ~SkGradientShaderBase() override; 124 125 // The cache is initialized on-demand when getCache32 is called. 126 class GradientShaderCache : public SkRefCnt { 127 public: 128 GradientShaderCache(U8CPU alpha, bool dither, const SkGradientShaderBase& shader); 129 ~GradientShaderCache(); 130 131 const SkPMColor* getCache32(); 132 133 SkPixelRef* getCache32PixelRef() const { return fCache32PixelRef.get(); } 134 135 unsigned getAlpha() const { return fCacheAlpha; } 136 bool getDither() const { return fCacheDither; } 137 138 private: 139 // Working pointer. If it's nullptr, we need to recompute the cache values. 140 SkPMColor* fCache32; 141 142 sk_sp<SkPixelRef> fCache32PixelRef; 143 const unsigned fCacheAlpha; // The alpha value we used when we computed the cache. 144 // Larger than 8bits so we can store uninitialized 145 // value. 146 const bool fCacheDither; // The dither flag used when we computed the cache. 147 148 const SkGradientShaderBase& fShader; 149 150 // Make sure we only initialize the cache once. 151 SkOnce fCache32InitOnce; 152 153 static void initCache32(GradientShaderCache* cache); 154 155 static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count, 156 U8CPU alpha, uint32_t gradFlags, bool dither); 157 }; 158 159 class GradientShaderBaseContext : public Context { 160 public: 161 GradientShaderBaseContext(const SkGradientShaderBase& shader, const ContextRec&); 162 163 uint32_t getFlags() const override { return fFlags; } 164 165 bool isValid() const; 166 167 protected: 168 SkMatrix fDstToIndex; 169 SkMatrix::MapXYProc fDstToIndexProc; 170 uint8_t fDstToIndexClass; 171 uint8_t fFlags; 172 bool fDither; 173 174 sk_sp<GradientShaderCache> fCache; 175 176 private: 177 typedef Context INHERITED; 178 }; 179 180 bool isOpaque() const override; 181 182 enum class GradientBitmapType : uint8_t { 183 kLegacy, 184 kSRGB, 185 kHalfFloat, 186 }; 187 188 void getGradientTableBitmap(SkBitmap*, GradientBitmapType bitmapType) const; 189 190 enum { 191 /// Seems like enough for visual accuracy. TODO: if pos[] deserves 192 /// it, use a larger cache. 193 kCache32Bits = 8, 194 kCache32Count = (1 << kCache32Bits), 195 kCache32Shift = 16 - kCache32Bits, 196 kSqrt32Shift = 8 - kCache32Bits, 197 198 /// This value is used to *read* the dither cache; it may be 0 199 /// if dithering is disabled. 200 kDitherStride32 = kCache32Count, 201 }; 202 203 uint32_t getGradFlags() const { return fGradFlags; } 204 205 SkColor4f getXformedColor(size_t index, SkColorSpace*) const; 206 207 protected: 208 struct Rec { 209 SkFixed fPos; // 0...1 210 uint32_t fScale; // (1 << 24) / range 211 }; 212 213 class GradientShaderBase4fContext; 214 215 SkGradientShaderBase(SkReadBuffer& ); 216 void flatten(SkWriteBuffer&) const override; 217 SK_TO_STRING_OVERRIDE() 218 219 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const; 220 221 bool onAsLuminanceColor(SkColor*) const override; 222 223 void initLinearBitmap(SkBitmap* bitmap) const; 224 225 /* 226 * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively. 227 * Count is the number of colors in the gradient 228 * It will then flip all the color and rec information and return in their respective Dst 229 * pointers. It is assumed that space has already been allocated for the Dst pointers. 230 * The rec src and dst are only assumed to be valid if count > 2 231 */ 232 static void FlipGradientColors(SkColor* colorDst, Rec* recDst, 233 SkColor* colorSrc, Rec* recSrc, 234 int count); 235 236 bool onAppendStages(SkRasterPipeline* pipeline, SkColorSpace* dstCS, SkArenaAlloc* alloc, 237 const SkMatrix& ctm, const SkPaint& paint, 238 const SkMatrix* localM) const override; 239 240 virtual bool adjustMatrixAndAppendStages(SkArenaAlloc* alloc, 241 SkMatrix* matrix, 242 SkRasterPipeline* tPipeline, 243 SkRasterPipeline* postPipeline) const = 0; 244 245 template <typename T, typename... Args> 246 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) { 247 auto* ctx = alloc->make<T>(std::forward<Args>(args)...); 248 if (!ctx->isValid()) { 249 return nullptr; 250 } 251 return ctx; 252 } 253 254 const SkMatrix fPtsToUnit; 255 TileMode fTileMode; 256 TileProc fTileProc; 257 uint8_t fGradFlags; 258 Rec* fRecs; 259 260 private: 261 enum { 262 kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space 263 264 kStorageSize = kColorStorageCount * 265 (sizeof(SkColor) + sizeof(SkScalar) + sizeof(Rec) + sizeof(SkColor4f)) 266 }; 267 SkColor fStorage[(kStorageSize + 3) >> 2]; 268 public: 269 SkColor* fOrigColors; // original colors, before modulation by paint in context. 270 SkColor4f* fOrigColors4f; // original colors, as linear floats 271 SkScalar* fOrigPos; // original positions 272 int fColorCount; 273 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops 274 275 bool colorsAreOpaque() const { return fColorsAreOpaque; } 276 277 TileMode getTileMode() const { return fTileMode; } 278 Rec* getRecs() const { return fRecs; } 279 280 private: 281 bool fColorsAreOpaque; 282 283 sk_sp<GradientShaderCache> refCache(U8CPU alpha, bool dither) const; 284 mutable SkMutex fCacheMutex; 285 mutable sk_sp<GradientShaderCache> fCache; 286 287 void initCommon(); 288 289 typedef SkShaderBase INHERITED; 290 }; 291 292 293 static inline int init_dither_toggle(int x, int y) { 294 x &= 1; 295 y = (y & 1) << 1; 296 return (x | y) * SkGradientShaderBase::kDitherStride32; 297 } 298 299 static inline int next_dither_toggle(int toggle) { 300 return toggle ^ SkGradientShaderBase::kDitherStride32; 301 } 302 303 /////////////////////////////////////////////////////////////////////////////// 304 305 #if SK_SUPPORT_GPU 306 307 #include "GrColorSpaceXform.h" 308 #include "GrCoordTransform.h" 309 #include "GrFragmentProcessor.h" 310 #include "glsl/GrGLSLColorSpaceXformHelper.h" 311 #include "glsl/GrGLSLFragmentProcessor.h" 312 #include "glsl/GrGLSLProgramDataManager.h" 313 314 class GrInvariantOutput; 315 316 /* 317 * The interpretation of the texture matrix depends on the sample mode. The 318 * texture matrix is applied both when the texture coordinates are explicit 319 * and when vertex positions are used as texture coordinates. In the latter 320 * case the texture matrix is applied to the pre-view-matrix position 321 * values. 322 * 323 * Normal SampleMode 324 * The post-matrix texture coordinates are in normalize space with (0,0) at 325 * the top-left and (1,1) at the bottom right. 326 * RadialGradient 327 * The matrix specifies the radial gradient parameters. 328 * (0,0) in the post-matrix space is center of the radial gradient. 329 * Radial2Gradient 330 * Matrix transforms to space where first circle is centered at the 331 * origin. The second circle will be centered (x, 0) where x may be 332 * 0 and is provided by setRadial2Params. The post-matrix space is 333 * normalized such that 1 is the second radius - first radius. 334 * SweepGradient 335 * The angle from the origin of texture coordinates in post-matrix space 336 * determines the gradient value. 337 */ 338 339 class GrTextureStripAtlas; 340 341 // Base class for Gr gradient effects 342 class GrGradientEffect : public GrFragmentProcessor { 343 public: 344 struct CreateArgs { 345 CreateArgs(GrContext* context, 346 const SkGradientShaderBase* shader, 347 const SkMatrix* matrix, 348 SkShader::TileMode tileMode, 349 sk_sp<GrColorSpaceXform> colorSpaceXform, 350 bool gammaCorrect) 351 : fContext(context) 352 , fShader(shader) 353 , fMatrix(matrix) 354 , fTileMode(tileMode) 355 , fColorSpaceXform(std::move(colorSpaceXform)) 356 , fGammaCorrect(gammaCorrect) {} 357 358 GrContext* fContext; 359 const SkGradientShaderBase* fShader; 360 const SkMatrix* fMatrix; 361 SkShader::TileMode fTileMode; 362 sk_sp<GrColorSpaceXform> fColorSpaceXform; 363 bool fGammaCorrect; 364 }; 365 366 class GLSLProcessor; 367 368 ~GrGradientEffect() override; 369 370 bool useAtlas() const { return SkToBool(-1 != fRow); } 371 SkScalar getYCoord() const { return fYCoord; } 372 373 enum ColorType { 374 kTwo_ColorType, 375 kThree_ColorType, // Symmetric three color 376 kTexture_ColorType, 377 378 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 379 kSingleHardStop_ColorType, // 0, t, t, 1 380 kHardStopLeftEdged_ColorType, // 0, 0, 1 381 kHardStopRightEdged_ColorType, // 0, 1, 1 382 #endif 383 }; 384 385 ColorType getColorType() const { return fColorType; } 386 387 // Determines the type of gradient, one of: 388 // - Two-color 389 // - Symmetric three-color 390 // - Texture 391 // - Centered hard stop 392 // - Left-edged hard stop 393 // - Right-edged hard stop 394 ColorType determineColorType(const SkGradientShaderBase& shader); 395 396 enum PremulType { 397 kBeforeInterp_PremulType, 398 kAfterInterp_PremulType, 399 }; 400 401 PremulType getPremulType() const { return fPremulType; } 402 403 const SkColor* getColors(int pos) const { 404 SkASSERT(fColorType != kTexture_ColorType); 405 SkASSERT(pos < fColors.count()); 406 return &fColors[pos]; 407 } 408 409 const SkColor4f* getColors4f(int pos) const { 410 SkASSERT(fColorType != kTexture_ColorType); 411 SkASSERT(pos < fColors4f.count()); 412 return &fColors4f[pos]; 413 } 414 415 protected: 416 GrGradientEffect(const CreateArgs&, bool isOpaque); 417 418 #if GR_TEST_UTILS 419 /** Helper struct that stores (and populates) parameters to construct a random gradient. 420 If fUseColors4f is true, then the SkColor4f factory should be called, with fColors4f and 421 fColorSpace. Otherwise, the SkColor factory should be called, with fColors. fColorCount 422 will be the number of color stops in either case, and fColors and fStops can be passed to 423 the gradient factory. (The constructor may decide not to use stops, in which case fStops 424 will be nullptr). */ 425 struct RandomGradientParams { 426 static const int kMaxRandomGradientColors = 5; 427 428 RandomGradientParams(SkRandom* r); 429 430 bool fUseColors4f; 431 SkColor fColors[kMaxRandomGradientColors]; 432 SkColor4f fColors4f[kMaxRandomGradientColors]; 433 sk_sp<SkColorSpace> fColorSpace; 434 SkScalar fStopStorage[kMaxRandomGradientColors]; 435 SkShader::TileMode fTileMode; 436 int fColorCount; 437 SkScalar* fStops; 438 }; 439 #endif 440 441 bool onIsEqual(const GrFragmentProcessor&) const override; 442 443 const GrCoordTransform& getCoordTransform() const { return fCoordTransform; } 444 445 /** Checks whether the constructor failed to fully initialize the processor. */ 446 bool isValid() const { 447 return fColorType != kTexture_ColorType || fTextureSampler.isInitialized(); 448 } 449 450 private: 451 static OptimizationFlags OptFlags(bool isOpaque); 452 453 // If we're in legacy mode, then fColors will be populated. If we're gamma-correct, then 454 // fColors4f and fColorSpaceXform will be populated. 455 SkTDArray<SkColor> fColors; 456 457 SkTDArray<SkColor4f> fColors4f; 458 sk_sp<GrColorSpaceXform> fColorSpaceXform; 459 460 SkTDArray<SkScalar> fPositions; 461 SkShader::TileMode fTileMode; 462 463 GrCoordTransform fCoordTransform; 464 TextureSampler fTextureSampler; 465 SkScalar fYCoord; 466 GrTextureStripAtlas* fAtlas; 467 int fRow; 468 bool fIsOpaque; 469 ColorType fColorType; 470 PremulType fPremulType; // This is already baked into the table for texture gradients, and 471 // only changes behavior for gradients that don't use a texture. 472 typedef GrFragmentProcessor INHERITED; 473 474 }; 475 476 /////////////////////////////////////////////////////////////////////////////// 477 478 // Base class for GL gradient effects 479 class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor { 480 public: 481 GLSLProcessor() { 482 fCachedYCoord = SK_ScalarMax; 483 } 484 485 protected: 486 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; 487 488 protected: 489 /** 490 * Subclasses must call this. It will return a key for the part of the shader code controlled 491 * by the base class. The subclasses must stick it in their key and then pass it to the below 492 * emit* functions from their emitCode function. 493 */ 494 static uint32_t GenBaseGradientKey(const GrProcessor&); 495 496 // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses 497 // should call this method from their emitCode(). 498 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&); 499 500 // Emit code that gets a fragment's color from an expression for t; has branches for 501 // several control flows inside -- 2-color gradients, 3-color symmetric gradients, 4+ 502 // color gradients that use the traditional texture lookup, as well as several varieties 503 // of hard stop gradients 504 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder, 505 GrGLSLUniformHandler* uniformHandler, 506 const GrShaderCaps* shaderCaps, 507 const GrGradientEffect&, 508 const char* gradientTValue, 509 const char* outputColor, 510 const char* inputColor, 511 const TextureSamplers&); 512 513 private: 514 enum { 515 // First bit for premul before/after interp 516 kPremulBeforeInterpKey = 1, 517 518 // Next three bits for 2/3 color type or different special 519 // hard stop cases (neither means using texture atlas) 520 kTwoColorKey = 2, 521 kThreeColorKey = 4, 522 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 523 kHardStopCenteredKey = 6, 524 kHardStopZeroZeroOneKey = 8, 525 kHardStopZeroOneOneKey = 10, 526 527 // Next two bits for tile mode 528 kClampTileMode = 16, 529 kRepeatTileMode = 32, 530 kMirrorTileMode = 48, 531 532 // Lower six bits for premul, 2/3 color type, and tile mode 533 kReservedBits = 6, 534 #endif 535 }; 536 537 SkScalar fCachedYCoord; 538 GrGLSLProgramDataManager::UniformHandle fColorsUni; 539 GrGLSLProgramDataManager::UniformHandle fHardStopT; 540 GrGLSLProgramDataManager::UniformHandle fFSYUni; 541 GrGLSLColorSpaceXformHelper fColorSpaceHelper; 542 543 typedef GrGLSLFragmentProcessor INHERITED; 544 }; 545 546 #endif 547 548 #endif 549