GrDrawState.h revision 972265db219ce25b5159879c75e6c62efaf0fa79
1/*
2 * Copyright 2011 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 GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
11#include "GrColor.h"
12#include "GrMatrix.h"
13#include "GrNoncopyable.h"
14#include "GrRefCnt.h"
15#include "GrSamplerState.h"
16#include "GrStencil.h"
17#include "GrTexture.h"
18
19#include "SkXfermode.h"
20
21class GrRenderTarget;
22class GrTexture;
23
24class GrDrawState : public GrRefCnt {
25
26public:
27    /**
28     * Number of texture stages. Each stage takes as input a color and
29     * 2D texture coordinates. The color input to the first enabled stage is the
30     * per-vertex color or the constant color (setColor/setAlpha) if there are
31     * no per-vertex colors. For subsequent stages the input color is the output
32     * color from the previous enabled stage. The output color of each stage is
33     * the input color modulated with the result of a texture lookup. Texture
34     * lookups are specified by a texture a sampler (setSamplerState). Texture
35     * coordinates for each stage come from the vertices based on a
36     * GrVertexLayout bitfield. The output fragment color is the output color of
37     * the last enabled stage. The presence or absence of texture coordinates
38     * for each stage in the vertex layout indicates whether a stage is enabled
39     * or not.
40     *
41     * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
42     * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
43     * through kNumStages-1 are earmarked for use by GrTextContext and
44     * GrPathRenderer-derived classes.
45     */
46    enum {
47        kNumStages = 4,
48        kMaxTexCoords = kNumStages
49    };
50
51    /**
52     *  Bitfield used to indicate a set of stages.
53     */
54    typedef uint32_t StageMask;
55    GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
56
57    GrDrawState() {
58        this->reset();
59    }
60
61    GrDrawState(const GrDrawState& state) {
62        *this = state;
63    }
64
65    /**
66     * Resets to the default state. Sampler states will not be modified.
67     */
68    void reset() {
69        // make sure any pad is zero for memcmp
70        // all GrDrawState members should default to something valid by the
71        // the memset except those initialized individually below. There should
72        // be no padding between the individually initialized members.
73        memset(this->podStart(), 0, this->memsetSize());
74
75        // pedantic assertion that our ptrs will
76        // be NULL (0 ptr is mem addr 0)
77        GrAssert((intptr_t)(void*)NULL == 0LL);
78        GR_STATIC_ASSERT(0 == kBoth_DrawFace);
79        GrAssert(fStencilSettings.isDisabled());
80
81        // memset exceptions
82        fColor = 0xffffffff;
83        fCoverage = 0xffffffff;
84        fFirstCoverageStage = kNumStages;
85        fColorFilterMode = SkXfermode::kDst_Mode;
86        fSrcBlend = kOne_GrBlendCoeff;
87        fDstBlend = kZero_GrBlendCoeff;
88        fViewMatrix.reset();
89        fBehaviorBits = 0;
90
91        // ensure values that will be memcmp'ed in == but not memset in reset()
92        // are tightly packed
93        GrAssert(this->memsetSize() +  sizeof(fColor) + sizeof(fCoverage) +
94                 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
95                 sizeof(fSrcBlend) + sizeof(fDstBlend) ==
96                 this->podSize());
97    }
98
99    ///////////////////////////////////////////////////////////////////////////
100    /// @name Color
101    ////
102
103    /**
104     *  Sets color for next draw to a premultiplied-alpha color.
105     *
106     *  @param color    the color to set.
107     */
108    void setColor(GrColor color) { fColor = color; }
109
110    GrColor getColor() const { return fColor; }
111
112    /**
113     *  Sets the color to be used for the next draw to be
114     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
115     *
116     *  @param alpha The alpha value to set as the color.
117     */
118    void setAlpha(uint8_t a) {
119        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
120    }
121
122    /**
123     * Add a color filter that can be represented by a color and a mode. Applied
124     * after color-computing texture stages.
125     */
126    void setColorFilter(GrColor c, SkXfermode::Mode mode) {
127        fColorFilterColor = c;
128        fColorFilterMode = mode;
129    }
130
131    GrColor getColorFilterColor() const { return fColorFilterColor; }
132    SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
133
134    /// @}
135
136    ///////////////////////////////////////////////////////////////////////////
137    /// @name Coverage
138    ////
139
140    /**
141     * Sets a constant fractional coverage to be applied to the draw. The
142     * initial value (after construction or reset()) is 0xff. The constant
143     * coverage is ignored when per-vertex coverage is provided.
144     */
145    void setCoverage(uint8_t coverage) {
146        fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
147    }
148
149    /**
150     * Version of above that specifies 4 channel per-vertex color. The value
151     * should be premultiplied.
152     */
153    void setCoverage4(GrColor coverage) {
154        fCoverage = coverage;
155    }
156
157    GrColor getCoverage() const {
158        return fCoverage;
159    }
160
161    /// @}
162
163    ///////////////////////////////////////////////////////////////////////////
164    /// @name Textures
165    ////
166
167    /**
168     * Sets the texture used at the next drawing call
169     *
170     * @param stage The texture stage for which the texture will be set
171     *
172     * @param texture The texture to set. Can be NULL though there is no
173     * advantage to settings a NULL texture if doing non-textured drawing
174     */
175    void setTexture(int stage, GrTexture* texture) {
176        GrAssert((unsigned)stage < kNumStages);
177
178        if (isBehaviorEnabled(kTexturesNeedRef_BehaviorBit)) {
179            // If we don't clear out the current texture before unreffing
180            // it we can get into an infinite loop as the GrGLTexture's
181            // onRelease method recursively calls setTexture
182            GrTexture* temp = fTextures[stage];
183            fTextures[stage] = NULL;
184
185            SkSafeRef(texture);
186            SkSafeUnref(temp);
187        }
188
189        fTextures[stage] = texture;
190    }
191
192    /**
193     * Retrieves the currently set texture.
194     *
195     * @return    The currently set texture. The return value will be NULL if no
196     *            texture has been set, NULL was most recently passed to
197     *            setTexture, or the last setTexture was destroyed.
198     */
199    const GrTexture* getTexture(int stage) const {
200        GrAssert((unsigned)stage < kNumStages);
201        return fTextures[stage];
202    }
203    GrTexture* getTexture(int stage) {
204        GrAssert((unsigned)stage < kNumStages);
205        return fTextures[stage];
206    }
207
208    /**
209     * Release all the textures referred to by this draw state
210     */
211    void releaseTextures() {
212        for (int i = 0; i < kNumStages; ++i) {
213            this->setTexture(i, NULL);
214        }
215    }
216
217    class AutoTextureRelease : public ::GrNoncopyable {
218    public:
219        AutoTextureRelease(GrDrawState* ds) : fDrawState(ds) {}
220        ~AutoTextureRelease() {
221            if (NULL != fDrawState) {
222                fDrawState->releaseTextures();
223            }
224        }
225    private:
226        GrDrawState* fDrawState;
227    };
228
229    /// @}
230
231    ///////////////////////////////////////////////////////////////////////////
232    /// @name Samplers
233    ////
234
235    /**
236     * Returns the current sampler for a stage.
237     */
238    const GrSamplerState& getSampler(int stage) const {
239        GrAssert((unsigned)stage < kNumStages);
240        return fSamplerStates[stage];
241    }
242
243    /**
244     * Writable pointer to a stage's sampler.
245     */
246    GrSamplerState* sampler(int stage) {
247        GrAssert((unsigned)stage < kNumStages);
248        return fSamplerStates + stage;
249    }
250
251    /**
252     * Preconcats the matrix of all samplers in the mask with the same matrix.
253     */
254    void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
255        GrAssert(!(stageMask & kIllegalStageMaskBits));
256        for (int i = 0; i < kNumStages; ++i) {
257            if ((1 << i) & stageMask) {
258                fSamplerStates[i].preConcatMatrix(matrix);
259            }
260        }
261    }
262
263    /// @}
264
265    ///////////////////////////////////////////////////////////////////////////
266    /// @name Coverage / Color Stages
267    ////
268
269    /**
270     * A common pattern is to compute a color with the initial stages and then
271     * modulate that color by a coverage value in later stage(s) (AA, mask-
272     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
273     * computed based on the pre-coverage-modulated color. The division of
274     * stages between color-computing and coverage-computing is specified by
275     * this method. Initially this is kNumStages (all stages
276     * are color-computing).
277     */
278    void setFirstCoverageStage(int firstCoverageStage) {
279        GrAssert((unsigned)firstCoverageStage <= kNumStages);
280        fFirstCoverageStage = firstCoverageStage;
281    }
282
283    /**
284     * Gets the index of the first coverage-computing stage.
285     */
286    int getFirstCoverageStage() const {
287        return fFirstCoverageStage;
288    }
289
290    ///@}
291
292    ///////////////////////////////////////////////////////////////////////////
293    /// @name Blending
294    ////
295
296    /**
297     * Sets the blending function coeffecients.
298     *
299     * The blend function will be:
300     *    D' = sat(S*srcCoef + D*dstCoef)
301     *
302     *   where D is the existing destination color, S is the incoming source
303     *   color, and D' is the new destination color that will be written. sat()
304     *   is the saturation function.
305     *
306     * @param srcCoef coeffecient applied to the src color.
307     * @param dstCoef coeffecient applied to the dst color.
308     */
309    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
310        fSrcBlend = srcCoeff;
311        fDstBlend = dstCoeff;
312    #if GR_DEBUG
313        switch (dstCoeff) {
314        case kDC_GrBlendCoeff:
315        case kIDC_GrBlendCoeff:
316        case kDA_GrBlendCoeff:
317        case kIDA_GrBlendCoeff:
318            GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
319                     "coverage stages.\n");
320            break;
321        default:
322            break;
323        }
324        switch (srcCoeff) {
325        case kSC_GrBlendCoeff:
326        case kISC_GrBlendCoeff:
327        case kSA_GrBlendCoeff:
328        case kISA_GrBlendCoeff:
329            GrPrintf("Unexpected src blend coeff. Won't work correctly with"
330                     "coverage stages.\n");
331            break;
332        default:
333            break;
334        }
335    #endif
336    }
337
338    GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
339    GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
340
341    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
342                          GrBlendCoeff* dstBlendCoeff) const {
343        *srcBlendCoeff = fSrcBlend;
344        *dstBlendCoeff = fDstBlend;
345    }
346
347    /**
348     * Sets the blending function constant referenced by the following blending
349     * coeffecients:
350     *      kConstC_GrBlendCoeff
351     *      kIConstC_GrBlendCoeff
352     *      kConstA_GrBlendCoeff
353     *      kIConstA_GrBlendCoeff
354     *
355     * @param constant the constant to set
356     */
357    void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
358
359    /**
360     * Retrieves the last value set by setBlendConstant()
361     * @return the blending constant value
362     */
363    GrColor getBlendConstant() const { return fBlendConstant; }
364
365    /// @}
366
367    ///////////////////////////////////////////////////////////////////////////
368    /// @name View Matrix
369    ////
370
371    /**
372     * Sets the matrix applied to vertex positions.
373     *
374     * In the post-view-matrix space the rectangle [0,w]x[0,h]
375     * fully covers the render target. (w and h are the width and height of the
376     * the rendertarget.)
377     */
378    void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
379
380    /**
381     * Gets a writable pointer to the view matrix.
382     */
383    GrMatrix* viewMatrix() { return &fViewMatrix; }
384
385    /**
386     *  Multiplies the current view matrix by a matrix
387     *
388     *  After this call V' = V*m where V is the old view matrix,
389     *  m is the parameter to this function, and V' is the new view matrix.
390     *  (We consider positions to be column vectors so position vector p is
391     *  transformed by matrix X as p' = X*p.)
392     *
393     *  @param m the matrix used to modify the view matrix.
394     */
395    void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
396
397    /**
398     *  Multiplies the current view matrix by a matrix
399     *
400     *  After this call V' = m*V where V is the old view matrix,
401     *  m is the parameter to this function, and V' is the new view matrix.
402     *  (We consider positions to be column vectors so position vector p is
403     *  transformed by matrix X as p' = X*p.)
404     *
405     *  @param m the matrix used to modify the view matrix.
406     */
407    void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
408
409    /**
410     * Retrieves the current view matrix
411     * @return the current view matrix.
412     */
413    const GrMatrix& getViewMatrix() const { return fViewMatrix; }
414
415    /**
416     *  Retrieves the inverse of the current view matrix.
417     *
418     *  If the current view matrix is invertible, return true, and if matrix
419     *  is non-null, copy the inverse into it. If the current view matrix is
420     *  non-invertible, return false and ignore the matrix parameter.
421     *
422     * @param matrix if not null, will receive a copy of the current inverse.
423     */
424    bool getViewInverse(GrMatrix* matrix) const {
425        // TODO: determine whether we really need to leave matrix unmodified
426        // at call sites when inversion fails.
427        GrMatrix inverse;
428        if (fViewMatrix.invert(&inverse)) {
429            if (matrix) {
430                *matrix = inverse;
431            }
432            return true;
433        }
434        return false;
435    }
436
437    class AutoViewMatrixRestore : public ::GrNoncopyable {
438    public:
439        AutoViewMatrixRestore() : fDrawState(NULL) {}
440        AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
441            fDrawState = NULL;
442            this->set(ds, newMatrix);
443        }
444        AutoViewMatrixRestore(GrDrawState* ds) {
445            fDrawState = NULL;
446            this->set(ds);
447        }
448        ~AutoViewMatrixRestore() {
449            this->set(NULL, GrMatrix::I());
450        }
451        void set(GrDrawState* ds, const GrMatrix& newMatrix) {
452            if (NULL != fDrawState) {
453                fDrawState->setViewMatrix(fSavedMatrix);
454            }
455            if (NULL != ds) {
456                fSavedMatrix = ds->getViewMatrix();
457                ds->setViewMatrix(newMatrix);
458            }
459            fDrawState = ds;
460        }
461        void set(GrDrawState* ds) {
462            if (NULL != fDrawState) {
463                fDrawState->setViewMatrix(fSavedMatrix);
464            }
465            if (NULL != ds) {
466                fSavedMatrix = ds->getViewMatrix();
467            }
468            fDrawState = ds;
469        }
470    private:
471        GrDrawState* fDrawState;
472        GrMatrix fSavedMatrix;
473    };
474
475    /// @}
476
477    ///////////////////////////////////////////////////////////////////////////
478    /// @name Render Target
479    ////
480
481    /**
482     * Sets the rendertarget used at the next drawing call
483     *
484     * @param target  The render target to set.
485     */
486    void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
487
488    /**
489     * Retrieves the currently set rendertarget.
490     *
491     * @return    The currently set render target.
492     */
493    const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
494    GrRenderTarget* getRenderTarget() { return fRenderTarget; }
495
496    class AutoRenderTargetRestore : public ::GrNoncopyable {
497    public:
498        AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
499        AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
500            fDrawState = NULL;
501            fSavedTarget = NULL;
502            this->set(ds, newTarget);
503        }
504        ~AutoRenderTargetRestore() { this->set(NULL, NULL); }
505        void set(GrDrawState* ds, GrRenderTarget* newTarget) {
506            if (NULL != fDrawState) {
507                fDrawState->setRenderTarget(fSavedTarget);
508            }
509            if (NULL != ds) {
510                fSavedTarget = ds->getRenderTarget();
511                ds->setRenderTarget(newTarget);
512            }
513            fDrawState = ds;
514        }
515    private:
516        GrDrawState* fDrawState;
517        GrRenderTarget* fSavedTarget;
518    };
519
520    /// @}
521
522    ///////////////////////////////////////////////////////////////////////////
523    /// @name Stencil
524    ////
525
526    /**
527     * Sets the stencil settings to use for the next draw.
528     * Changing the clip has the side-effect of possibly zeroing
529     * out the client settable stencil bits. So multipass algorithms
530     * using stencil should not change the clip between passes.
531     * @param settings  the stencil settings to use.
532     */
533    void setStencil(const GrStencilSettings& settings) {
534        fStencilSettings = settings;
535    }
536
537    /**
538     * Shortcut to disable stencil testing and ops.
539     */
540    void disableStencil() {
541        fStencilSettings.setDisabled();
542    }
543
544    const GrStencilSettings& getStencil() const { return fStencilSettings; }
545
546    GrStencilSettings* stencil() { return &fStencilSettings; }
547
548    /// @}
549
550    ///////////////////////////////////////////////////////////////////////////
551    /// @name Color Matrix
552    ////
553
554    /**
555     * Sets the color matrix to use for the next draw.
556     * @param matrix  the 5x4 matrix to apply to the incoming color
557     */
558    void setColorMatrix(const float matrix[20]) {
559        memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
560    }
561
562    const float* getColorMatrix() const { return fColorMatrix; }
563
564    /// @}
565
566    ///////////////////////////////////////////////////////////////////////////
567    // @name Edge AA
568    // Edge equations can be specified to perform antialiasing. Because the
569    // edges are specified as per-vertex data, vertices that are shared by
570    // multiple edges must be split.
571    //
572    ////
573
574    /**
575     * When specifying edges as vertex data this enum specifies what type of
576     * edges are in use. The edges are always 4 GrScalars in memory, even when
577     * the edge type requires fewer than 4.
578     *
579     * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
580     *       (either adjust in VS or use origin_upper_left in GLSL)
581     */
582    enum VertexEdgeType {
583        /* 1-pixel wide line
584           2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
585        kHairLine_EdgeType,
586        /* Quadratic specified by u^2-v canonical coords (only 2
587           components used). Coverage based on signed distance with negative
588           being inside, positive outside. Edge specified in window space
589           (y-down) */
590        kQuad_EdgeType,
591        /* Same as above but for hairline quadratics. Uses unsigned distance.
592           Coverage is min(0, 1-distance). */
593        kHairQuad_EdgeType,
594        /* Circle specified as center_x, center_y, outer_radius, inner_radius
595           all in window space (y-down). */
596        kCircle_EdgeType,
597
598        kVertexEdgeTypeCnt
599    };
600
601    /**
602     * Determines the interpretation per-vertex edge data when the
603     * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
604     * are not specified the value of this setting has no effect.
605     */
606    void setVertexEdgeType(VertexEdgeType type) {
607        GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
608        fVertexEdgeType = type;
609    }
610
611    VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
612
613    /// @}
614
615    ///////////////////////////////////////////////////////////////////////////
616    /// @name State Flags
617    ////
618
619    /**
620     *  Flags that affect rendering. Controlled using enable/disableState(). All
621     *  default to disabled.
622     */
623    enum StateBits {
624        /**
625         * Perform dithering. TODO: Re-evaluate whether we need this bit
626         */
627        kDither_StateBit        = 0x01,
628        /**
629         * Perform HW anti-aliasing. This means either HW FSAA, if supported
630         * by the render target, or smooth-line rendering if a line primitive
631         * is drawn and line smoothing is supported by the 3D API.
632         */
633        kHWAntialias_StateBit   = 0x02,
634        /**
635         * Draws will respect the clip, otherwise the clip is ignored.
636         */
637        kClip_StateBit          = 0x04,
638        /**
639         * Disables writing to the color buffer. Useful when performing stencil
640         * operations.
641         */
642        kNoColorWrites_StateBit = 0x08,
643        /**
644         * Draws will apply the color matrix, otherwise the color matrix is
645         * ignored.
646         */
647        kColorMatrix_StateBit   = 0x20,
648
649        // Users of the class may add additional bits to the vector
650        kDummyStateBit,
651        kLastPublicStateBit = kDummyStateBit-1,
652    };
653
654    void resetStateFlags() {
655        fFlagBits = 0;
656    }
657
658    /**
659     * Enable render state settings.
660     *
661     * @param flags   bitfield of StateBits specifing the states to enable
662     */
663    void enableState(uint32_t stateBits) {
664        fFlagBits |= stateBits;
665    }
666
667    /**
668     * Disable render state settings.
669     *
670     * @param flags   bitfield of StateBits specifing the states to disable
671     */
672    void disableState(uint32_t stateBits) {
673        fFlagBits &= ~(stateBits);
674    }
675
676    bool isDitherState() const {
677        return 0 != (fFlagBits & kDither_StateBit);
678    }
679
680    bool isHWAntialiasState() const {
681        return 0 != (fFlagBits & kHWAntialias_StateBit);
682    }
683
684    bool isClipState() const {
685        return 0 != (fFlagBits & kClip_StateBit);
686    }
687
688    bool isColorWriteDisabled() const {
689        return 0 != (fFlagBits & kNoColorWrites_StateBit);
690    }
691
692    bool isStateFlagEnabled(uint32_t stateBit) const {
693        return 0 != (stateBit & fFlagBits);
694    }
695
696    /**
697     *  Flags that do not affect rendering.
698     */
699    enum GrBehaviorBits {
700        /**
701         * Calls to setTexture will ref/unref the texture
702         */
703        kTexturesNeedRef_BehaviorBit = 0x01,
704    };
705
706    void enableBehavior(uint32_t behaviorBits) {
707        fBehaviorBits |= behaviorBits;
708    }
709
710    void disableBehavior(uint32_t behaviorBits) {
711        fBehaviorBits &= ~(behaviorBits);
712    }
713
714    bool isBehaviorEnabled(uint32_t behaviorBits) const {
715        return 0 != (behaviorBits & fBehaviorBits);
716    }
717
718    /// @}
719
720    ///////////////////////////////////////////////////////////////////////////
721    /// @name Face Culling
722    ////
723
724    enum DrawFace {
725        kInvalid_DrawFace = -1,
726
727        kBoth_DrawFace,
728        kCCW_DrawFace,
729        kCW_DrawFace,
730    };
731
732    /**
733     * Controls whether clockwise, counterclockwise, or both faces are drawn.
734     * @param face  the face(s) to draw.
735     */
736    void setDrawFace(DrawFace face) {
737        GrAssert(kInvalid_DrawFace != face);
738        fDrawFace = face;
739    }
740
741    /**
742     * Gets whether the target is drawing clockwise, counterclockwise,
743     * or both faces.
744     * @return the current draw face(s).
745     */
746    DrawFace getDrawFace() const { return fDrawFace; }
747
748    /// @}
749
750    ///////////////////////////////////////////////////////////////////////////
751
752    // Most stages are usually not used, so conditionals here
753    // reduce the expected number of bytes touched by 50%.
754    bool operator ==(const GrDrawState& s) const {
755        if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
756            return false;
757        }
758
759        if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
760            return false;
761        }
762
763        // kTexturesNeedRef is an internal flag for altering the draw state's
764        // behavior rather than a property that will impact drawing - ignore it
765        // here
766        if ((fBehaviorBits & ~kTexturesNeedRef_BehaviorBit) !=
767            (s.fBehaviorBits & ~kTexturesNeedRef_BehaviorBit)) {
768            return false;
769        }
770
771        for (int i = 0; i < kNumStages; i++) {
772            if (fTextures[i] &&
773                this->fSamplerStates[i] != s.fSamplerStates[i]) {
774                return false;
775            }
776        }
777        if (kColorMatrix_StateBit & s.fFlagBits) {
778            if (memcmp(fColorMatrix,
779                        s.fColorMatrix,
780                        sizeof(fColorMatrix))) {
781                return false;
782            }
783        }
784
785        return true;
786    }
787    bool operator !=(const GrDrawState& s) const { return !(*this == s); }
788
789    // Most stages are usually not used, so conditionals here
790    // reduce the expected number of bytes touched by 50%.
791    GrDrawState& operator =(const GrDrawState& s) {
792        memcpy(this->podStart(), s.podStart(), this->podSize());
793
794        fViewMatrix = s.fViewMatrix;
795        fBehaviorBits = s.fBehaviorBits;
796
797        for (int i = 0; i < kNumStages; i++) {
798            if (s.fTextures[i]) {
799                this->fSamplerStates[i] = s.fSamplerStates[i];
800            }
801        }
802        if (kColorMatrix_StateBit & s.fFlagBits) {
803            memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
804        }
805
806        return *this;
807    }
808
809private:
810
811    const void* podStart() const {
812        return reinterpret_cast<const void*>(&fPodStartMarker);
813    }
814    void* podStart() {
815        return reinterpret_cast<void*>(&fPodStartMarker);
816    }
817    size_t memsetSize() const {
818        return reinterpret_cast<size_t>(&fMemsetEndMarker) -
819               reinterpret_cast<size_t>(&fPodStartMarker) +
820               sizeof(fMemsetEndMarker);
821    }
822    size_t podSize() const {
823        // Can't use offsetof() with non-POD types, so stuck with pointer math.
824        return reinterpret_cast<size_t>(&fPodEndMarker) -
825               reinterpret_cast<size_t>(&fPodStartMarker) +
826               sizeof(fPodEndMarker);
827    }
828
829    static const StageMask kIllegalStageMaskBits = ~((1U << kNumStages)-1);
830    // @{ these fields can be initialized with memset to 0
831    union {
832        GrColor             fBlendConstant;
833        GrColor             fPodStartMarker;
834    };
835    GrTexture*          fTextures[kNumStages];
836    GrColor             fColorFilterColor;
837    uint32_t            fFlagBits;
838    DrawFace            fDrawFace;
839    VertexEdgeType      fVertexEdgeType;
840    GrStencilSettings   fStencilSettings;
841    union {
842        GrRenderTarget* fRenderTarget;
843        GrRenderTarget* fMemsetEndMarker;
844    };
845    // @}
846
847    // @{ Initialized to values other than zero, but memcmp'ed in operator==
848    // and memcpy'ed in operator=.
849    GrColor             fColor;
850    GrColor             fCoverage;
851    int                 fFirstCoverageStage;
852    SkXfermode::Mode    fColorFilterMode;
853    GrBlendCoeff        fSrcBlend;
854    union {
855        GrBlendCoeff    fDstBlend;
856        GrBlendCoeff    fPodEndMarker;
857    };
858    // @}
859
860    uint32_t            fBehaviorBits;
861    GrMatrix            fViewMatrix;
862
863    // This field must be last; it will not be copied or compared
864    // if the corresponding fTexture[] is NULL.
865    GrSamplerState      fSamplerStates[kNumStages];
866    // only compared if the color matrix enable flag is set
867    float               fColorMatrix[20];       // 5 x 4 matrix
868
869};
870
871#endif
872