GrDrawState.h revision dcd69bfca1d8e85ef5abc4e54f1e4b820d38e428
19381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com/*
29381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com * Copyright 2011 Google Inc.
39381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com *
49381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
59381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com * found in the LICENSE file.
69381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com */
79381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
89381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#ifndef GrDrawState_DEFINED
99381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#define GrDrawState_DEFINED
109381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
112eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrBackendEffectFactory.h"
129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrColor.h"
13b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com#include "SkMatrix.h"
142e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.com#include "GrRefCnt.h"
1508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com#include "GrEffectStage.h"
169381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrStencil.h"
1764aef2bacd1f5c25ffd9347aabd6265c9b60c0f4bsalomon@google.com#include "GrTexture.h"
189ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com#include "GrRenderTarget.h"
1968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com#include "effects/GrSimpleTextureEffect.h"
209381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
219381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "SkXfermode.h"
229381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
23af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.comclass GrPaint;
249381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
252e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.comclass GrDrawState : public GrRefCnt {
262e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.compublic:
27fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    SK_DECLARE_INST_COUNT(GrDrawState)
28d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
299381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
301322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
311322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
321322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * output from the previous enabled stage and a position. The position is either derived from
331322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * the interpolated vertex positions or explicit per-vertex coords, depending upon the
341322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrVertexLayout used to draw.
35bf5cad4e9c5808493b35cb9b0000a2d36b7f9b78robertphillips@google.com     *
361322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The stages are divided into two sets, color-computing and coverage-computing. The final color
371322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * stage produces the final pixel color. The coverage-computing stages function exactly as the
381322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * color-computing but the output of the final coverage stage is treated as a fractional pixel
391322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * coverage rather than as input to the src/dst color blend step.
401322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
411322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The input color to the first enabled color-stage is either the constant color or interpolated
421322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
431322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
441322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
451322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect).
461322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
47cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * See the documentation of kCoverageDrawing_StateBit for information about disabling the
48cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * the color / coverage distinction.
49cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     *
501322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
511322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
521322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
53dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com     * by GrClipMaskManager.
549381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
559381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum {
56580711694654b8edc70028d09c4211445b661466twiz@google.com        kNumStages = 5,
579381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kMaxTexCoords = kNumStages
589381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
599381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
60ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState() {
6152a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com        this->reset();
6252a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    }
6346f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
64ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState(const GrDrawState& state) {
6546f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com        *this = state;
6646f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com    }
6746f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
689ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    virtual ~GrDrawState() {
697d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
709ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
719ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
7252a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    /**
737d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com     * Resets to the default state.
7408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * GrEffects will be removed from all stages.
75d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     */
7652a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    void reset() {
779ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
787d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
7952a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com
80ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(NULL);
81ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
82ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColor = 0xffffffff;
83ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fViewMatrix.reset();
84ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = kOne_GrBlendCoeff;
85ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = kZero_GrBlendCoeff;
86ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fBlendConstant = 0x0;
87ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0x0;
88ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = kHairLine_EdgeType;
89ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
90ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = kNumStages;
91ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = 0xffffffff;
92ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
93ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = 0x0;
94ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = kBoth_DrawFace;
95af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    }
96af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com
97af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    /**
98af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
991e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * encompasses more than GrPaint. Aspects of GrDrawState that have no
100af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrPaint equivalents are not modified. GrPaint has fewer stages than
101af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrDrawState. The extra GrDrawState stages are disabled.
102af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     */
103af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    void setFromPaint(const GrPaint& paint);
1048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
1068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Color
1078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
1088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
1108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets color for next draw to a premultiplied-alpha color.
1118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
1128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param color    the color to set.
1138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
114ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setColor(GrColor color) { fCommon.fColor = color; }
1158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
116ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColor() const { return fCommon.fColor; }
1178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
1198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets the color to be used for the next draw to be
1208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
1218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
1228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param alpha The alpha value to set as the color.
1238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
1248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setAlpha(uint8_t a) {
1258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
1268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
1278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
1298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Add a color filter that can be represented by a color and a mode. Applied
1308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * after color-computing texture stages.
1318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
1328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setColorFilter(GrColor c, SkXfermode::Mode mode) {
133ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = c;
134ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = mode;
1358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
1368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
137ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
138ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
1398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1405b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
1415b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     * Constructor sets the color to be 'color' which is undone by the destructor.
1425b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
1435b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoColorRestore : public ::GrNoncopyable {
1445b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
1455b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoColorRestore(GrDrawState* drawState, GrColor color) {
1465b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState = drawState;
1475b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fOldColor = fDrawState->getColor();
1485b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState->setColor(color);
1495b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        }
1505b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        ~AutoColorRestore() {
1515b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState->setColor(fOldColor);
1525b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        }
1535b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
1545b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrDrawState*    fDrawState;
1555b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrColor         fOldColor;
1565b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
1575b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
1588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
1598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
1612401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @name Coverage
1622401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ////
1632401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
1642401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
165d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Sets a constant fractional coverage to be applied to the draw. The
1662401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * initial value (after construction or reset()) is 0xff. The constant
1672401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * coverage is ignored when per-vertex coverage is provided.
1682401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
1692401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage(uint8_t coverage) {
170ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
1712401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
1722401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
1732401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
1742401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * Version of above that specifies 4 channel per-vertex color. The value
1752401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * should be premultiplied.
1762401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
1772401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage4(GrColor coverage) {
178ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = coverage;
1792401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
1802401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
1812401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    GrColor getCoverage() const {
182ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fCoverage;
1832401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
1842401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
1852401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @}
1862401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
1872401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
1888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Textures
1898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
1908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
19268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com     * Creates a GrSimpleTextureEffect.
1931e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com     */
194b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
19508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
19668b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
197d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com        this->stage(stageIdx)->setEffect(effect)->unref();
198dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com    }
19908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void createTextureEffect(int stageIdx,
20008283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                             GrTexture* texture,
201b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                             const SkMatrix& matrix,
202dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com                             const GrTextureParams& params) {
20308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
20468b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
205d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com        this->stage(stageIdx)->setEffect(effect)->unref();
2061ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com    }
2071ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com
2087d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    bool stagesDisabled() {
2097d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        for (int i = 0; i < kNumStages; ++i) {
21008283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (NULL != fStages[i].getEffect()) {
2117d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                return false;
2127d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com            }
2137d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        }
2143eee8fbe0f280bc1dea59dc0b0ebd8021b51137ftomhudson@google.com        return true;
2157d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    }
216676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
21708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void disableStage(int stageIdx) {
21808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        fStages[stageIdx].setEffect(NULL);
219676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com    }
220676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
221972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    /**
222f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com     * Release all the GrEffects referred to by this draw state.
223972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com     */
2247d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    void disableStages() {
225972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        for (int i = 0; i < kNumStages; ++i) {
226676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com            this->disableStage(i);
227972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
228972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    }
229972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
2307d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    class AutoStageDisable : public ::GrNoncopyable {
231972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    public:
2327d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
2337d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        ~AutoStageDisable() {
234972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            if (NULL != fDrawState) {
2357d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                fDrawState->disableStages();
236972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            }
237972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
238972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    private:
239972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        GrDrawState* fDrawState;
240972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    };
241972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
2428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
2438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
24508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    /// @name Stages
2468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
2478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
24908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * Returns the current stage by index.
2508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
25108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    const GrEffectStage& getStage(int stageIdx) const {
25208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert((unsigned)stageIdx < kNumStages);
25308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return fStages[stageIdx];
2548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
2558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
25708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * Writable pointer to a stage.
2588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
25908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    GrEffectStage* stage(int stageIdx) {
26008283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert((unsigned)stageIdx < kNumStages);
26108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return fStages + stageIdx;
2628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
2638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
265288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcat gives the transformation from the
266288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * old coord system to the new coord system.
2678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
268b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void preConcatStageMatrices(const SkMatrix& preConcat) {
2698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
270e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (this->isStageEnabled(i)) {
27108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcat);
2728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
2738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
2748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
2758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
276e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    /**
277288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcatInverse is the inverse of the
278288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * transformation from the old coord system to the new coord system. Returns false if the matrix
279288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * cannot be inverted.
280e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com     */
281b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
282b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inv;
283e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        bool computed = false;
284e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
285e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (this->isStageEnabled(i)) {
286288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com                if (!computed && !preConcatInverse.invert(&inv)) {
287e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    return false;
288e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                } else {
289e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    computed = true;
290e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                }
29108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcatInverse);
292e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            }
293e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
294e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return true;
295e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
296e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com
2978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
2988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
2998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
3008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Coverage / Color Stages
3018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
3028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * A common pattern is to compute a color with the initial stages and then
3058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * modulate that color by a coverage value in later stage(s) (AA, mask-
306d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
307d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * computed based on the pre-coverage-modulated color. The division of
308d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * stages between color-computing and coverage-computing is specified by
3098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * this method. Initially this is kNumStages (all stages
3108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are color-computing).
3118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
3128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setFirstCoverageStage(int firstCoverageStage) {
3138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrAssert((unsigned)firstCoverageStage <= kNumStages);
314ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = firstCoverageStage;
3158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets the index of the first coverage-computing stage.
3198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
3208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    int getFirstCoverageStage() const {
321ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fFirstCoverageStage;
3228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///@}
3258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
3278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Blending
3288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
3298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3311e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * Sets the blending function coefficients.
3328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * The blend function will be:
3348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *    D' = sat(S*srcCoef + D*dstCoef)
3358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   where D is the existing destination color, S is the incoming source
3378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   color, and D' is the new destination color that will be written. sat()
3388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   is the saturation function.
3398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3401e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param srcCoef coefficient applied to the src color.
3411e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param dstCoef coefficient applied to the dst color.
3428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
3438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
344ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = srcCoeff;
345ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = dstCoeff;
3468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #if GR_DEBUG
3478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (dstCoeff) {
34847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDC_GrBlendCoeff:
34947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDC_GrBlendCoeff:
35047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDA_GrBlendCoeff:
35147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDA_GrBlendCoeff:
3528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
3538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
3548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
3558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
3568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
3578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
3588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (srcCoeff) {
35947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSC_GrBlendCoeff:
36047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISC_GrBlendCoeff:
36147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSA_GrBlendCoeff:
36247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISA_GrBlendCoeff:
3638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected src blend coeff. Won't work correctly with"
3648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
3658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
3668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
3678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
3688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
3698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #endif
3708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
372ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
373ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
3748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
3768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                          GrBlendCoeff* dstBlendCoeff) const {
377ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *srcBlendCoeff = fCommon.fSrcBlend;
378ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *dstBlendCoeff = fCommon.fDstBlend;
3798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the blending function constant referenced by the following blending
3831e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * coefficients:
38447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstC_GrBlendCoeff
38547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstC_GrBlendCoeff
38647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstA_GrBlendCoeff
38747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstA_GrBlendCoeff
3888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param constant the constant to set
3908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
391ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
3928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the last value set by setBlendConstant()
3958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the blending constant value
3968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
397ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
3988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
4008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
4028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name View Matrix
4038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
4048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
406a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com     * Sets the matrix applied to vertex positions.
4078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * In the post-view-matrix space the rectangle [0,w]x[0,h]
4098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * fully covers the render target. (w and h are the width and height of the
410ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the render-target.)
4118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
412ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
4138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets a writable pointer to the view matrix.
4168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
417ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
4188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
4218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = V*m where V is the old view matrix,
4238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
4248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
4258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
4268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
4288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
429ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
4308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
4338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = m*V where V is the old view matrix,
4358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
4368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
4378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
4388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
4408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
441ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
4428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the current view matrix
4458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current view matrix.
4468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
447ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
4488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Retrieves the inverse of the current view matrix.
4518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  If the current view matrix is invertible, return true, and if matrix
4538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  is non-null, copy the inverse into it. If the current view matrix is
4548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  non-invertible, return false and ignore the matrix parameter.
4558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param matrix if not null, will receive a copy of the current inverse.
4578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
458b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool getViewInverse(SkMatrix* matrix) const {
4598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // TODO: determine whether we really need to leave matrix unmodified
4608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // at call sites when inversion fails.
461b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inverse;
462ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fCommon.fViewMatrix.invert(&inverse)) {
4638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (matrix) {
4648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                *matrix = inverse;
4658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
4668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            return true;
4678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
4688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        return false;
4698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
4708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4715b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
4725b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
4735b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
4742fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * Preconcats the current view matrix and restores the previous view matrix in the destructor.
475c196b522d06919885c6bbe28b7b06d2e5b2cb9bfbsalomon@google.com     * Effect matrices are automatically adjusted to compensate.
4765b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
4778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoViewMatrixRestore : public ::GrNoncopyable {
4788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
4798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoViewMatrixRestore() : fDrawState(NULL) {}
4802fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
4812fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoViewMatrixRestore(GrDrawState* ds,
482b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                              const SkMatrix& preconcatMatrix,
4832fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                              uint32_t explicitCoordStageMask = 0) {
4848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
4852fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(ds, preconcatMatrix, explicitCoordStageMask);
4868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
4872fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
4882fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        ~AutoViewMatrixRestore() { this->restore(); }
4892fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
490a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
491a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
492a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
4932fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void restore();
494f467ce7bc33af5f496e0619387551aedec6d2517skia.committer@gmail.com
4952fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void set(GrDrawState* drawState,
496b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                 const SkMatrix& preconcatMatrix,
4972fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                 uint32_t explicitCoordStageMask = 0);
4982fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
499ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        bool isSet() const { return NULL != fDrawState; }
5002fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
5018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
502288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
503b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
50408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
505288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
5069381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
5079381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
5085b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
5095b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
5105b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
5112fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * This sets the view matrix to identity and adjusts stage matrices to compensate. The
5122fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * destructor undoes the changes, restoring the view matrix that was set before the
5132fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * constructor. It is similar to passing the inverse of the current view matrix to
5142fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
5155b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
5165b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoDeviceCoordDraw : ::GrNoncopyable {
5175b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
5182fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoDeviceCoordDraw() : fDrawState(NULL) {}
5195b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        /**
5202fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
5212fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
5222fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * to specify such stages.
5235b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com         */
5245b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoDeviceCoordDraw(GrDrawState* drawState,
5252fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                            uint32_t explicitCoordStageMask = 0) {
5262fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            fDrawState = NULL;
5272fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(drawState, explicitCoordStageMask);
5282fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        }
5292fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
530a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        ~AutoDeviceCoordDraw() { this->restore(); }
531a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
5322fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
5332fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
534a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
535a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns true if this object was successfully initialized on to a GrDrawState. It may
536a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * return false because a non-default constructor or set() were never called or because
537a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * the view matrix was not invertible.
538a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
5395b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        bool succeeded() const { return NULL != fDrawState; }
5402fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
541a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
542a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns the matrix that was set previously set on the drawState. This is only valid
543a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * if succeeded returns true.
544a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
545b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        const SkMatrix& getOriginalMatrix() const {
546a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            GrAssert(this->succeeded());
547a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            return fViewMatrix;
548a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        }
5492fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
550a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
551a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
552a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
553a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        void restore();
5542fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
5555b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
556288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
557b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
55808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
559288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
5605b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
5615b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
5628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
5638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
5658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Render Target
5668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
5678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
569ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Sets the render-target used at the next drawing call
5708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
5718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param target  The render target to set.
5728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
573d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    void setRenderTarget(GrRenderTarget* target) {
574ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(SkSafeRef(target));
5759ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
5768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
578ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Retrieves the currently set render-target.
5798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
5808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return    The currently set render target.
5818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
582ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
583ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
5848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoRenderTargetRestore : public ::GrNoncopyable {
5868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
587cadbcb8e536f89babb4e165bfdca18384e97d582bsalomon@google.com        AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
5888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
5898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
5907460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com            fSavedTarget = NULL;
5918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            this->set(ds, newTarget);
5928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
5939ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        ~AutoRenderTargetRestore() { this->restore(); }
5949ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
5959ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void restore() {
5968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != fDrawState) {
5978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fDrawState->setRenderTarget(fSavedTarget);
5989ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = NULL;
5998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
6009ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            GrSafeSetNull(fSavedTarget);
6019ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        }
6029ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
6039ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void set(GrDrawState* ds, GrRenderTarget* newTarget) {
6049ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            this->restore();
6059ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
6068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != ds) {
6079ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                GrAssert(NULL == fSavedTarget);
6088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fSavedTarget = ds->getRenderTarget();
6099ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                SkSafeRef(fSavedTarget);
6108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                ds->setRenderTarget(newTarget);
6119ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = ds;
6128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
6138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
6148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
6158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* fDrawState;
6168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrRenderTarget* fSavedTarget;
6178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
6188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
6208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
6228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Stencil
6238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
6248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the stencil settings to use for the next draw.
6278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Changing the clip has the side-effect of possibly zeroing
6288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * out the client settable stencil bits. So multipass algorithms
6298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * using stencil should not change the clip between passes.
6308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param settings  the stencil settings to use.
6318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setStencil(const GrStencilSettings& settings) {
633ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings = settings;
6348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Shortcut to disable stencil testing and ops.
6388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableStencil() {
640ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
6418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
643ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
6448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
645ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
6468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
6488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
6508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    // @name Edge AA
6511e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com    // Edge equations can be specified to perform anti-aliasing. Because the
6527ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // edges are specified as per-vertex data, vertices that are shared by
6537ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // multiple edges must be split.
6548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    //
6558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
6568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6589381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * When specifying edges as vertex data this enum specifies what type of
65981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com     * edges are in use. The edges are always 4 SkScalars in memory, even when
6609381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the edge type requires fewer than 4.
66193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *
66293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
66393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *       (either adjust in VS or use origin_upper_left in GLSL)
6649381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
6659381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum VertexEdgeType {
6669381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        /* 1-pixel wide line
6679381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com           2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
6689381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kHairLine_EdgeType,
669d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        /* Quadratic specified by u^2-v canonical coords (only 2
67069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           components used). Coverage based on signed distance with negative
67193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           being inside, positive outside. Edge specified in window space
67293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           (y-down) */
67369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kQuad_EdgeType,
67469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        /* Same as above but for hairline quadratics. Uses unsigned distance.
67569cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           Coverage is min(0, 1-distance). */
67669cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kHairQuad_EdgeType,
67793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        /* Circle specified as center_x, center_y, outer_radius, inner_radius
67893c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           all in window space (y-down). */
67993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        kCircle_EdgeType,
68046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
68146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com           all in window space (y-down). */
68246d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        kEllipse_EdgeType,
68369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
68469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kVertexEdgeTypeCnt
6859381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
6869381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
6879381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
688d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Determines the interpretation per-vertex edge data when the
6898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
6908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are not specified the value of this setting has no effect.
6918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setVertexEdgeType(VertexEdgeType type) {
69369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
694ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = type;
6958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
697ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
6988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
7008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
7028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name State Flags
7038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
7048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Flags that affect rendering. Controlled using enable/disableState(). All
7078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  default to disabled.
7088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
7098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum StateBits {
7108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
7118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Perform dithering. TODO: Re-evaluate whether we need this bit
7128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
7138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDither_StateBit        = 0x01,
7148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
715cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
716cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
717cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * the 3D API.
7188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
7198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kHWAntialias_StateBit   = 0x02,
7208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
7218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Draws will respect the clip, otherwise the clip is ignored.
7228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
7238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kClip_StateBit          = 0x04,
7248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
7258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Disables writing to the color buffer. Useful when performing stencil
7268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * operations.
7278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
7288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kNoColorWrites_StateBit = 0x08,
7290342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com
730cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com        /**
731cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Usually coverage is applied after color blending. The color is blended using the coeffs
732cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
733cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
734cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * this case there is no distinction between coverage and color and the caller needs direct
735cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * control over the blend coeffs. When set, there will be a single blend step controlled by
736cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * setBlendFunc() which will use coverage*color as the src color.
737cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         */
738cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         kCoverageDrawing_StateBit = 0x10,
739cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
7408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // Users of the class may add additional bits to the vector
7418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDummyStateBit,
7428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kLastPublicStateBit = kDummyStateBit-1,
7438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
7448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void resetStateFlags() {
746ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0;
7470fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com    }
7480fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
7498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Enable render state settings.
7518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7521e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to enable
7538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
7548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void enableState(uint32_t stateBits) {
755ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits |= stateBits;
7568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7570fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
7588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Disable render state settings.
7608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7611e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to disable
7628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
7638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableState(uint32_t stateBits) {
764ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits &= ~(stateBits);
7658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7660fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
767d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    /**
768d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * Enable or disable stateBits based on a boolean.
769d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     *
7701e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits to enable or disable
771d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * @param enable    if true enable stateBits, otherwise disable
772d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     */
773d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    void setState(uint32_t stateBits, bool enable) {
774d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        if (enable) {
775d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->enableState(stateBits);
776d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        } else {
777d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->disableState(stateBits);
778d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        }
779d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    }
780d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com
7818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isDitherState() const {
782ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kDither_StateBit);
7838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7840fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
7858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isHWAntialiasState() const {
786ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
7878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7880fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
7898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isClipState() const {
790ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kClip_StateBit);
7918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7920fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
7938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isColorWriteDisabled() const {
794ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
7958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
797cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    bool isCoverageDrawing() const {
798ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
799cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    }
800cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
8018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isStateFlagEnabled(uint32_t stateBit) const {
802ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (stateBit & fCommon.fFlagBits);
8038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
8048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
8068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
8088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Face Culling
8098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
8108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum DrawFace {
812978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        kInvalid_DrawFace = -1,
813978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com
8148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kBoth_DrawFace,
8158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCCW_DrawFace,
8168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCW_DrawFace,
8178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
8188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
8208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Controls whether clockwise, counterclockwise, or both faces are drawn.
8218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param face  the face(s) to draw.
8228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
8238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setDrawFace(DrawFace face) {
824978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        GrAssert(kInvalid_DrawFace != face);
825ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = face;
8268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
8278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
8298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets whether the target is drawing clockwise, counterclockwise,
8308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * or both faces.
8318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current draw face(s).
8328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
833ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    DrawFace getDrawFace() const { return fCommon.fDrawFace; }
834d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
8358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
8368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
83862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
839f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    bool isStageEnabled(int s) const {
840f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        GrAssert((unsigned)s < kNumStages);
84108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return (NULL != fStages[s].getEffect());
842f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    }
843f13f58804659175925042a291304d483a4fd9278tomhudson@google.com
84462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // Most stages are usually not used, so conditionals here
84562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // reduce the expected number of bytes touched by 50%.
8469381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator ==(const GrDrawState& s) const {
847ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
8488fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            return false;
8498fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com        }
85062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
85162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
852f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            bool enabled = this->isStageEnabled(i);
853f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            if (enabled != s.isStageEnabled(i)) {
854f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com                return false;
855f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            }
85608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (enabled && this->fStages[i] != s.fStages[i]) {
85762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                return false;
85862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
85962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
86062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return true;
8619381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    }
8629381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator !=(const GrDrawState& s) const { return !(*this == s); }
86362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
864ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState& operator= (const GrDrawState& s) {
865ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        this->setRenderTarget(s.fRenderTarget.get());
866ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon = s.fCommon;
86762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
868e742bf0ab19659145325ac894f7e0b78c8efbd89tomhudson@google.com            if (s.isStageEnabled(i)) {
86908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                this->fStages[i] = s.fStages[i];
87062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
87162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
87262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return *this;
87362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    }
87462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
87562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.comprivate:
8762e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.com
877ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
878ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct CommonState {
879ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // These fields are roughly sorted by decreasing likelihood of being different in op==
880ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColor;
881ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkMatrix                        fViewMatrix;
882ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fSrcBlend;
883ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fDstBlend;
884ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fBlendConstant;
885ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        uint32_t                        fFlagBits;
886ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        VertexEdgeType                  fVertexEdgeType;
887ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrStencilSettings               fStencilSettings;
888ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        int                             fFirstCoverageStage;
889ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fCoverage;
890ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkXfermode::Mode                fColorFilterMode;
891ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColorFilterColor;
892ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DrawFace                        fDrawFace;
893ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator== (const CommonState& other) const {
894ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return fColor == other.fColor &&
895ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
896ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fSrcBlend == other.fSrcBlend &&
897ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDstBlend == other.fDstBlend &&
898ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fBlendConstant == other.fBlendConstant &&
899ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFlagBits == other.fFlagBits &&
900ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fVertexEdgeType == other.fVertexEdgeType &&
901ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fStencilSettings == other.fStencilSettings &&
902ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFirstCoverageStage == other.fFirstCoverageStage &&
903ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fCoverage == other.fCoverage &&
904ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterMode == other.fColorFilterMode &&
905ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterColor == other.fColorFilterColor &&
906ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDrawFace == other.fDrawFace;
907ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
908ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator!= (const CommonState& other) const { return !(*this == other); }
909ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
910ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
911ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
912ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState must directly reference GrEffects, however. */
913ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct SavedEffectStage {
914ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SavedEffectStage() : fEffect(NULL) {}
915ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        const GrEffect*                    fEffect;
916ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrEffectStage::SavedCoordChange    fCoordChange;
917ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
918ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
919ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.compublic:
920ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /**
921ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
922ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
923ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * dispose mechanism returns them to the cache. This allows recycling resources through the
924ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the cache while they are in a deferred draw queue.
925ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     */
926ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    class DeferredState {
927ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    public:
928ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState() : fRenderTarget(NULL) {
929ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = false;)
930ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
931ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // TODO: Remove this when DeferredState no longer holds a ref to the RT
932ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        ~DeferredState() { SkSafeUnref(fRenderTarget); }
933ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
934ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void saveFrom(const GrDrawState& drawState) {
935ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fCommon = drawState.fCommon;
936ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
937ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fRenderTarget = drawState.fRenderTarget.get();
938ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            SkSafeRef(fRenderTarget);
939ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
940ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // ref gets fully unref'ed it will cause the underlying effect to unref its resources
941ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // and recycle them to the cache (if no one else is holding a ref to the resources).
942ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
943ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].saveFrom(drawState.fStages[i]);
944ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
945ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = true;)
946ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
947ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
948ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void restoreTo(GrDrawState* drawState) {
949ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GrAssert(fInitialized);
950ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->fCommon = fCommon;
951ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->setRenderTarget(fRenderTarget);
952ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
953ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].restoreTo(&drawState->fStages[i]);
954ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
955ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
956ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
957ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool isEqual(const GrDrawState& state) const {
958ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
959ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                return false;
960ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
961ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
962dcd69bfca1d8e85ef5abc4e54f1e4b820d38e428bsalomon@google.com                if (!fStages[i].isEqual(state.fStages[i])) {
963ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                    return false;
964ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                }
965ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
966ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return true;
967ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
968ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
969ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    private:
970ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrRenderTarget*                 fRenderTarget;
971ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        CommonState                     fCommon;
972ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrEffectStage::DeferredStage    fStages[kNumStages];
973ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
974ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GR_DEBUGCODE(bool fInitialized;)
975ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
976ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
977ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.comprivate:
978ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkAutoTUnref<GrRenderTarget>    fRenderTarget;
979ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    CommonState                     fCommon;
980ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrEffectStage                   fStages[kNumStages];
9818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
982fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    typedef GrRefCnt INHERITED;
9839381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com};
9849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
9859381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#endif
986