GrDrawState.h revision af3a3b9fb1f3be46082013a2d1977d12faf1f61c
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"
1308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com#include "GrEffectStage.h"
14cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com#include "GrRefCnt.h"
15cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com#include "GrRenderTarget.h"
169381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrStencil.h"
17cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com#include "GrTemplates.h"
1864aef2bacd1f5c25ffd9347aabd6265c9b60c0f4bsalomon@google.com#include "GrTexture.h"
1968b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com#include "effects/GrSimpleTextureEffect.h"
209381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
21cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com#include "SkMatrix.h"
229381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "SkXfermode.h"
239381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
24af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.comclass GrPaint;
259381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
262e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.comclass GrDrawState : public GrRefCnt {
272e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.compublic:
28fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    SK_DECLARE_INST_COUNT(GrDrawState)
29d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
309381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
311322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
321322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
331322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * output from the previous enabled stage and a position. The position is either derived from
341322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * the interpolated vertex positions or explicit per-vertex coords, depending upon the
35af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * GrVertexLayout used to draw.
36bf5cad4e9c5808493b35cb9b0000a2d36b7f9b78robertphillips@google.com     *
371322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The stages are divided into two sets, color-computing and coverage-computing. The final color
381322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * stage produces the final pixel color. The coverage-computing stages function exactly as the
391322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * color-computing but the output of the final coverage stage is treated as a fractional pixel
401322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * coverage rather than as input to the src/dst color blend step.
411322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
421322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The input color to the first enabled color-stage is either the constant color or interpolated
43af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
441322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
451322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
461322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect).
471322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
48cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * See the documentation of kCoverageDrawing_StateBit for information about disabling the
49cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * the color / coverage distinction.
50cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     *
511322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
521322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
531322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
54dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com     * by GrClipMaskManager.
559381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
569381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum {
57580711694654b8edc70028d09c4211445b661466twiz@google.com        kNumStages = 5,
589381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
599381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
60ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState() {
6175847199c25121c9989e8dba103ac6002d2132d6reed@google.com#if GR_DEBUG
62af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        VertexLayoutUnitTest();
6375847199c25121c9989e8dba103ac6002d2132d6reed@google.com#endif
6452a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com        this->reset();
6552a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    }
6646f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
67ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState(const GrDrawState& state) {
6846f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com        *this = state;
6946f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com    }
7046f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
719ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    virtual ~GrDrawState() {
727d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
739ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
749ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
7552a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    /**
767d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com     * Resets to the default state.
7708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * GrEffects will be removed from all stages.
78d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     */
7952a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    void reset() {
809ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
817d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
8252a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com
83ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(NULL);
84ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
85ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColor = 0xffffffff;
86af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        fCommon.fVertexLayout = kDefault_VertexLayout;
87ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fViewMatrix.reset();
88ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = kOne_GrBlendCoeff;
89ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = kZero_GrBlendCoeff;
90ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fBlendConstant = 0x0;
91ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0x0;
92ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = kHairLine_EdgeType;
93ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
94ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = kNumStages;
95ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = 0xffffffff;
96ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
97ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = 0x0;
98ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = kBoth_DrawFace;
99af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    }
100af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com
101af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    /**
102af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
1031e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * encompasses more than GrPaint. Aspects of GrDrawState that have no
104af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrPaint equivalents are not modified. GrPaint has fewer stages than
105af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrDrawState. The extra GrDrawState stages are disabled.
106af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     */
107af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    void setFromPaint(const GrPaint& paint);
1088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
110af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /// @name Vertex Layout
111cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    ////
112cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
113af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
114af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * The format of vertices is represented as a bitfield of flags.
115af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Flags that indicate the layout of vertex data. Vertices always contain
116af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * positions and may also contain texture coordinates, per-vertex colors,
117af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * and per-vertex coverage. Each stage can use any texture coordinates as
118af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * its input texture coordinates or it may use the positions as texture
119af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * coordinates.
120b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com     *
121af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * If no texture coordinates are specified for a stage then the stage is
122af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * disabled.
123af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
124af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * The order in memory is always (position, texture coords, color, coverage)
125af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * with any unused fields omitted.
126b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com     */
127cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
128cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
129af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Generates a bit indicating that a texture stage uses texture coordinates
130cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     *
131af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param stageIdx    the stage that will use texture coordinates.
132af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
133af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return the bit to add to a GrVertexLayout bitfield.
134cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
135af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int StageTexCoordVertexLayoutBit(int stageIdx) {
136af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        GrAssert(stageIdx < kNumStages);
137af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        return (1 << stageIdx);
138af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    }
139cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
140af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static bool StageUsesTexCoords(GrVertexLayout layout, int stageIdx);
141b8b705b1b983a2ee3a254bed4dd03f926101e4e7jvanverth@google.com
142af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.comprivate:
143af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    // non-stage bits start at this index.
144af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static const int STAGE_BIT_CNT = kNumStages;
145af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.compublic:
146af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
147af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
148af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Additional Bits that can be specified in GrVertexLayout.
149af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
150af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    enum VertexLayoutBits {
151af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        /* vertices have colors (GrColor) */
152af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kColor_VertexLayoutBit              = 1 << (STAGE_BIT_CNT + 0),
153af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        /* vertices have coverage (GrColor)
154af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com         */
155af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kCoverage_VertexLayoutBit           = 1 << (STAGE_BIT_CNT + 1),
156af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        /* Each vertex specificies an edge. Distance to the edge is used to
157af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com         * compute a coverage. See GrDrawState::setVertexEdgeType().
158af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com         */
159af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kEdge_VertexLayoutBit               = 1 << (STAGE_BIT_CNT + 2),
160af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        // for below assert
161af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kDummyVertexLayoutBit,
162af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kHighVertexLayoutBit = kDummyVertexLayoutBit - 1
163af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    };
164af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    // make sure we haven't exceeded the number of bits in GrVertexLayout.
165af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
166af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
167af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    enum VertexLayout {
168af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        kDefault_VertexLayout = 0
169af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    };
170cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
171cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
172af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *  Sets vertex layout for next draw.
173cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     *
174af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *  @param layout    the vertex layout to set.
175cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
176af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    void setVertexLayout(GrVertexLayout layout) { fCommon.fVertexLayout = layout; }
177af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
178af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    GrVertexLayout getVertexLayout() const { return fCommon.fVertexLayout; }
179af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    size_t getVertexSize() const { return VertexSize(fCommon.fVertexLayout); }
180af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
181cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
182b8b705b1b983a2ee3a254bed4dd03f926101e4e7jvanverth@google.com    ////////////////////////////////////////////////////////////////////////////
183af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    // Helpers for picking apart vertex layouts
184af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
185af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
186af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the size of a vertex from a vertex layout
187af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return size of a single vertex.
188af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
189af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static size_t VertexSize(GrVertexLayout vertexLayout);
190d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
191af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
192af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the offset of texture coordinates in a vertex
193af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return offset of texture coordinates in vertex layout or 0 if positions
194af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *         are used as texture coordinates for the stage.
195af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
196af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout);
197af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
198af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
199af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the offset of the color in a vertex
200af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return offset of color in vertex layout or -1 if the
201af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *         layout has no color.
202af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
203af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int VertexColorOffset(GrVertexLayout vertexLayout);
204af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
205af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
206af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the offset of the coverage in a vertex
207af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return offset of coverage in vertex layout or -1 if the
208af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *         layout has no coverage.
209af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
210af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int VertexCoverageOffset(GrVertexLayout vertexLayout);
211af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
212af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     /**
213af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com      * Helper function to compute the offset of the edge pts in a vertex
214af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com      * @return offset of edge in vertex layout or -1 if the
215af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com      *         layout has no edge.
216af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com      */
217af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     static int VertexEdgeOffset(GrVertexLayout vertexLayout);
218af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
219af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
220af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to determine if vertex layout contains explicit texture
221af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * coordinates.
222af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
223af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param vertexLayout  layout to query
224af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
225af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return true if vertex specifies texture coordinates,
226af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *         false otherwise.
227af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
228af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static bool VertexUsesTexCoords(GrVertexLayout vertexLayout);
229af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
230af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
231af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the size of each vertex and the offsets of
232af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * texture coordinates and color.
233af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
234af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param vertexLayout          the layout to query
235af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param texCoordOffset        after return it is the offset of the
236af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              tex coord index in the vertex or -1 if
237af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              tex coords aren't used. (optional)
238af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param colorOffset           after return it is the offset of the
239af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              color field in each vertex, or -1 if
240af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              there aren't per-vertex colors. (optional)
241af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param coverageOffset        after return it is the offset of the
242af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              coverage field in each vertex, or -1 if
243af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              there aren't per-vertex coeverages.
244af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              (optional)
245af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param edgeOffset            after return it is the offset of the
246af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              edge eq field in each vertex, or -1 if
247af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              there aren't per-vertex edge equations.
248af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                              (optional)
249af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return size of a single vertex
250af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
251af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int VertexSizeAndOffsets(GrVertexLayout vertexLayout,
252af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int *texCoordOffset,
253af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int *colorOffset,
254af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int *coverageOffset,
255af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int* edgeOffset);
256af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
257af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
258af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Helper function to compute the size of each vertex and the offsets of
259af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * texture coordinates and color. Determines tex coord offsets by stage
260af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * rather than by index. (Each stage can be mapped to any t.c. index
261af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * by StageTexCoordVertexLayoutBit.) If a stage uses positions for
262af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * tex coords then that stage's offset will be 0 (positions are always at 0).
263af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
264af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param vertexLayout              the layout to query
265af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param texCoordOffsetsByStage    after return it is the offset of each
266af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  tex coord index in the vertex or -1 if
267af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  index isn't used. (optional)
268af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param colorOffset               after return it is the offset of the
269af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  color field in each vertex, or -1 if
270af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  there aren't per-vertex colors.
271af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  (optional)
272af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param coverageOffset            after return it is the offset of the
273af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  coverage field in each vertex, or -1 if
274af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  there aren't per-vertex coeverages.
275af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  (optional)
276af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param edgeOffset                after return it is the offset of the
277af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  edge eq field in each vertex, or -1 if
278af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  there aren't per-vertex edge equations.
279af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *                                  (optional)
280af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @return size of a single vertex
281af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
282af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
283af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int texCoordOffsetsByStage[kNumStages],
284af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int* colorOffset,
285af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int* coverageOffset,
286af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   int* edgeOffset);
287af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
288af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
289af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Determines whether src alpha is guaranteed to be one for all src pixels
290af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
291af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    bool srcAlphaWillBeOne(GrVertexLayout) const;
292af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
293af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
294af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
295af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
296af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    bool hasSolidCoverage(GrVertexLayout) const;
297cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
298cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
299cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Accessing positions, texture coords, or colors, of a vertex within an
300cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * array is a hassle involving casts and simple math. These helpers exist
301cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * to keep GrDrawTarget clients' code a bit nicer looking.
302cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
303cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
304cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
305cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Gets a pointer to a GrPoint of a vertex's position or texture
306cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * coordinate.
307af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * @param vertices      the vetex array
308cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexIndex   the index of the vertex in the array
309cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexSize    the size of each vertex in the array
310cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param offset        the offset in bytes of the vertex component.
311cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     *                      Defaults to zero (corresponding to vertex position)
312cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @return pointer to the vertex component as a GrPoint
313cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
314cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static GrPoint* GetVertexPoint(void* vertices,
315cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexIndex,
316cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexSize,
317cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int offset = 0) {
318cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
319cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<GrPoint*>(start + offset +
320cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                 vertexIndex * vertexSize);
321cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
322cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static const GrPoint* GetVertexPoint(const void* vertices,
323cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexIndex,
324cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexSize,
325cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int offset = 0) {
326cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
327cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<const GrPoint*>(start + offset +
328cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                       vertexIndex * vertexSize);
329cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
330cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
331cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
332cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Gets a pointer to a GrColor inside a vertex within a vertex array.
333cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertices      the vetex array
334cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexIndex   the index of the vertex in the array
335cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexSize    the size of each vertex in the array
336cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param offset        the offset in bytes of the vertex color
337cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @return pointer to the vertex component as a GrColor
338cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
339cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static GrColor* GetVertexColor(void* vertices,
340cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexIndex,
341cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexSize,
342cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int offset) {
343cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
344cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<GrColor*>(start + offset +
345cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                 vertexIndex * vertexSize);
346cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
347cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static const GrColor* GetVertexColor(const void* vertices,
348cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexIndex,
349cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexSize,
350cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int offset) {
351cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        const intptr_t start = GrTCast<intptr_t>(vertices);
352cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<const GrColor*>(start + offset +
353cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                       vertexIndex * vertexSize);
354cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
355cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
356af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    static void VertexLayoutUnitTest();
357cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
358cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /// @}
359cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
360cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    ///////////////////////////////////////////////////////////////////////////
3618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Color
3628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
3638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets color for next draw to a premultiplied-alpha color.
3668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param color    the color to set.
3688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
369ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setColor(GrColor color) { fCommon.fColor = color; }
3708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
371ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColor() const { return fCommon.fColor; }
3728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets the color to be used for the next draw to be
3758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
3768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param alpha The alpha value to set as the color.
3788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
3798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setAlpha(uint8_t a) {
3808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
3818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Add a color filter that can be represented by a color and a mode. Applied
3858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * after color-computing texture stages.
3868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
3878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setColorFilter(GrColor c, SkXfermode::Mode mode) {
388ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = c;
389ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = mode;
3908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
3918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
392ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
393ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
3948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3955b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
3965b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     * Constructor sets the color to be 'color' which is undone by the destructor.
3975b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
3985b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoColorRestore : public ::GrNoncopyable {
3995b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
400d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        AutoColorRestore() : fDrawState(NULL) {}
401d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
4025b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoColorRestore(GrDrawState* drawState, GrColor color) {
403d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            fDrawState = NULL;
404d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            this->set(drawState, color);
405d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        }
406d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
407d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        void reset() {
408d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            if (NULL != fDrawState) {
409d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com                fDrawState->setColor(fOldColor);
410d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com                fDrawState = NULL;
411d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            }
412d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        }
413d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
414d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        void set(GrDrawState* drawState, GrColor color) {
415d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            this->reset();
4165b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState = drawState;
4175b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fOldColor = fDrawState->getColor();
4185b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState->setColor(color);
4195b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        }
420d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
421d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        ~AutoColorRestore() { this->reset(); }
4225b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
4235b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrDrawState*    fDrawState;
4245b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrColor         fOldColor;
4255b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
4265b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
4278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
4288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
4302401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @name Coverage
4312401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ////
4322401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4332401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
434d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Sets a constant fractional coverage to be applied to the draw. The
4352401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * initial value (after construction or reset()) is 0xff. The constant
4362401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * coverage is ignored when per-vertex coverage is provided.
4372401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
4382401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage(uint8_t coverage) {
439ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
4402401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4412401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4422401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
4432401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * Version of above that specifies 4 channel per-vertex color. The value
4442401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * should be premultiplied.
4452401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
4462401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage4(GrColor coverage) {
447ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = coverage;
4482401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4492401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4502401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    GrColor getCoverage() const {
451ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fCoverage;
4522401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4532401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4542401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @}
4552401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4562401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
457adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    /// @name Effect Stages
4588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
4598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
460adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
461adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        fStages[stageIdx].setEffect(effect);
462adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return effect;
463adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    }
464adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com
4658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
46668b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com     * Creates a GrSimpleTextureEffect.
4671e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com     */
468b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
46908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
47068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
471adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        this->setEffect(stageIdx, effect)->unref();
472dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com    }
47308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void createTextureEffect(int stageIdx,
47408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                             GrTexture* texture,
475b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                             const SkMatrix& matrix,
476dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com                             const GrTextureParams& params) {
47708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
47868b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
479adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        this->setEffect(stageIdx, effect)->unref();
4801ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com    }
4811ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com
4827d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    bool stagesDisabled() {
4837d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        for (int i = 0; i < kNumStages; ++i) {
48408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (NULL != fStages[i].getEffect()) {
4857d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                return false;
4867d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com            }
4877d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        }
4883eee8fbe0f280bc1dea59dc0b0ebd8021b51137ftomhudson@google.com        return true;
4897d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    }
490676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
491adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
492676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
493972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    /**
494f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com     * Release all the GrEffects referred to by this draw state.
495972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com     */
4967d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    void disableStages() {
497972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        for (int i = 0; i < kNumStages; ++i) {
498676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com            this->disableStage(i);
499972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
500972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    }
501972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
5027d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    class AutoStageDisable : public ::GrNoncopyable {
503972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    public:
5047d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
5057d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        ~AutoStageDisable() {
506972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            if (NULL != fDrawState) {
5077d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                fDrawState->disableStages();
508972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            }
509972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
510972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    private:
511972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        GrDrawState* fDrawState;
512972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    };
513972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
5148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
51508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * Returns the current stage by index.
5168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
51708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    const GrEffectStage& getStage(int stageIdx) const {
51808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert((unsigned)stageIdx < kNumStages);
51908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return fStages[stageIdx];
5208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
523288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcat gives the transformation from the
524288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * old coord system to the new coord system.
5258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
526b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void preConcatStageMatrices(const SkMatrix& preConcat) {
527cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com        this->preConcatStageMatrices(~0U, preConcat);
528cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    }
529cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    /**
530cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com     * Version of above that applies the update matrix selectively to stages via a mask.
531cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com     */
532cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
5338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
534cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com            if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
53508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcat);
5368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
5378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
5388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
540e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    /**
541288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcatInverse is the inverse of the
542288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * transformation from the old coord system to the new coord system. Returns false if the matrix
543288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * cannot be inverted.
544e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com     */
545b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
546b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inv;
547e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        bool computed = false;
548e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
549e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (this->isStageEnabled(i)) {
550288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com                if (!computed && !preConcatInverse.invert(&inv)) {
551e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    return false;
552e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                } else {
553e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    computed = true;
554e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                }
55508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcatInverse);
556e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            }
557e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
558e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return true;
559e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
560e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com
5618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
5628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
5648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Coverage / Color Stages
5658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
5668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
5688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * A common pattern is to compute a color with the initial stages and then
5698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * modulate that color by a coverage value in later stage(s) (AA, mask-
570d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
571d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * computed based on the pre-coverage-modulated color. The division of
572d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * stages between color-computing and coverage-computing is specified by
5738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * this method. Initially this is kNumStages (all stages
5748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are color-computing).
5758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
5768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setFirstCoverageStage(int firstCoverageStage) {
5778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrAssert((unsigned)firstCoverageStage <= kNumStages);
578ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = firstCoverageStage;
5798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
5828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets the index of the first coverage-computing stage.
5838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
5848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    int getFirstCoverageStage() const {
585ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fFirstCoverageStage;
5868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///@}
5898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
5918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Blending
5928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
5938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
5951e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * Sets the blending function coefficients.
5968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
5978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * The blend function will be:
5988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *    D' = sat(S*srcCoef + D*dstCoef)
5998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   where D is the existing destination color, S is the incoming source
6018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   color, and D' is the new destination color that will be written. sat()
6028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   is the saturation function.
6038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6041e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param srcCoef coefficient applied to the src color.
6051e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param dstCoef coefficient applied to the dst color.
6068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
608ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = srcCoeff;
609ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = dstCoeff;
6108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #if GR_DEBUG
6118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (dstCoeff) {
61247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDC_GrBlendCoeff:
61347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDC_GrBlendCoeff:
61447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDA_GrBlendCoeff:
61547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDA_GrBlendCoeff:
6168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
6178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
6188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
6208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
6228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (srcCoeff) {
62347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSC_GrBlendCoeff:
62447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISC_GrBlendCoeff:
62547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSA_GrBlendCoeff:
62647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISA_GrBlendCoeff:
6278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected src blend coeff. Won't work correctly with"
6288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
6298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
6318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
6338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #endif
6348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
636ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
637ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
6388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
6408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                          GrBlendCoeff* dstBlendCoeff) const {
641ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *srcBlendCoeff = fCommon.fSrcBlend;
642ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *dstBlendCoeff = fCommon.fDstBlend;
6438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the blending function constant referenced by the following blending
6471e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * coefficients:
64847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstC_GrBlendCoeff
64947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstC_GrBlendCoeff
65047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstA_GrBlendCoeff
65147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstA_GrBlendCoeff
6528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param constant the constant to set
6548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
655ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
6568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the last value set by setBlendConstant()
6598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the blending constant value
6608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
661ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
6628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6632b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
6642b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Determines whether multiplying the computed per-pixel color by the pixel's fractional
6652b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * coverage before the blend will give the correct final destination color. In general it
6662b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * will not as coverage is applied after blending.
6672b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
6682b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    bool canTweakAlphaForCoverage() const;
6692b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
6702b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
6712b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Optimizations for blending / coverage to that can be applied based on the current state.
6722b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
6732b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    enum BlendOptFlags {
6742b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6752b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * No optimization
6762b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6772b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kNone_BlendOpt                  = 0,
6782b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6792b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Don't draw at all
6802b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6812b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kSkipDraw_BlendOptFlag          = 0x1,
6822b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6832b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Emit the src color, disable HW blending (replace dst with src)
6842b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6852b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kDisableBlend_BlendOptFlag      = 0x2,
6862b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6872b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * The coverage value does not have to be computed separately from alpha, the the output
6882b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * color can be the modulation of the two.
6892b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6902b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kCoverageAsAlpha_BlendOptFlag   = 0x4,
6912b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6922b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
6932b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * "don't cares".
6942b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6952b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kEmitCoverage_BlendOptFlag      = 0x8,
6962b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
6972b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Emit transparent black instead of the src color, no need to compute coverage.
6982b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
6992b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kEmitTransBlack_BlendOptFlag    = 0x10,
7002b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    };
7012b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
7022b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
7032b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
7042b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Determines what optimizations can be applied based on the blend. The coefficients may have
7052b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
7062b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * params that receive the tweaked coefficients. Normally the function looks at the current
7072b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
7082b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * determine the blend optimizations that would be used if there was partial pixel coverage.
7092b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     *
7102b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
7112b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * playback) must call this function and respect the flags that replace the output color.
7122b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
7132b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    BlendOptFlags getBlendOpts(bool forceCoverage = false,
7142b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com                               GrBlendCoeff* srcCoeff = NULL,
7152b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com                               GrBlendCoeff* dstCoeff = NULL) const;
7162b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
7178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
7188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
7208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name View Matrix
7218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
7228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
724a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com     * Sets the matrix applied to vertex positions.
7258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * In the post-view-matrix space the rectangle [0,w]x[0,h]
7278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * fully covers the render target. (w and h are the width and height of the
728ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the render-target.)
7298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
730ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
7318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets a writable pointer to the view matrix.
7348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
735ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
7368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
7398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = V*m where V is the old view matrix,
7418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
7428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
7438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
7448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
7468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
747ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
7488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
7518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = m*V where V is the old view matrix,
7538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
7548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
7558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
7568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
7588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
759ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
7608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the current view matrix
7638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current view matrix.
7648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
765ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
7668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Retrieves the inverse of the current view matrix.
7698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  If the current view matrix is invertible, return true, and if matrix
7718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  is non-null, copy the inverse into it. If the current view matrix is
7728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  non-invertible, return false and ignore the matrix parameter.
7738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param matrix if not null, will receive a copy of the current inverse.
7758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
776b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool getViewInverse(SkMatrix* matrix) const {
7778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // TODO: determine whether we really need to leave matrix unmodified
7788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // at call sites when inversion fails.
779b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inverse;
780ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fCommon.fViewMatrix.invert(&inverse)) {
7818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (matrix) {
7828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                *matrix = inverse;
7838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
7848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            return true;
7858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
7868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        return false;
7878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
7888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7895b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
7905b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
7915b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
7922fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * Preconcats the current view matrix and restores the previous view matrix in the destructor.
793c196b522d06919885c6bbe28b7b06d2e5b2cb9bfbsalomon@google.com     * Effect matrices are automatically adjusted to compensate.
7945b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
7958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoViewMatrixRestore : public ::GrNoncopyable {
7968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
7978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoViewMatrixRestore() : fDrawState(NULL) {}
7982fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
7992fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoViewMatrixRestore(GrDrawState* ds,
800b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                              const SkMatrix& preconcatMatrix,
8012fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                              uint32_t explicitCoordStageMask = 0) {
8028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
8032fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(ds, preconcatMatrix, explicitCoordStageMask);
8048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
8052fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8062fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        ~AutoViewMatrixRestore() { this->restore(); }
8072fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
808a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
809a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
810a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
8112fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void restore();
812f467ce7bc33af5f496e0619387551aedec6d2517skia.committer@gmail.com
8132fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void set(GrDrawState* drawState,
814b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                 const SkMatrix& preconcatMatrix,
8152fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                 uint32_t explicitCoordStageMask = 0);
8162fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
817ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        bool isSet() const { return NULL != fDrawState; }
8182fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
820288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
821b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
82208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
823288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
8249381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
8259381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
8265b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
8275b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
8285b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
8292fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * This sets the view matrix to identity and adjusts stage matrices to compensate. The
8302fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * destructor undoes the changes, restoring the view matrix that was set before the
8312fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * constructor. It is similar to passing the inverse of the current view matrix to
8322fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
8335b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
8345b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoDeviceCoordDraw : ::GrNoncopyable {
8355b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
8362fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoDeviceCoordDraw() : fDrawState(NULL) {}
8375b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        /**
8382fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
8392fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
8402fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * to specify such stages.
8415b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com         */
8425b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoDeviceCoordDraw(GrDrawState* drawState,
8432fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                            uint32_t explicitCoordStageMask = 0) {
8442fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            fDrawState = NULL;
8452fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(drawState, explicitCoordStageMask);
8462fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        }
8472fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
848a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        ~AutoDeviceCoordDraw() { this->restore(); }
849a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
8502fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
8512fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
852a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
853a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns true if this object was successfully initialized on to a GrDrawState. It may
854a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * return false because a non-default constructor or set() were never called or because
855a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * the view matrix was not invertible.
856a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
8575b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        bool succeeded() const { return NULL != fDrawState; }
8582fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
859a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
860a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns the matrix that was set previously set on the drawState. This is only valid
861a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * if succeeded returns true.
862a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
863b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        const SkMatrix& getOriginalMatrix() const {
864a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            GrAssert(this->succeeded());
865a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            return fViewMatrix;
866a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        }
8672fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
868a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
869a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
870a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
871a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        void restore();
8722fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8735b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
874288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
875b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
87608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
877288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
8785b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
8795b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
8808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
8818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
8838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Render Target
8848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
8858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
887ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Sets the render-target used at the next drawing call
8888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
8898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param target  The render target to set.
8908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
891d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    void setRenderTarget(GrRenderTarget* target) {
892ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(SkSafeRef(target));
8939ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
8948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
896ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Retrieves the currently set render-target.
8978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
8988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return    The currently set render target.
8998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
900ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
901ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
9028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoRenderTargetRestore : public ::GrNoncopyable {
9048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
905cadbcb8e536f89babb4e165bfdca18384e97d582bsalomon@google.com        AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
9068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
9078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
9087460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com            fSavedTarget = NULL;
9098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            this->set(ds, newTarget);
9108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
9119ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        ~AutoRenderTargetRestore() { this->restore(); }
9129ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9139ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void restore() {
9148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != fDrawState) {
9158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fDrawState->setRenderTarget(fSavedTarget);
9169ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = NULL;
9178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
9189ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            GrSafeSetNull(fSavedTarget);
9199ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        }
9209ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9219ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void set(GrDrawState* ds, GrRenderTarget* newTarget) {
9229ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            this->restore();
9239ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != ds) {
9259ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                GrAssert(NULL == fSavedTarget);
9268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fSavedTarget = ds->getRenderTarget();
9279ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                SkSafeRef(fSavedTarget);
9288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                ds->setRenderTarget(newTarget);
9299ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = ds;
9308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
9318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
9328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
9338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* fDrawState;
9348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrRenderTarget* fSavedTarget;
9358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
9368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
9388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
9408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Stencil
9418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
9428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
9448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the stencil settings to use for the next draw.
9458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Changing the clip has the side-effect of possibly zeroing
9468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * out the client settable stencil bits. So multipass algorithms
9478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * using stencil should not change the clip between passes.
9488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param settings  the stencil settings to use.
9498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
9508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setStencil(const GrStencilSettings& settings) {
951ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings = settings;
9528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
9538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
9558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Shortcut to disable stencil testing and ops.
9568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
9578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableStencil() {
958ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
9598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
9608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
961ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
9628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
963ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
9648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
9668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
9688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    // @name Edge AA
9691e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com    // Edge equations can be specified to perform anti-aliasing. Because the
9707ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // edges are specified as per-vertex data, vertices that are shared by
9717ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // multiple edges must be split.
9728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    //
9738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
9748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
9769381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * When specifying edges as vertex data this enum specifies what type of
97781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com     * edges are in use. The edges are always 4 SkScalars in memory, even when
9789381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the edge type requires fewer than 4.
97993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *
98093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
98193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *       (either adjust in VS or use origin_upper_left in GLSL)
9829381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
9839381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum VertexEdgeType {
9849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        /* 1-pixel wide line
9859381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com           2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
9869381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kHairLine_EdgeType,
987d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        /* Quadratic specified by u^2-v canonical coords (only 2
98869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           components used). Coverage based on signed distance with negative
98993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           being inside, positive outside. Edge specified in window space
99093c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           (y-down) */
99169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kQuad_EdgeType,
99269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        /* Same as above but for hairline quadratics. Uses unsigned distance.
99369cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           Coverage is min(0, 1-distance). */
99469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kHairQuad_EdgeType,
99593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        /* Circle specified as center_x, center_y, outer_radius, inner_radius
99693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           all in window space (y-down). */
99793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com        kCircle_EdgeType,
99846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
99946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com           all in window space (y-down). */
100046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com        kEllipse_EdgeType,
100169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
100269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kVertexEdgeTypeCnt
10039381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
10049381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
10059381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
1006d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Determines the interpretation per-vertex edge data when the
1007af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
10088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are not specified the value of this setting has no effect.
10098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setVertexEdgeType(VertexEdgeType type) {
101169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
1012ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = type;
10138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
10148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1015ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
10168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
10188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
10208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name State Flags
10218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
10228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Flags that affect rendering. Controlled using enable/disableState(). All
10258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  default to disabled.
10268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum StateBits {
10288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Perform dithering. TODO: Re-evaluate whether we need this bit
10308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDither_StateBit        = 0x01,
10328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
1033cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
1034cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
1035cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * the 3D API.
10368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kHWAntialias_StateBit   = 0x02,
10388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Draws will respect the clip, otherwise the clip is ignored.
10408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kClip_StateBit          = 0x04,
10428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Disables writing to the color buffer. Useful when performing stencil
10448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * operations.
10458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kNoColorWrites_StateBit = 0x08,
10470342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com
1048cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com        /**
1049cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Usually coverage is applied after color blending. The color is blended using the coeffs
1050cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
1051cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
1052cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * this case there is no distinction between coverage and color and the caller needs direct
1053cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * control over the blend coeffs. When set, there will be a single blend step controlled by
1054cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * setBlendFunc() which will use coverage*color as the src color.
1055cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         */
1056cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         kCoverageDrawing_StateBit = 0x10,
1057cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
10588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // Users of the class may add additional bits to the vector
10598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDummyStateBit,
10608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kLastPublicStateBit = kDummyStateBit-1,
10618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
10628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void resetStateFlags() {
1064ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0;
10650fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com    }
10660fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
10678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Enable render state settings.
10698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
10701e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to enable
10718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void enableState(uint32_t stateBits) {
1073ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits |= stateBits;
10748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
10750fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
10768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Disable render state settings.
10788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
10791e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to disable
10808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableState(uint32_t stateBits) {
1082ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits &= ~(stateBits);
10838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
10840fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1085d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    /**
1086d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * Enable or disable stateBits based on a boolean.
1087d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     *
10881e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits to enable or disable
1089d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * @param enable    if true enable stateBits, otherwise disable
1090d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     */
1091d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    void setState(uint32_t stateBits, bool enable) {
1092d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        if (enable) {
1093d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->enableState(stateBits);
1094d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        } else {
1095d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->disableState(stateBits);
1096d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        }
1097d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    }
1098d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com
10998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isDitherState() const {
1100ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kDither_StateBit);
11018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11020fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isHWAntialiasState() const {
1104ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
11058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11060fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isClipState() const {
1108ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kClip_StateBit);
11098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11100fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isColorWriteDisabled() const {
1112ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
11138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1115cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    bool isCoverageDrawing() const {
1116ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
1117cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    }
1118cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
11198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isStateFlagEnabled(uint32_t stateBit) const {
1120ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (stateBit & fCommon.fFlagBits);
11218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
11248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
11268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Face Culling
11278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
11288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum DrawFace {
1130978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        kInvalid_DrawFace = -1,
1131978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com
11328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kBoth_DrawFace,
11338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCCW_DrawFace,
11348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCW_DrawFace,
11358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
11368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
11388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Controls whether clockwise, counterclockwise, or both faces are drawn.
11398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param face  the face(s) to draw.
11408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
11418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setDrawFace(DrawFace face) {
1142978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        GrAssert(kInvalid_DrawFace != face);
1143ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = face;
11448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
11478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets whether the target is drawing clockwise, counterclockwise,
11488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * or both faces.
11498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current draw face(s).
11508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
1151ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    DrawFace getDrawFace() const { return fCommon.fDrawFace; }
1152d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
11538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
11548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
115662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
1157f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    bool isStageEnabled(int s) const {
1158f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        GrAssert((unsigned)s < kNumStages);
115908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return (NULL != fStages[s].getEffect());
1160f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    }
1161f13f58804659175925042a291304d483a4fd9278tomhudson@google.com
1162af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    // Most stages are usually not used, so conditionals here
1163af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    // reduce the expected number of bytes touched by 50%.
11649381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator ==(const GrDrawState& s) const {
1165ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
11668fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            return false;
11678fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com        }
1168af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
116962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
1170f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            bool enabled = this->isStageEnabled(i);
1171f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            if (enabled != s.isStageEnabled(i)) {
1172f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com                return false;
1173f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            }
117408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (enabled && this->fStages[i] != s.fStages[i]) {
117562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                return false;
117662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
117762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
117862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return true;
11799381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    }
11809381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator !=(const GrDrawState& s) const { return !(*this == s); }
118162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
1182ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState& operator= (const GrDrawState& s) {
1183ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        this->setRenderTarget(s.fRenderTarget.get());
1184ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon = s.fCommon;
118562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
1186e742bf0ab19659145325ac894f7e0b78c8efbd89tomhudson@google.com            if (s.isStageEnabled(i)) {
118708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                this->fStages[i] = s.fStages[i];
118862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
118962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
119062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return *this;
119162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    }
119262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
119362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.comprivate:
11942e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.com
1195ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1196ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct CommonState {
1197ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // These fields are roughly sorted by decreasing likelihood of being different in op==
1198ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColor;
1199af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        GrVertexLayout                  fVertexLayout;
1200ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkMatrix                        fViewMatrix;
1201ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fSrcBlend;
1202ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fDstBlend;
1203ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fBlendConstant;
1204ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        uint32_t                        fFlagBits;
1205ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        VertexEdgeType                  fVertexEdgeType;
1206ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrStencilSettings               fStencilSettings;
1207ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        int                             fFirstCoverageStage;
1208ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fCoverage;
1209ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkXfermode::Mode                fColorFilterMode;
1210ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColorFilterColor;
1211ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DrawFace                        fDrawFace;
1212ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator== (const CommonState& other) const {
1213ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return fColor == other.fColor &&
1214af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com                   fVertexLayout == other.fVertexLayout &&
1215ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1216ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fSrcBlend == other.fSrcBlend &&
1217ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDstBlend == other.fDstBlend &&
1218ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fBlendConstant == other.fBlendConstant &&
1219ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFlagBits == other.fFlagBits &&
1220ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fVertexEdgeType == other.fVertexEdgeType &&
1221ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fStencilSettings == other.fStencilSettings &&
1222ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFirstCoverageStage == other.fFirstCoverageStage &&
1223ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fCoverage == other.fCoverage &&
1224ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterMode == other.fColorFilterMode &&
1225ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterColor == other.fColorFilterColor &&
1226ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDrawFace == other.fDrawFace;
1227ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1228ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator!= (const CommonState& other) const { return !(*this == other); }
1229ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1230ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1231ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1232ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState must directly reference GrEffects, however. */
1233ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct SavedEffectStage {
1234ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SavedEffectStage() : fEffect(NULL) {}
1235ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        const GrEffect*                    fEffect;
1236ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrEffectStage::SavedCoordChange    fCoordChange;
1237ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1238ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1239ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.compublic:
1240ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /**
1241ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1242ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1243ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * dispose mechanism returns them to the cache. This allows recycling resources through the
1244ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the cache while they are in a deferred draw queue.
1245ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     */
1246ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    class DeferredState {
1247ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    public:
1248ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState() : fRenderTarget(NULL) {
1249ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = false;)
1250ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1251ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // TODO: Remove this when DeferredState no longer holds a ref to the RT
1252ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        ~DeferredState() { SkSafeUnref(fRenderTarget); }
1253ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1254ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void saveFrom(const GrDrawState& drawState) {
1255ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fCommon = drawState.fCommon;
1256ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1257ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fRenderTarget = drawState.fRenderTarget.get();
1258ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            SkSafeRef(fRenderTarget);
1259ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1260ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1261ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // and recycle them to the cache (if no one else is holding a ref to the resources).
1262ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1263ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].saveFrom(drawState.fStages[i]);
1264ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1265ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = true;)
1266ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1267ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1268ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void restoreTo(GrDrawState* drawState) {
1269ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GrAssert(fInitialized);
1270ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->fCommon = fCommon;
1271ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->setRenderTarget(fRenderTarget);
1272ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1273ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].restoreTo(&drawState->fStages[i]);
1274ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1275ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1276ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1277ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool isEqual(const GrDrawState& state) const {
1278ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1279ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                return false;
1280ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1281ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1282dcd69bfca1d8e85ef5abc4e54f1e4b820d38e428bsalomon@google.com                if (!fStages[i].isEqual(state.fStages[i])) {
1283ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                    return false;
1284ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                }
1285ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1286ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return true;
1287ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1288ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1289ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    private:
1290af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        GrRenderTarget*                 fRenderTarget;
1291af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        CommonState                     fCommon;
1292af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com        GrEffectStage::DeferredStage    fStages[kNumStages];
1293ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1294ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GR_DEBUGCODE(bool fInitialized;)
1295ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1296ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1297ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.comprivate:
1298af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    SkAutoTUnref<GrRenderTarget>    fRenderTarget;
1299af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    CommonState                     fCommon;
1300af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    GrEffectStage                   fStages[kNumStages];
13018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1302fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    typedef GrRefCnt INHERITED;
13039381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com};
13049381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
13052b446734cfa8201e5478648988de86b646cb9544bsalomon@google.comGR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
13062b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
13079381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#endif
1308