Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #ifndef GrSamplerState_DEFINED
     12 #define GrSamplerState_DEFINED
     13 
     14 #include "GrTypes.h"
     15 #include "GrMatrix.h"
     16 
     17 #define MAX_KERNEL_WIDTH 25
     18 
     19 class GrSamplerState {
     20 public:
     21     enum Filter {
     22         /**
     23          * Read the closest src texel to the sample position
     24          */
     25         kNearest_Filter,
     26         /**
     27          * Blend between closest 4 src texels to sample position (tent filter)
     28          */
     29         kBilinear_Filter,
     30         /**
     31          * Average of 4 bilinear filterings spaced +/- 1 texel from sample
     32          * position in x and y. Intended for averaging 16 texels in a downsample
     33          * pass. (rasterizing such that texture samples fall exactly halfway
     34          * between texels in x and y spaced 4 texels apart.) Only supported
     35          * on shader backends.
     36          */
     37         k4x4Downsample_Filter,
     38         /**
     39          * Apply a separable convolution kernel.
     40          */
     41         kConvolution_Filter,
     42         /**
     43          * Apply a dilate filter (max over a 1D radius).
     44          */
     45         kDilate_Filter,
     46         /**
     47          * Apply an erode filter (min over a 1D radius).
     48          */
     49         kErode_Filter,
     50 
     51         kDefault_Filter = kNearest_Filter
     52     };
     53 
     54     /**
     55      * The intepretation of the texture matrix depends on the sample mode. The
     56      * texture matrix is applied both when the texture coordinates are explicit
     57      * and  when vertex positions are used as texture  coordinates. In the latter
     58      * case the texture matrix is applied to the pre-view-matrix position
     59      * values.
     60      *
     61      * kNormal_SampleMode
     62      *  The post-matrix texture coordinates are in normalize space with (0,0) at
     63      *  the top-left and (1,1) at the bottom right.
     64      * kRadial_SampleMode
     65      *  The matrix specifies the radial gradient parameters.
     66      *  (0,0) in the post-matrix space is center of the radial gradient.
     67      * kRadial2_SampleMode
     68      *   Matrix transforms to space where first circle is centered at the
     69      *   origin. The second circle will be centered (x, 0) where x may be
     70      *   0 and is provided by setRadial2Params. The post-matrix space is
     71      *   normalized such that 1 is the second radius - first radius.
     72      * kSweepSampleMode
     73      *  The angle from the origin of texture coordinates in post-matrix space
     74      *  determines the gradient value.
     75      */
     76     enum SampleMode {
     77         kNormal_SampleMode,     //!< sample color directly
     78         kRadial_SampleMode,     //!< treat as radial gradient
     79         kRadial2_SampleMode,    //!< treat as 2-point radial gradient
     80         kSweep_SampleMode,      //!< treat as sweep gradient
     81 
     82         kDefault_SampleMode = kNormal_SampleMode
     83     };
     84 
     85     /**
     86      * Describes how a texture is sampled when coordinates are outside the
     87      * texture border
     88      */
     89     enum WrapMode {
     90         kClamp_WrapMode,
     91         kRepeat_WrapMode,
     92         kMirror_WrapMode,
     93 
     94         kDefault_WrapMode = kClamp_WrapMode
     95     };
     96 
     97     /**
     98      * For the filters which perform more than one texture sample (convolution,
     99      * erode, dilate), this determines the direction in which the texture
    100      * coordinates will be incremented.
    101      */
    102     enum FilterDirection {
    103         kX_FilterDirection,
    104         kY_FilterDirection,
    105 
    106         kDefault_FilterDirection = kX_FilterDirection,
    107     };
    108     /**
    109      * Default sampler state is set to clamp, use normal sampling mode, be
    110      * unfiltered, and use identity matrix.
    111      */
    112     GrSamplerState()
    113     : fRadial2CenterX1()
    114     , fRadial2Radius0()
    115     , fRadial2PosRoot() {
    116         this->reset();
    117     }
    118 
    119     WrapMode getWrapX() const { return fWrapX; }
    120     WrapMode getWrapY() const { return fWrapY; }
    121     FilterDirection getFilterDirection() const { return fFilterDirection; }
    122     SampleMode getSampleMode() const { return fSampleMode; }
    123     const GrMatrix& getMatrix() const { return fMatrix; }
    124     const GrRect& getTextureDomain() const { return fTextureDomain; }
    125     bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
    126     Filter getFilter() const { return fFilter; }
    127     int getKernelWidth() const { return fKernelWidth; }
    128     const float* getKernel() const { return fKernel; }
    129     bool swapsRAndB() const { return fSwapRAndB; }
    130 
    131     bool isGradient() const {
    132         return  kRadial_SampleMode == fSampleMode ||
    133                 kRadial2_SampleMode == fSampleMode ||
    134                 kSweep_SampleMode == fSampleMode;
    135     }
    136 
    137     void setWrapX(WrapMode mode) { fWrapX = mode; }
    138     void setWrapY(WrapMode mode) { fWrapY = mode; }
    139     void setSampleMode(SampleMode mode) { fSampleMode = mode; }
    140     void setFilterDirection(FilterDirection mode) { fFilterDirection = mode; }
    141 
    142     /**
    143      * Access the sampler's matrix. See SampleMode for explanation of
    144      * relationship between the matrix and sample mode.
    145      */
    146     GrMatrix* matrix() { return &fMatrix; }
    147 
    148     /**
    149      * Sets the sampler's texture coordinate domain to a
    150      * custom rectangle, rather than the default (0,1).
    151      * This option is currently only supported with kClamp_WrapMode
    152      */
    153     void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }
    154 
    155     /**
    156      * Swaps the R and B components when reading from the texture. Has no effect
    157      * if the texture is alpha only.
    158      */
    159     void setRAndBSwap(bool swap) { fSwapRAndB = swap; }
    160 
    161     /**
    162      *  Multiplies the current sampler matrix  a matrix
    163      *
    164      *  After this call M' = M*m where M is the old matrix, m is the parameter
    165      *  to this function, and M' is the new matrix. (We consider points to
    166      *  be column vectors so tex cood vector t is transformed by matrix X as
    167      *  t' = X*t.)
    168      *
    169      *  @param matrix   the matrix used to modify the matrix.
    170      */
    171     void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }
    172 
    173     /**
    174      * Sets filtering type.
    175      * @param filter    type of filtering to apply
    176      */
    177     void setFilter(Filter filter) { fFilter = filter; }
    178 
    179     void reset(WrapMode wrapXAndY,
    180                Filter filter,
    181                FilterDirection direction,
    182                const GrMatrix& matrix) {
    183         fWrapX = wrapXAndY;
    184         fWrapY = wrapXAndY;
    185         fSampleMode = kDefault_SampleMode;
    186         fFilter = filter;
    187         fFilterDirection = direction;
    188         fMatrix = matrix;
    189         fTextureDomain.setEmpty();
    190         fSwapRAndB = false;
    191     }
    192     void reset(WrapMode wrapXAndY, Filter filter, const GrMatrix& matrix) {
    193         this->reset(wrapXAndY, filter, kDefault_FilterDirection, matrix);
    194     }
    195     void reset(WrapMode wrapXAndY,
    196                Filter filter) {
    197         this->reset(wrapXAndY, filter, kDefault_FilterDirection, GrMatrix::I());
    198     }
    199     void reset(const GrMatrix& matrix) {
    200         this->reset(kDefault_WrapMode, kDefault_Filter, kDefault_FilterDirection, matrix);
    201     }
    202     void reset() {
    203         this->reset(kDefault_WrapMode, kDefault_Filter, kDefault_FilterDirection, GrMatrix::I());
    204     }
    205 
    206     GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
    207     GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
    208     bool     isRadial2PosRoot() const { return SkToBool(fRadial2PosRoot); }
    209     // do the radial gradient params lead to a linear (rather than quadratic)
    210     // equation.
    211     bool radial2IsDegenerate() const { return GR_Scalar1 == fRadial2CenterX1; }
    212 
    213     /**
    214      * Sets the parameters for kRadial2_SampleMode. The texture
    215      * matrix must be set so that the first point is at (0,0) and the second
    216      * point lies on the x-axis. The second radius minus the first is 1 unit.
    217      * The additional parameters to define the gradient are specified by this
    218      * function.
    219      */
    220     void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
    221         fRadial2CenterX1 = centerX1;
    222         fRadial2Radius0 = radius0;
    223         fRadial2PosRoot = posRoot;
    224     }
    225 
    226     void setConvolutionParams(int kernelWidth, const float* kernel) {
    227         GrAssert(kernelWidth >= 0 && kernelWidth <= MAX_KERNEL_WIDTH);
    228         fKernelWidth = kernelWidth;
    229         if (NULL != kernel) {
    230             memcpy(fKernel, kernel, kernelWidth * sizeof(float));
    231         }
    232     }
    233 
    234     void setMorphologyRadius(int radius) {
    235         GrAssert(radius >= 0 && radius <= MAX_KERNEL_WIDTH);
    236         fKernelWidth = radius;
    237     }
    238 
    239 private:
    240     WrapMode            fWrapX : 8;
    241     WrapMode            fWrapY : 8;
    242     FilterDirection     fFilterDirection : 8;
    243     SampleMode          fSampleMode : 8;
    244     Filter              fFilter : 8;
    245     GrMatrix            fMatrix;
    246     bool                fSwapRAndB;
    247     GrRect              fTextureDomain;
    248 
    249     // these are undefined unless fSampleMode == kRadial2_SampleMode
    250     GrScalar            fRadial2CenterX1;
    251     GrScalar            fRadial2Radius0;
    252     SkBool8             fRadial2PosRoot;
    253 
    254     // These are undefined unless fFilter == kConvolution_Filter
    255     uint8_t             fKernelWidth;
    256     float               fKernel[MAX_KERNEL_WIDTH];
    257 };
    258 
    259 #endif
    260 
    261