OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkGradientShaderPriv_DEFINED | 8 #ifndef SkGradientShaderPriv_DEFINED |
9 #define SkGradientShaderPriv_DEFINED | 9 #define SkGradientShaderPriv_DEFINED |
10 | 10 |
11 #include "SkGradientBitmapCache.h" | 11 #include "SkGradientBitmapCache.h" |
12 #include "SkGradientShader.h" | 12 #include "SkGradientShader.h" |
13 #include "SkClampRange.h" | 13 #include "SkClampRange.h" |
14 #include "SkColorPriv.h" | 14 #include "SkColorPriv.h" |
15 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
16 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
17 #include "SkMallocPixelRef.h" | 17 #include "SkMallocPixelRef.h" |
18 #include "SkUtils.h" | 18 #include "SkUtils.h" |
19 #include "SkShader.h" | 19 #include "SkShader.h" |
20 #include "SkOnce.h" | 20 #include "SkOnce.h" |
21 | 21 |
22 #if SK_SUPPORT_GPU | |
23 #define GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS 1 | |
24 #endif | |
25 | |
26 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1, | 22 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1, |
27 int count) { | 23 int count) { |
28 if (count > 0) { | 24 if (count > 0) { |
29 if (v0 == v1) { | 25 if (v0 == v1) { |
30 sk_memset32(dst, v0, count); | 26 sk_memset32(dst, v0, count); |
31 } else { | 27 } else { |
32 int pairs = count >> 1; | 28 int pairs = count >> 1; |
33 for (int i = 0; i < pairs; i++) { | 29 for (int i = 0; i < pairs; i++) { |
34 *dst++ = v0; | 30 *dst++ = v0; |
35 *dst++ = v1; | 31 *dst++ = v1; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 | 121 |
126 const uint16_t* getCache16(); | 122 const uint16_t* getCache16(); |
127 const SkPMColor* getCache32(); | 123 const SkPMColor* getCache32(); |
128 | 124 |
129 SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef;
} | 125 SkMallocPixelRef* getCache32PixelRef() const { return fCache32PixelRef;
} |
130 | 126 |
131 unsigned getAlpha() const { return fCacheAlpha; } | 127 unsigned getAlpha() const { return fCacheAlpha; } |
132 bool getDither() const { return fCacheDither; } | 128 bool getDither() const { return fCacheDither; } |
133 | 129 |
134 private: | 130 private: |
135 // Working pointers. If either is nullptr, we need to recompute the corr
esponding | 131 // Working pointers. If either is nullptr, we need to recompute the corr
esponding cache values. |
136 // cache values. | |
137 uint16_t* fCache16; | 132 uint16_t* fCache16; |
138 SkPMColor* fCache32; | 133 SkPMColor* fCache32; |
139 | 134 |
140 uint16_t* fCache16Storage; // Storage for fCache16, allocated
on demand. | 135 uint16_t* fCache16Storage; // Storage for fCache16, allocated
on demand. |
141 SkMallocPixelRef* fCache32PixelRef; | 136 SkMallocPixelRef* fCache32PixelRef; |
142 const unsigned fCacheAlpha; // The alpha value we used when we
computed the cache. | 137 const unsigned fCacheAlpha; // The alpha value we used when we
computed the cache. |
143 // Larger than 8bits so we can sto
re uninitialized | 138 // Larger than 8bits so we can sto
re uninitialized |
144 // value. | 139 // value. |
145 const bool fCacheDither; // The dither flag used when we co
mputed the cache. | 140 const bool fCacheDither; // The dither flag used when we co
mputed the cache. |
146 | 141 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 kCache32Count = (1 << kCache32Bits), | 190 kCache32Count = (1 << kCache32Bits), |
196 kCache32Shift = 16 - kCache32Bits, | 191 kCache32Shift = 16 - kCache32Bits, |
197 kSqrt32Shift = 8 - kCache32Bits, | 192 kSqrt32Shift = 8 - kCache32Bits, |
198 | 193 |
199 /// This value is used to *read* the dither cache; it may be 0 | 194 /// This value is used to *read* the dither cache; it may be 0 |
200 /// if dithering is disabled. | 195 /// if dithering is disabled. |
201 kDitherStride32 = kCache32Count, | 196 kDitherStride32 = kCache32Count, |
202 kDitherStride16 = kCache16Count, | 197 kDitherStride16 = kCache16Count, |
203 }; | 198 }; |
204 | 199 |
| 200 enum GpuColorType { |
| 201 kTwo_GpuColorType, |
| 202 kThree_GpuColorType, // Symmetric three color |
| 203 kTexture_GpuColorType |
| 204 }; |
| 205 |
| 206 // Determines and returns the gradient is a two color gradient, symmetric th
ree color gradient |
| 207 // or other (texture gradient). If it is two or symmetric three color, the c
olors array will |
| 208 // also be filled with the gradient colors |
| 209 GpuColorType getGpuColorType(SkColor colors[3]) const; |
| 210 |
205 uint32_t getGradFlags() const { return fGradFlags; } | 211 uint32_t getGradFlags() const { return fGradFlags; } |
206 | 212 |
207 protected: | 213 protected: |
208 class GradientShaderBase4fContext; | 214 class GradientShaderBase4fContext; |
209 | 215 |
210 SkGradientShaderBase(SkReadBuffer& ); | 216 SkGradientShaderBase(SkReadBuffer& ); |
211 void flatten(SkWriteBuffer&) const override; | 217 void flatten(SkWriteBuffer&) const override; |
212 SK_TO_STRING_OVERRIDE() | 218 SK_TO_STRING_OVERRIDE() |
213 | 219 |
214 const SkMatrix fPtsToUnit; | 220 const SkMatrix fPtsToUnit; |
215 TileMode fTileMode; | 221 TileMode fTileMode; |
216 TileProc fTileProc; | 222 TileProc fTileProc; |
| 223 int fColorCount; |
217 uint8_t fGradFlags; | 224 uint8_t fGradFlags; |
218 | 225 |
219 struct Rec { | 226 struct Rec { |
220 SkFixed fPos; // 0...1 | 227 SkFixed fPos; // 0...1 |
221 uint32_t fScale; // (1 << 24) / range | 228 uint32_t fScale; // (1 << 24) / range |
222 }; | 229 }; |
223 Rec* fRecs; | 230 Rec* fRecs; |
224 | 231 |
225 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const; | 232 void commonAsAGradient(GradientInfo*, bool flipGrad = false) const; |
226 | 233 |
(...skipping 13 matching lines...) Expand all Loading... |
240 private: | 247 private: |
241 enum { | 248 enum { |
242 kColorStorageCount = 4, // more than this many colors, and we'll use sk_
malloc for the space | 249 kColorStorageCount = 4, // more than this many colors, and we'll use sk_
malloc for the space |
243 | 250 |
244 kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(SkScalar)
+ sizeof(Rec)) | 251 kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(SkScalar)
+ sizeof(Rec)) |
245 }; | 252 }; |
246 SkColor fStorage[(kStorageSize + 3) >> 2]; | 253 SkColor fStorage[(kStorageSize + 3) >> 2]; |
247 public: | 254 public: |
248 SkColor* fOrigColors; // original colors, before modulation by paint in c
ontext. | 255 SkColor* fOrigColors; // original colors, before modulation by paint in c
ontext. |
249 SkScalar* fOrigPos; // original positions | 256 SkScalar* fOrigPos; // original positions |
250 int fColorCount; | |
251 | |
252 SkTArray<sk_sp<SkShader>> fSubGradients; | |
253 | 257 |
254 bool colorsAreOpaque() const { return fColorsAreOpaque; } | 258 bool colorsAreOpaque() const { return fColorsAreOpaque; } |
255 | 259 |
256 TileMode getTileMode() const { return fTileMode; } | |
257 Rec* getRecs() const { return fRecs; } | |
258 | |
259 private: | 260 private: |
260 bool fColorsAreOpaque; | 261 bool fColorsAreOpaque; |
261 | 262 |
262 GradientShaderCache* refCache(U8CPU alpha, bool dither) const; | 263 GradientShaderCache* refCache(U8CPU alpha, bool dither) const; |
263 mutable SkMutex fCacheMutex; | 264 mutable SkMutex fCacheMutex; |
264 mutable SkAutoTUnref<GradientShaderCache> fCache; | 265 mutable SkAutoTUnref<GradientShaderCache> fCache; |
265 | 266 |
266 void initCommon(); | 267 void initCommon(); |
267 | 268 |
268 typedef SkShader INHERITED; | 269 typedef SkShader INHERITED; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 class GLSLProcessor; | 329 class GLSLProcessor; |
329 | 330 |
330 GrGradientEffect(GrContext* ctx, | 331 GrGradientEffect(GrContext* ctx, |
331 const SkGradientShaderBase& shader, | 332 const SkGradientShaderBase& shader, |
332 const SkMatrix& matrix, | 333 const SkMatrix& matrix, |
333 SkShader::TileMode tileMode); | 334 SkShader::TileMode tileMode); |
334 | 335 |
335 virtual ~GrGradientEffect(); | 336 virtual ~GrGradientEffect(); |
336 | 337 |
337 bool useAtlas() const { return SkToBool(-1 != fRow); } | 338 bool useAtlas() const { return SkToBool(-1 != fRow); } |
338 SkScalar getYCoord() const { return fYCoord; } | 339 SkScalar getYCoord() const { return fYCoord; }; |
339 | 340 |
340 enum ColorType { | 341 SkGradientShaderBase::GpuColorType getColorType() const { return fColorType;
} |
341 kTwo_ColorType, | |
342 kThree_ColorType, // Symmetric three color | |
343 kTexture_ColorType, | |
344 | |
345 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS | |
346 kHardStopCentered_ColorType, // 0, 0.5, 0.5, 1 | |
347 kHardStopLeftEdged_ColorType, // 0, 0, 1 | |
348 kHardStopRightEdged_ColorType, // 0, 1, 1 | |
349 #endif | |
350 }; | |
351 | |
352 ColorType getColorType() const { return fColorType; } | |
353 | |
354 // Determines the type of gradient, one of: | |
355 // - Two-color | |
356 // - Symmetric three-color | |
357 // - Texture | |
358 // - Centered hard stop | |
359 // - Left-edged hard stop | |
360 // - Right-edged hard stop | |
361 ColorType determineColorType(const SkGradientShaderBase& shader); | |
362 | 342 |
363 enum PremulType { | 343 enum PremulType { |
364 kBeforeInterp_PremulType, | 344 kBeforeInterp_PremulType, |
365 kAfterInterp_PremulType, | 345 kAfterInterp_PremulType, |
366 }; | 346 }; |
367 | 347 |
368 PremulType getPremulType() const { return fPremulType; } | 348 PremulType getPremulType() const { return fPremulType; } |
369 | 349 |
370 const SkColor* getColors(int pos) const { | 350 const SkColor* getColors(int pos) const { |
371 SkASSERT(fColorType != kTexture_ColorType); | 351 SkASSERT(fColorType != SkGradientShaderBase::kTexture_GpuColorType); |
372 SkASSERT(pos < fColors.count()); | 352 SkASSERT((pos-1) <= fColorType); |
373 return &fColors[pos]; | 353 return &fColors[pos]; |
374 } | 354 } |
375 | 355 |
376 protected: | 356 protected: |
377 /** Populates a pair of arrays with colors and stop info to construct a rand
om gradient. | 357 /** Populates a pair of arrays with colors and stop info to construct a rand
om gradient. |
378 The function decides whether stop values should be used or not. The retu
rn value indicates | 358 The function decides whether stop values should be used or not. The retu
rn value indicates |
379 the number of colors, which will be capped by kMaxRandomGradientColors.
colors should be | 359 the number of colors, which will be capped by kMaxRandomGradientColors.
colors should be |
380 sized to be at least kMaxRandomGradientColors. stops is a pointer to an
array of at least | 360 sized to be at least kMaxRandomGradientColors. stops is a pointer to an
array of at least |
381 size kMaxRandomGradientColors. It may be updated to nullptr, indicating
that nullptr should | 361 size kMaxRandomGradientColors. It may be updated to nullptr, indicating
that nullptr should be |
382 be passed to the gradient factory rather than the array. | 362 passed to the gradient factory rather than the array. |
383 */ | 363 */ |
384 static const int kMaxRandomGradientColors = 4; | 364 static const int kMaxRandomGradientColors = 4; |
385 static int RandomGradientParams(SkRandom* r, | 365 static int RandomGradientParams(SkRandom* r, |
386 SkColor colors[kMaxRandomGradientColors], | 366 SkColor colors[kMaxRandomGradientColors], |
387 SkScalar** stops, | 367 SkScalar** stops, |
388 SkShader::TileMode* tm); | 368 SkShader::TileMode* tm); |
389 | 369 |
390 bool onIsEqual(const GrFragmentProcessor&) const override; | 370 bool onIsEqual(const GrFragmentProcessor&) const override; |
391 | 371 |
392 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; | 372 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; |
393 | 373 |
394 const GrCoordTransform& getCoordTransform() const { return fCoordTransform;
} | 374 const GrCoordTransform& getCoordTransform() const { return fCoordTransform;
} |
395 | 375 |
396 private: | 376 private: |
397 static const GrCoordSet kCoordSet = kLocal_GrCoordSet; | 377 static const GrCoordSet kCoordSet = kLocal_GrCoordSet; |
398 | 378 |
399 SkTDArray<SkColor> fColors; | |
400 SkTDArray<SkScalar> fPositions; | |
401 SkShader::TileMode fTileMode; | |
402 | |
403 GrCoordTransform fCoordTransform; | 379 GrCoordTransform fCoordTransform; |
404 GrTextureAccess fTextureAccess; | 380 GrTextureAccess fTextureAccess; |
405 SkScalar fYCoord; | 381 SkScalar fYCoord; |
406 GrTextureStripAtlas* fAtlas; | 382 GrTextureStripAtlas* fAtlas; |
407 int fRow; | 383 int fRow; |
408 bool fIsOpaque; | 384 bool fIsOpaque; |
409 ColorType fColorType; | 385 SkGradientShaderBase::GpuColorType fColorType; |
410 PremulType fPremulType; // This is already baked into the table for texture
gradients, and | 386 SkColor fColors[3]; // More than 3 colors we use texture |
411 // only changes behavior for gradients that don't us
e a texture. | 387 PremulType fPremulType; // This only changes behavior for two and three colo
r special cases. |
| 388 // It is already baked into to the table for texture
gradients. |
412 typedef GrFragmentProcessor INHERITED; | 389 typedef GrFragmentProcessor INHERITED; |
413 | 390 |
414 }; | 391 }; |
415 | 392 |
416 /////////////////////////////////////////////////////////////////////////////// | 393 /////////////////////////////////////////////////////////////////////////////// |
417 | 394 |
418 // Base class for GL gradient effects | 395 // Base class for GLSL gradient effects |
419 class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor { | 396 class GrGradientEffect::GLSLProcessor : public GrGLSLFragmentProcessor { |
420 public: | 397 public: |
421 GLSLProcessor() { | 398 GLSLProcessor(); |
422 fCachedYCoord = SK_ScalarMax; | |
423 } | |
424 | 399 |
425 protected: | 400 protected: |
426 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; | 401 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; |
427 | 402 |
428 protected: | 403 protected: |
429 /** | 404 /** |
430 * Subclasses must call this. It will return a key for the part of the shade
r code controlled | 405 * Subclasses must call this. It will return a key for the part of the shade
r code controlled |
431 * by the base class. The subclasses must stick it in their key and then pas
s it to the below | 406 * by the base class. The subclasses must stick it in their key and then pas
s it to the below |
432 * emit* functions from their emitCode function. | 407 * emit* functions from their emitCode function. |
433 */ | 408 */ |
434 static uint32_t GenBaseGradientKey(const GrProcessor&); | 409 static uint32_t GenBaseGradientKey(const GrProcessor&); |
435 | 410 |
436 // Emits the uniform used as the y-coord to texture samples in derived class
es. Subclasses | 411 // Emits the uniform used as the y-coord to texture samples in derived class
es. Subclasses |
437 // should call this method from their emitCode(). | 412 // should call this method from their emitCode(). |
438 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&); | 413 void emitUniforms(GrGLSLUniformHandler*, const GrGradientEffect&); |
439 | 414 |
440 // Emit code that gets a fragment's color from an expression for t; has bran
ches for | 415 |
441 // several control flows inside -- 2-color gradients, 3-color symmetric grad
ients, 4+ | 416 // emit code that gets a fragment's color from an expression for t; Has bran
ches for 3 separate |
442 // color gradients that use the traditional texture lookup, as well as sever
al varieties | 417 // control flows inside -- 2 color gradients, 3 color symmetric gradients (b
oth using |
443 // of hard stop gradients | 418 // native GLSL mix), and 4+ color gradients that use the traditional texture
lookup. |
444 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder, | 419 void emitColor(GrGLSLFPFragmentBuilder* fragBuilder, |
445 GrGLSLUniformHandler* uniformHandler, | 420 GrGLSLUniformHandler* uniformHandler, |
446 const GrGLSLCaps* caps, | 421 const GrGLSLCaps* caps, |
447 const GrGradientEffect&, | 422 const GrGradientEffect&, |
448 const char* gradientTValue, | 423 const char* gradientTValue, |
449 const char* outputColor, | 424 const char* outputColor, |
450 const char* inputColor, | 425 const char* inputColor, |
451 const SamplerHandle* texSamplers); | 426 const SamplerHandle* texSamplers); |
452 | 427 |
453 private: | 428 private: |
454 enum { | 429 enum { |
455 // First bit for premul before/after interp | 430 // First bit for premul before/after interp |
456 kPremulBeforeInterpKey = 1, | 431 kPremulBeforeInterpKey = 1, |
457 | 432 |
458 // Next three bits for 2/3 color type or different special | 433 // Next two bits for 2/3 color type (neither means using texture atlas) |
459 // hard stop cases (neither means using texture atlas) | 434 kTwoColorKey = 4, |
460 kTwoColorKey = 2, | 435 kThreeColorKey = 6, |
461 kThreeColorKey = 4, | |
462 #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS | |
463 kHardStopCenteredKey = 6, | |
464 kHardStopZeroZeroOneKey = 8, | |
465 kHardStopZeroOneOneKey = 10, | |
466 | |
467 // Next two bits for tile mode | |
468 kClampTileMode = 16, | |
469 kRepeatTileMode = 32, | |
470 kMirrorTileMode = 48, | |
471 | |
472 // Lower six bits for premul, 2/3 color type, and tile mode | |
473 kReservedBits = 6, | |
474 #endif | |
475 }; | 436 }; |
476 | 437 |
477 SkScalar fCachedYCoord; | 438 SkScalar fCachedYCoord; |
478 GrGLSLProgramDataManager::UniformHandle fColorsUni; | |
479 GrGLSLProgramDataManager::UniformHandle fFSYUni; | 439 GrGLSLProgramDataManager::UniformHandle fFSYUni; |
| 440 GrGLSLProgramDataManager::UniformHandle fColorStartUni; |
| 441 GrGLSLProgramDataManager::UniformHandle fColorMidUni; |
| 442 GrGLSLProgramDataManager::UniformHandle fColorEndUni; |
480 | 443 |
481 typedef GrGLSLFragmentProcessor INHERITED; | 444 typedef GrGLSLFragmentProcessor INHERITED; |
482 }; | 445 }; |
483 | 446 |
484 #endif | 447 #endif |
485 | 448 |
486 #endif | 449 #endif |
OLD | NEW |