gfx/skia/trunk/src/effects/gradients/SkGradientShaderPriv.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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  */
     8 #ifndef SkGradientShaderPriv_DEFINED
     9 #define SkGradientShaderPriv_DEFINED
    11 #include "SkGradientShader.h"
    12 #include "SkClampRange.h"
    13 #include "SkColorPriv.h"
    14 #include "SkReadBuffer.h"
    15 #include "SkWriteBuffer.h"
    16 #include "SkMallocPixelRef.h"
    17 #include "SkUnitMapper.h"
    18 #include "SkUtils.h"
    19 #include "SkTemplates.h"
    20 #include "SkBitmapCache.h"
    21 #include "SkShader.h"
    23 static inline void sk_memset32_dither(uint32_t dst[], uint32_t v0, uint32_t v1,
    24                                int count) {
    25     if (count > 0) {
    26         if (v0 == v1) {
    27             sk_memset32(dst, v0, count);
    28         } else {
    29             int pairs = count >> 1;
    30             for (int i = 0; i < pairs; i++) {
    31                 *dst++ = v0;
    32                 *dst++ = v1;
    33             }
    34             if (count & 1) {
    35                 *dst = v0;
    36             }
    37         }
    38     }
    39 }
    41 //  Clamp
    43 static inline SkFixed clamp_tileproc(SkFixed x) {
    44     return SkClampMax(x, 0xFFFF);
    45 }
    47 // Repeat
    49 static inline SkFixed repeat_tileproc(SkFixed x) {
    50     return x & 0xFFFF;
    51 }
    53 // Mirror
    55 // Visual Studio 2010 (MSC_VER=1600) optimizes bit-shift code incorrectly.
    56 // See http://code.google.com/p/skia/issues/detail?id=472
    57 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
    58 #pragma optimize("", off)
    59 #endif
    61 static inline SkFixed mirror_tileproc(SkFixed x) {
    62     int s = x << 15 >> 31;
    63     return (x ^ s) & 0xFFFF;
    64 }
    66 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
    67 #pragma optimize("", on)
    68 #endif
    70 ///////////////////////////////////////////////////////////////////////////////
    72 typedef SkFixed (*TileProc)(SkFixed);
    74 ///////////////////////////////////////////////////////////////////////////////
    76 static const TileProc gTileProcs[] = {
    77     clamp_tileproc,
    78     repeat_tileproc,
    79     mirror_tileproc
    80 };
    82 ///////////////////////////////////////////////////////////////////////////////
    84 class SkGradientShaderBase : public SkShader {
    85 public:
    86     struct Descriptor {
    87         Descriptor() {
    88             sk_bzero(this, sizeof(*this));
    89             fTileMode = SkShader::kClamp_TileMode;
    90         }
    92         const SkColor*      fColors;
    93         const SkScalar*     fPos;
    94         int                 fCount;
    95         SkShader::TileMode  fTileMode;
    96         SkUnitMapper*       fMapper;
    97         uint32_t            fFlags;
    98     };
   100 public:
   101     SkGradientShaderBase(const Descriptor& desc);
   102     virtual ~SkGradientShaderBase();
   104     virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&) SK_OVERRIDE;
   105     virtual uint32_t getFlags() SK_OVERRIDE { return fFlags; }
   106     virtual bool isOpaque() const SK_OVERRIDE;
   108     void getGradientTableBitmap(SkBitmap*) const;
   110     enum {
   111         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
   112         /// it, use a larger cache.
   113         kCache16Bits    = 8,
   114         kCache16Count = (1 << kCache16Bits),
   115         kCache16Shift   = 16 - kCache16Bits,
   116         kSqrt16Shift    = 8 - kCache16Bits,
   118         /// Seems like enough for visual accuracy. TODO: if pos[] deserves
   119         /// it, use a larger cache.
   120         kCache32Bits    = 8,
   121         kCache32Count   = (1 << kCache32Bits),
   122         kCache32Shift   = 16 - kCache32Bits,
   123         kSqrt32Shift    = 8 - kCache32Bits,
   125         /// This value is used to *read* the dither cache; it may be 0
   126         /// if dithering is disabled.
   127         kDitherStride32 = kCache32Count,
   128         kDitherStride16 = kCache16Count,
   129     };
   132 protected:
   133     SkGradientShaderBase(SkReadBuffer& );
   134     virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
   135     SK_TO_STRING_OVERRIDE()
   137     SkUnitMapper* fMapper;
   138     SkMatrix    fPtsToUnit;     // set by subclass
   139     SkMatrix    fDstToIndex;
   140     SkMatrix::MapXYProc fDstToIndexProc;
   141     TileMode    fTileMode;
   142     TileProc    fTileProc;
   143     int         fColorCount;
   144     uint8_t     fDstToIndexClass;
   145     uint8_t     fFlags;
   146     uint8_t     fGradFlags;
   148     struct Rec {
   149         SkFixed     fPos;   // 0...1
   150         uint32_t    fScale; // (1 << 24) / range
   151     };
   152     Rec*        fRecs;
   154     const uint16_t*     getCache16() const;
   155     const SkPMColor*    getCache32() const;
   157     void commonAsAGradient(GradientInfo*) const;
   159 private:
   160     enum {
   161         kColorStorageCount = 4, // more than this many colors, and we'll use sk_malloc for the space
   163         kStorageSize = kColorStorageCount * (sizeof(SkColor) + sizeof(Rec))
   164     };
   165     SkColor     fStorage[(kStorageSize + 3) >> 2];
   166     SkColor*    fOrigColors; // original colors, before modulation by paint in setContext
   167     bool        fColorsAreOpaque;
   169     mutable uint16_t*   fCache16;   // working ptr. If this is NULL, we need to recompute the cache values
   170     mutable SkPMColor*  fCache32;   // working ptr. If this is NULL, we need to recompute the cache values
   172     mutable uint16_t*   fCache16Storage;    // storage for fCache16, allocated on demand
   173     mutable SkMallocPixelRef* fCache32PixelRef;
   174     mutable unsigned    fCacheAlpha;        // the alpha value we used when we computed the cache. larger than 8bits so we can store uninitialized value
   176     static void Build16bitCache(uint16_t[], SkColor c0, SkColor c1, int count);
   177     static void Build32bitCache(SkPMColor[], SkColor c0, SkColor c1, int count,
   178                                 U8CPU alpha, uint32_t gradFlags);
   179     void setCacheAlpha(U8CPU alpha) const;
   180     void initCommon();
   182     typedef SkShader INHERITED;
   183 };
   185 static inline int init_dither_toggle(int x, int y) {
   186     x &= 1;
   187     y = (y & 1) << 1;
   188     return (x | y) * SkGradientShaderBase::kDitherStride32;
   189 }
   191 static inline int next_dither_toggle(int toggle) {
   192     return toggle ^ SkGradientShaderBase::kDitherStride32;
   193 }
   195 static inline int init_dither_toggle16(int x, int y) {
   196     return ((x ^ y) & 1) * SkGradientShaderBase::kDitherStride16;
   197 }
   199 static inline int next_dither_toggle16(int toggle) {
   200     return toggle ^ SkGradientShaderBase::kDitherStride16;
   201 }
   203 ///////////////////////////////////////////////////////////////////////////////
   205 #if SK_SUPPORT_GPU
   207 #include "GrCoordTransform.h"
   208 #include "gl/GrGLEffect.h"
   210 class GrEffectStage;
   211 class GrBackendEffectFactory;
   213 /*
   214  * The interpretation of the texture matrix depends on the sample mode. The
   215  * texture matrix is applied both when the texture coordinates are explicit
   216  * and  when vertex positions are used as texture  coordinates. In the latter
   217  * case the texture matrix is applied to the pre-view-matrix position
   218  * values.
   219  *
   220  * Normal SampleMode
   221  *  The post-matrix texture coordinates are in normalize space with (0,0) at
   222  *  the top-left and (1,1) at the bottom right.
   223  * RadialGradient
   224  *  The matrix specifies the radial gradient parameters.
   225  *  (0,0) in the post-matrix space is center of the radial gradient.
   226  * Radial2Gradient
   227  *   Matrix transforms to space where first circle is centered at the
   228  *   origin. The second circle will be centered (x, 0) where x may be
   229  *   0 and is provided by setRadial2Params. The post-matrix space is
   230  *   normalized such that 1 is the second radius - first radius.
   231  * SweepGradient
   232  *  The angle from the origin of texture coordinates in post-matrix space
   233  *  determines the gradient value.
   234  */
   236  class GrTextureStripAtlas;
   238 // Base class for Gr gradient effects
   239 class GrGradientEffect : public GrEffect {
   240 public:
   242     GrGradientEffect(GrContext* ctx,
   243                      const SkGradientShaderBase& shader,
   244                      const SkMatrix& matrix,
   245                      SkShader::TileMode tileMode);
   247     virtual ~GrGradientEffect();
   249     bool useAtlas() const { return SkToBool(-1 != fRow); }
   250     SkScalar getYCoord() const { return fYCoord; };
   252     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
   254     enum ColorType {
   255         kTwo_ColorType,
   256         kThree_ColorType,
   257         kTexture_ColorType
   258     };
   260     ColorType getColorType() const { return fColorType; }
   262     enum PremulType {
   263         kBeforeInterp_PremulType,
   264         kAfterInterp_PremulType,
   265     };
   267     PremulType getPremulType() const { return fPremulType; }
   269     const SkColor* getColors(int pos) const {
   270         SkASSERT(fColorType != kTexture_ColorType);
   271         SkASSERT((pos-1) <= fColorType);
   272         return &fColors[pos];
   273     }
   275 protected:
   277     /** Populates a pair of arrays with colors and stop info to construct a random gradient.
   278         The function decides whether stop values should be used or not. The return value indicates
   279         the number of colors, which will be capped by kMaxRandomGradientColors. colors should be
   280         sized to be at least kMaxRandomGradientColors. stops is a pointer to an array of at least
   281         size kMaxRandomGradientColors. It may be updated to NULL, indicating that NULL should be
   282         passed to the gradient factory rather than the array.
   283     */
   284     static const int kMaxRandomGradientColors = 4;
   285     static int RandomGradientParams(SkRandom* r,
   286                                     SkColor colors[kMaxRandomGradientColors],
   287                                     SkScalar** stops,
   288                                     SkShader::TileMode* tm);
   290     virtual bool onIsEqual(const GrEffect& effect) const SK_OVERRIDE;
   292     const GrCoordTransform& getCoordTransform() const { return fCoordTransform; }
   294 private:
   295     static const GrCoordSet kCoordSet = kLocal_GrCoordSet;
   297     enum {
   298         kMaxAnalyticColors = 3 // if more colors use texture
   299     };
   301     GrCoordTransform fCoordTransform;
   302     GrTextureAccess fTextureAccess;
   303     SkScalar fYCoord;
   304     GrTextureStripAtlas* fAtlas;
   305     int fRow;
   306     bool fIsOpaque;
   307     ColorType fColorType;
   308     SkColor fColors[kMaxAnalyticColors];
   309     PremulType fPremulType; // This only changes behavior for two and three color special cases.
   310                             // It is already baked into to the table for texture gradients.
   311     typedef GrEffect INHERITED;
   313 };
   315 ///////////////////////////////////////////////////////////////////////////////
   317 // Base class for GL gradient effects
   318 class GrGLGradientEffect : public GrGLEffect {
   319 public:
   320     GrGLGradientEffect(const GrBackendEffectFactory& factory);
   321     virtual ~GrGLGradientEffect();
   323     virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE;
   325 protected:
   326     enum {
   327         kPremulTypeKeyBitCnt = 1,
   328         kPremulTypeMask = 1,
   329         kPremulBeforeInterpKey = kPremulTypeMask,
   331         kTwoColorKey = 2 << kPremulTypeKeyBitCnt,
   332         kThreeColorKey = 3 << kPremulTypeKeyBitCnt,
   333         kColorKeyMask = kTwoColorKey | kThreeColorKey,
   334         kColorKeyBitCnt = 2,
   336         // Subclasses must shift any key bits they produce up by this amount
   337         // and combine with the result of GenBaseGradientKey.
   338         kBaseKeyBitCnt = (kPremulTypeKeyBitCnt + kColorKeyBitCnt)
   339     };
   341     static GrGradientEffect::ColorType ColorTypeFromKey(EffectKey key){
   342         if (kTwoColorKey == (key & kColorKeyMask)) {
   343             return GrGradientEffect::kTwo_ColorType;
   344         } else if (kThreeColorKey == (key & kColorKeyMask)) {
   345             return GrGradientEffect::kThree_ColorType;
   346         } else {return GrGradientEffect::kTexture_ColorType;}
   347     }
   349     static GrGradientEffect::PremulType PremulTypeFromKey(EffectKey key){
   350         if (kPremulBeforeInterpKey == (key & kPremulTypeMask)) {
   351             return GrGradientEffect::kBeforeInterp_PremulType;
   352         } else {
   353             return GrGradientEffect::kAfterInterp_PremulType;
   354         }
   355     }
   357     /**
   358      * Subclasses must call this. It will return a value restricted to the lower kBaseKeyBitCnt
   359      * bits.
   360      */
   361     static EffectKey GenBaseGradientKey(const GrDrawEffect&);
   363     // Emits the uniform used as the y-coord to texture samples in derived classes. Subclasses
   364     // should call this method from their emitCode().
   365     void emitUniforms(GrGLShaderBuilder* builder, EffectKey key);
   368     // emit code that gets a fragment's color from an expression for t; Has branches for 3 separate
   369     // control flows inside -- 2 color gradients, 3 color symmetric gradients (both using
   370     // native GLSL mix), and 4+ color gradients that use the traditional texture lookup.
   371     void emitColor(GrGLShaderBuilder* builder,
   372                    const char* gradientTValue,
   373                    EffectKey key,
   374                    const char* outputColor,
   375                    const char* inputColor,
   376                    const TextureSamplerArray& samplers);
   378 private:
   379     SkScalar fCachedYCoord;
   380     GrGLUniformManager::UniformHandle fFSYUni;
   381     GrGLUniformManager::UniformHandle fColorStartUni;
   382     GrGLUniformManager::UniformHandle fColorMidUni;
   383     GrGLUniformManager::UniformHandle fColorEndUni;
   385     typedef GrGLEffect INHERITED;
   386 };
   388 #endif
   390 #endif

mercurial