GrPipelineBuilder.h revision 01c34ee59906f729f6ca7d35f0c0e5e2f5e693fe
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
269b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com/**
279b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com * Types used to describe format of vertices in arrays
289b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com  */
299b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comenum GrVertexAttribType {
309b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kFloat_GrVertexAttribType = 0,
319b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kVec2f_GrVertexAttribType,
329b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kVec3f_GrVertexAttribType,
339b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kVec4f_GrVertexAttribType,
349b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kVec4ub_GrVertexAttribType,   // vector of 4 unsigned bytes, e.g. colors
359b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
369b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    kLast_GrVertexAttribType = kVec4ub_GrVertexAttribType
379b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com};
389b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comstatic const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;
399b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
409b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comstruct GrVertexAttrib {
41f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com    inline void set(GrVertexAttribType type, size_t offset) {
423b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com        fType = type; fOffset = offset;
433b0d631cdfe2dcf59e7b7ea60d92566eade7bfc0jvanverth@google.com    }
449b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    bool operator==(const GrVertexAttrib& other) const {
459b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        return fType == other.fType && fOffset == other.fOffset;
469b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    };
479b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); }
489b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
499b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrVertexAttribType fType;
509b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    size_t             fOffset;
519b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com};
529b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comtemplate <int N>
549b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comclass GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
559b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
569b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com/**
579b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com * Type used to describe how attributes bind to program usage
589b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com */
599b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.comtypedef int GrAttribBindings;
609b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
612e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.comclass GrDrawState : public GrRefCnt {
622e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.compublic:
63fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    SK_DECLARE_INST_COUNT(GrDrawState)
64d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
659381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
661322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
671322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
681322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * output from the previous enabled stage and a position. The position is either derived from
691322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * the interpolated vertex positions or explicit per-vertex coords, depending upon the
709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * GrAttribBindings used to draw.
71bf5cad4e9c5808493b35cb9b0000a2d36b7f9b78robertphillips@google.com     *
721322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The stages are divided into two sets, color-computing and coverage-computing. The final color
731322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * stage produces the final pixel color. The coverage-computing stages function exactly as the
741322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * color-computing but the output of the final coverage stage is treated as a fractional pixel
751322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * coverage rather than as input to the src/dst color blend step.
761322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
771322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * The input color to the first enabled color-stage is either the constant color or interpolated
789b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
791322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
801322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
811322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrEffect).
821322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     *
83cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * See the documentation of kCoverageDrawing_StateBit for information about disabling the
84cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     * the color / coverage distinction.
85cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com     *
861322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
871322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
881322134a3a7232e4ae3433733ed425fd9966bd5cbsalomon@google.com     * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
89dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com     * by GrClipMaskManager.
909381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
919381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum {
92580711694654b8edc70028d09c4211445b661466twiz@google.com        kNumStages = 5,
939381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
949381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
95ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState() {
9675847199c25121c9989e8dba103ac6002d2132d6reed@google.com#if GR_DEBUG
979b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        VertexAttributesUnitTest();
9875847199c25121c9989e8dba103ac6002d2132d6reed@google.com#endif
9952a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com        this->reset();
10052a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    }
10146f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
102ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState(const GrDrawState& state) {
10346f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com        *this = state;
10446f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com    }
10546f7afb9867200b568c21736da8a8bbb56b20e30bsalomon@google.com
1069ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    virtual ~GrDrawState() {
1077d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
1089ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
1099ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
11052a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    /**
1117d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com     * Resets to the default state.
11208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * GrEffects will be removed from all stages.
113d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     */
11452a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com    void reset() {
1159ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
1167d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        this->disableStages();
11752a5dcb43b5acbde377f664807b0f75af8bb1666bsalomon@google.com
118ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(NULL);
119ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1209b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        this->setDefaultVertexAttribs();
1219b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
122ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColor = 0xffffffff;
123ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fViewMatrix.reset();
124ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = kOne_GrBlendCoeff;
125ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = kZero_GrBlendCoeff;
126ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fBlendConstant = 0x0;
127ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0x0;
128ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = kHairLine_EdgeType;
129ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
130ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = kNumStages;
131ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = 0xffffffff;
132ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
133ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = 0x0;
134ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = kBoth_DrawFace;
135af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    }
136af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com
137af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    /**
138af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
1391e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * encompasses more than GrPaint. Aspects of GrDrawState that have no
140af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrPaint equivalents are not modified. GrPaint has fewer stages than
141af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     * GrDrawState. The extra GrDrawState stages are disabled.
142af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com     */
143af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com    void setFromPaint(const GrPaint& paint);
1448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
1469b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /// @name Vertex Attributes
147cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    ////
148cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
1499b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    enum {
1509b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kVertexAttribCnt = 6,
151af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    };
152cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
1539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com   /**
154f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * The format of vertices is represented as an array of vertex attribute
155f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * pair, with each pair representing the type of the attribute and the
156f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * offset in the vertex structure (see GrVertexAttrib, above).
157cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     *
1589b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * This will only set up the vertex geometry. To bind the attributes in
159f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * the shaders, attribute indices and attribute bindings need to be set
1609b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * as well.
161cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
162af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
163af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
164f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *  Sets vertex attributes for next draw.
165af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
166f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *  @param attribs    the array of vertex attributes to set.
1679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  @param count      the number of attributes being set.
168f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *                    limited to a count of kVertexAttribCnt.
169af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
1709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    void setVertexAttribs(const GrVertexAttrib attribs[], int count);
171af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
1729b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
1739b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    int getVertexAttribCount() const { return fVertexAttribs.count(); }
1749b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
1759b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    size_t getVertexSize() const;
176af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
177af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com    /**
178f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *  Sets default vertex attributes for next draw.
179af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     *
1809b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  This will also set default vertex attribute indices and bindings
181af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com     */
1829b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    void setDefaultVertexAttribs();
183af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
184ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    bool validateVertexAttribs() const;
185ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
1869b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ////////////////////////////////////////////////////////////////////////////
1879b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // Helpers for picking apart vertex attributes
188af3a3b9fb1f3be46082013a2d1977d12faf1f61crobertphillips@google.com
1899b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // helper array to let us check the expected so we know what bound attrib indices
1909b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // we care about
1919b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
192cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
193cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
194cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Accessing positions, texture coords, or colors, of a vertex within an
195cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * array is a hassle involving casts and simple math. These helpers exist
196cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * to keep GrDrawTarget clients' code a bit nicer looking.
197cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
198cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
199cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
200cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Gets a pointer to a GrPoint of a vertex's position or texture
201cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * coordinate.
2029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * @param vertices      the vertex array
203cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexIndex   the index of the vertex in the array
204cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexSize    the size of each vertex in the array
205cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param offset        the offset in bytes of the vertex component.
206cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     *                      Defaults to zero (corresponding to vertex position)
207cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @return pointer to the vertex component as a GrPoint
208cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
209cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static GrPoint* GetVertexPoint(void* vertices,
210cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexIndex,
211cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexSize,
212cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int offset = 0) {
213cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
214cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<GrPoint*>(start + offset +
215cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                 vertexIndex * vertexSize);
216cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
217cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static const GrPoint* GetVertexPoint(const void* vertices,
218cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexIndex,
219cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexSize,
220cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int offset = 0) {
221cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
222cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<const GrPoint*>(start + offset +
223cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                       vertexIndex * vertexSize);
224cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
225cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
226cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /**
227cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * Gets a pointer to a GrColor inside a vertex within a vertex array.
228cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertices      the vetex array
229cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexIndex   the index of the vertex in the array
230cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param vertexSize    the size of each vertex in the array
231cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @param offset        the offset in bytes of the vertex color
232cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     * @return pointer to the vertex component as a GrColor
233cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com     */
234cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static GrColor* GetVertexColor(void* vertices,
235cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexIndex,
236cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int vertexSize,
237cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                   int offset) {
238cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        intptr_t start = GrTCast<intptr_t>(vertices);
239cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<GrColor*>(start + offset +
240cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                 vertexIndex * vertexSize);
241cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
242cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    static const GrColor* GetVertexColor(const void* vertices,
243cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexIndex,
244cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int vertexSize,
245cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                         int offset) {
246cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        const intptr_t start = GrTCast<intptr_t>(vertices);
247cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com        return GrTCast<const GrColor*>(start + offset +
248cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com                                       vertexIndex * vertexSize);
249cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    }
250cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
2519b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /// @}
2529b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ///////////////////////////////////////////////////////////////////////////
2549b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /// @name Attribute Bindings
2559b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ////
2569b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2579b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
258f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * The vertex data used by the current program is represented as a bitfield
259f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * of flags. Programs always use positions and may also use texture
260f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * coordinates, per-vertex colors, per-vertex coverage and edge data. Each
261f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * stage can use the explicit texture coordinates as its input texture
2629b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * coordinates or it may use the positions as texture coordinates.
2639b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
2649b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2659b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
2669b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Generates a bit indicating that a texture stage uses texture coordinates
2679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
2689b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * @param stageIdx    the stage that will use texture coordinates.
2699b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
2709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * @return the bit to add to a GrAttribBindings bitfield.
2719b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
2729b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static int ExplicitTexCoordAttribBindingsBit(int stageIdx) {
2739b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        GrAssert(stageIdx < kNumStages);
2749b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        return (1 << stageIdx);
2759b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    }
2769b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2779b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static bool StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx);
2789b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2799b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
2809b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Additional Bits that can be specified in GrAttribBindings.
2819b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
2829b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    enum AttribBindingsBits {
2839b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        /* program uses colors (GrColor) */
2849b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kColor_AttribBindingsBit              = 1 << (kNumStages + 0),
2859b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        /* program uses coverage (GrColor)
2869b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com         */
2879b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kCoverage_AttribBindingsBit           = 1 << (kNumStages + 1),
2889b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        /* program uses edge data. Distance to the edge is used to
2899b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com         * compute a coverage. See GrDrawState::setVertexEdgeType().
2909b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com         */
2919b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kEdge_AttribBindingsBit               = 1 << (kNumStages + 2),
2929b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        // for below assert
2939b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kDummyAttribBindingsBit,
2949b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kHighAttribBindingsBit = kDummyAttribBindingsBit - 1
2959b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    };
2969b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // make sure we haven't exceeded the number of bits in GrAttribBindings.
2979b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings)));
2989b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
2999b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    enum AttribBindings {
3009b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kDefault_AttribBindings = 0
3019b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    };
3029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3039b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
3049b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  Sets attribute bindings for next draw.
3059b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
3069b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  @param bindings    the attribute bindings to set.
3079b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3089b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; }
3099b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3109b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; }
3119b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3129b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ////////////////////////////////////////////////////////////////////////////
3139b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // Helpers for picking apart attribute bindings
3149b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3159b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
3169b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Helper function to determine if program uses explicit texture
3179b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * coordinates.
3189b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
3199b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * @param  bindings  attribute bindings to query
3209b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
3219b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * @return true if program uses texture coordinates,
3229b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *         false otherwise.
3239b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3249b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static bool AttributesBindExplicitTexCoords(GrAttribBindings bindings);
3259b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3269b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
3279b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Determines whether src alpha is guaranteed to be one for all src pixels
3289b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3299b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    bool srcAlphaWillBeOne(GrAttribBindings) const;
3309b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3319b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
3329b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
3339b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3349b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    bool hasSolidCoverage(GrAttribBindings) const;
3359b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3369b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static void VertexAttributesUnitTest();
33791274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com
3389b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /// @}
3399b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3409b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ///////////////////////////////////////////////////////////////////////////
3419b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /// @name Vertex Attribute Indices
3429b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ////
3439b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3449b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
3459b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Vertex attribute indices map the data set in the vertex attribute array
3469b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * to the bindings specified in the attribute bindings. Each binding type
347f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * has an associated index in the attribute array. This index is used to
348f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     * look up the vertex attribute data from the array, and potentially as the
3499b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * attribute index if we're binding attributes in GL.
350f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *
3519b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * Indices which do not have active attribute bindings will be ignored.
3529b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3549b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    enum AttribIndex {
3559b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kPosition_AttribIndex = 0,
3569b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kColor_AttribIndex,
3579b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kCoverage_AttribIndex,
3589b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kEdge_AttribIndex,
3599b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kTexCoord_AttribIndex,
3609b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3619b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kLast_AttribIndex = kTexCoord_AttribIndex
3629b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    };
3639b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static const int kAttribIndexCount = kLast_AttribIndex + 1;
3649b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3659b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // these are used when vertex color and coverage isn't set
3669b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    enum {
3679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt,
3689b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1,
3699b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    };
3709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3719b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    ////////////////////////////////////////////////////////////////////////////
372f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com    // Helpers to set attribute indices. These should match the index in the
373f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com    // current attribute index array.
3749b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3759b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    /**
376f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com     *  Sets index for next draw. This is used to look up the offset
3779b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  from the current vertex attribute array and to bind the attributes.
3789b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *
3799b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  @param index      the attribute index we're setting
3809b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     *  @param value      the value of the index
3819b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     */
3829b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; }
3839b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
3849b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    int getAttribIndex(AttribIndex index) const       { return fAttribIndices[index]; }
385cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
386cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    /// @}
387cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com
388cc78238f0b6aa1a7b3fc767758d9eeef4c1bffa9jvanverth@google.com    ///////////////////////////////////////////////////////////////////////////
3898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Color
3908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
3918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
3928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
3938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets color for next draw to a premultiplied-alpha color.
3948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
3958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param color    the color to set.
3968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
397ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setColor(GrColor color) { fCommon.fColor = color; }
3988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
399ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColor() const { return fCommon.fColor; }
4008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Sets the color to be used for the next draw to be
4038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (r,g,b,a) = (alpha, alpha, alpha, alpha).
4048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
4058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param alpha The alpha value to set as the color.
4068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
4078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setAlpha(uint8_t a) {
4088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        this->setColor((a << 24) | (a << 16) | (a << 8) | a);
4098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
4108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
4128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Add a color filter that can be represented by a color and a mode. Applied
4138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * after color-computing texture stages.
4148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
4158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setColorFilter(GrColor c, SkXfermode::Mode mode) {
416ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterColor = c;
417ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fColorFilterMode = mode;
4188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
4198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
420ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
421ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
4228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4235b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
4245b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     * Constructor sets the color to be 'color' which is undone by the destructor.
4255b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
4265b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoColorRestore : public ::GrNoncopyable {
4275b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
42866a58aca8379a33ccc7572a31c74a3334d08b47csugoi@google.com        AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
429d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
4305b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoColorRestore(GrDrawState* drawState, GrColor color) {
431d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            fDrawState = NULL;
432d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            this->set(drawState, color);
433d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        }
434d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
435d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        void reset() {
436d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            if (NULL != fDrawState) {
437d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com                fDrawState->setColor(fOldColor);
438d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com                fDrawState = NULL;
439d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            }
440d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        }
441d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
442d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        void set(GrDrawState* drawState, GrColor color) {
443d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com            this->reset();
4445b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState = drawState;
4455b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fOldColor = fDrawState->getColor();
4465b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com            fDrawState->setColor(color);
4475b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        }
448d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com
449d62e88e5af39347a8fc2a5abdf5feb67d7ea256dbsalomon@google.com        ~AutoColorRestore() { this->reset(); }
4505b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
4515b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrDrawState*    fDrawState;
4525b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        GrColor         fOldColor;
4535b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
4545b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
4558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
4568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
4578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
4582401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @name Coverage
4592401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ////
4602401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4612401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
462d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Sets a constant fractional coverage to be applied to the draw. The
4632401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * initial value (after construction or reset()) is 0xff. The constant
4642401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * coverage is ignored when per-vertex coverage is provided.
4652401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
4662401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage(uint8_t coverage) {
467ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
4682401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4692401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4702401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /**
4712401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * Version of above that specifies 4 channel per-vertex color. The value
4722401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     * should be premultiplied.
4732401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com     */
4742401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    void setCoverage4(GrColor coverage) {
475ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fCoverage = coverage;
4762401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4772401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4782401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    GrColor getCoverage() const {
479ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fCoverage;
4802401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    }
4812401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4822401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    /// @}
4832401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com
4842401ae8fd3c1f6282f571b5a7e0a499e9f4c09abbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
485adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    /// @name Effect Stages
4868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
4878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
48865eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com    const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
48965eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com        fStages[stageIdx].setEffect(effect);
49065eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com        return effect;
49165eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com    }
49201c34ee59906f729f6ca7d35f0c0e5e2f5e693feskia.committer@gmail.com
49391274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com    const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
49465eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com                                 int attr0, int attr1 = -1) {
49565eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com        fStages[stageIdx].setEffect(effect, attr0, attr1);
496adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return effect;
497adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    }
498adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com
4998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
50068b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com     * Creates a GrSimpleTextureEffect.
5011e8f016305805d4d8cad74aba3a21b78486f9d6ftomhudson@google.com     */
502b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
50308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
50468b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
505adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        this->setEffect(stageIdx, effect)->unref();
506dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com    }
50708283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void createTextureEffect(int stageIdx,
50808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                             GrTexture* texture,
509b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                             const SkMatrix& matrix,
510dfdb7e5240276493077b7c6e1f3cc8b8a0e195babsalomon@google.com                             const GrTextureParams& params) {
51108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert(!this->getStage(stageIdx).getEffect());
51268b58c95384dd6c2fd389a5b4bbf8fc468819454bsalomon@google.com        GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
513adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        this->setEffect(stageIdx, effect)->unref();
5141ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com    }
5151ce49fc91714ce8974d11246d29ebe7b97b5fe98bsalomon@google.com
5167d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    bool stagesDisabled() {
5177d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        for (int i = 0; i < kNumStages; ++i) {
51808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (NULL != fStages[i].getEffect()) {
5197d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                return false;
5207d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com            }
5217d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        }
5223eee8fbe0f280bc1dea59dc0b0ebd8021b51137ftomhudson@google.com        return true;
5237d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    }
524676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
52591274b99722d9be62e077ab979c630c23cdd04b1skia.committer@gmail.com    void disableStage(int stageIdx) {
52665eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com        this->setEffect(stageIdx, NULL);
527ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
528676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com
529972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    /**
530f271cc7183fe48ac64d2d9a454eb013c91b42d53bsalomon@google.com     * Release all the GrEffects referred to by this draw state.
531972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com     */
5327d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    void disableStages() {
533972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        for (int i = 0; i < kNumStages; ++i) {
534676e66096c60615bac52f365111596de5c4ca8a6tomhudson@google.com            this->disableStage(i);
535972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
536972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    }
537972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
5387d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com    class AutoStageDisable : public ::GrNoncopyable {
539972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    public:
5407d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
5417d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com        ~AutoStageDisable() {
542972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            if (NULL != fDrawState) {
5437d6afdd795eb4c7ce8f5a327117cfdba5f957ddbtomhudson@google.com                fDrawState->disableStages();
544972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com            }
545972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        }
546972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    private:
547972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com        GrDrawState* fDrawState;
548972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com    };
549972265db219ce25b5159879c75e6c62efaf0fa79robertphillips@google.com
5508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
55108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com     * Returns the current stage by index.
5528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
55308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    const GrEffectStage& getStage(int stageIdx) const {
55408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrAssert((unsigned)stageIdx < kNumStages);
55508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return fStages[stageIdx];
5568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
559288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcat gives the transformation from the
560288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * old coord system to the new coord system.
5618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
562b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    void preConcatStageMatrices(const SkMatrix& preConcat) {
563cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com        this->preConcatStageMatrices(~0U, preConcat);
564cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    }
565cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    /**
566cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com     * Version of above that applies the update matrix selectively to stages via a mask.
567cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com     */
568cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com    void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
5698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
570cabe00eaced87016647029b6fee08f24dcd062f3bsalomon@google.com            if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
57108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcat);
5728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
5738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
5748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
5758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
576e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    /**
577288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * Called when the source coord system is changing. preConcatInverse is the inverse of the
578288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * transformation from the old coord system to the new coord system. Returns false if the matrix
579288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com     * cannot be inverted.
580e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com     */
581b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
582b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inv;
583e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        bool computed = false;
584e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        for (int i = 0; i < kNumStages; ++i) {
585e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            if (this->isStageEnabled(i)) {
586288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com                if (!computed && !preConcatInverse.invert(&inv)) {
587e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    return false;
588e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                } else {
589e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                    computed = true;
590e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com                }
59108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                fStages[i].preConcatCoordChange(preConcatInverse);
592e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            }
593e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
594e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        return true;
595e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com    }
596e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com
5978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
5988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
5998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
6008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Coverage / Color Stages
6018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
6028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * A common pattern is to compute a color with the initial stages and then
6058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * modulate that color by a coverage value in later stage(s) (AA, mask-
606d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
607d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * computed based on the pre-coverage-modulated color. The division of
608d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * stages between color-computing and coverage-computing is specified by
6098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * this method. Initially this is kNumStages (all stages
6108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are color-computing).
6118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6128f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setFirstCoverageStage(int firstCoverageStage) {
6138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrAssert((unsigned)firstCoverageStage <= kNumStages);
614ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFirstCoverageStage = firstCoverageStage;
6158f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets the index of the first coverage-computing stage.
6198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    int getFirstCoverageStage() const {
621ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return fCommon.fFirstCoverageStage;
6228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///@}
6258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
6278f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Blending
6288f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
6298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6311e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * Sets the blending function coefficients.
6328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * The blend function will be:
6348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *    D' = sat(S*srcCoef + D*dstCoef)
6358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6368f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   where D is the existing destination color, S is the incoming source
6378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   color, and D' is the new destination color that will be written. sat()
6388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *   is the saturation function.
6398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6401e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param srcCoef coefficient applied to the src color.
6411e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param dstCoef coefficient applied to the dst color.
6428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
6438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
644ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fSrcBlend = srcCoeff;
645ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDstBlend = dstCoeff;
6468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #if GR_DEBUG
6478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (dstCoeff) {
64847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDC_GrBlendCoeff:
64947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDC_GrBlendCoeff:
65047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kDA_GrBlendCoeff:
65147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kIDA_GrBlendCoeff:
6528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
6538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
6548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
6568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
6588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        switch (srcCoeff) {
65947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSC_GrBlendCoeff:
66047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISC_GrBlendCoeff:
66147059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kSA_GrBlendCoeff:
66247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com        case kISA_GrBlendCoeff:
6638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrPrintf("Unexpected src blend coeff. Won't work correctly with"
6648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                     "coverage stages.\n");
6658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        default:
6678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            break;
6688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
6698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    #endif
6708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
672ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
673ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
6748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
6768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                          GrBlendCoeff* dstBlendCoeff) const {
677ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *srcBlendCoeff = fCommon.fSrcBlend;
678ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        *dstBlendCoeff = fCommon.fDstBlend;
6798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
6808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the blending function constant referenced by the following blending
6831e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * coefficients:
68447059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstC_GrBlendCoeff
68547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstC_GrBlendCoeff
68647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kConstA_GrBlendCoeff
68747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com     *      kIConstA_GrBlendCoeff
6888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
6898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param constant the constant to set
6908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
691ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
6928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
6948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the last value set by setBlendConstant()
6958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the blending constant value
6968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
697ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
6988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6992b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
7002b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Determines whether multiplying the computed per-pixel color by the pixel's fractional
7012b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * coverage before the blend will give the correct final destination color. In general it
7022b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * will not as coverage is applied after blending.
7032b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
7042b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    bool canTweakAlphaForCoverage() const;
7052b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
7062b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
7072b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Optimizations for blending / coverage to that can be applied based on the current state.
7082b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
7092b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    enum BlendOptFlags {
7102b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7112b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * No optimization
7122b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7132b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kNone_BlendOpt                  = 0,
7142b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7152b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Don't draw at all
7162b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7172b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kSkipDraw_BlendOptFlag          = 0x1,
7182b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7192b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Emit the src color, disable HW blending (replace dst with src)
7202b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7212b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kDisableBlend_BlendOptFlag      = 0x2,
7222b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7232b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * The coverage value does not have to be computed separately from alpha, the the output
7242b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * color can be the modulation of the two.
7252b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7262b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kCoverageAsAlpha_BlendOptFlag   = 0x4,
7272b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7282b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
7292b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * "don't cares".
7302b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7312b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kEmitCoverage_BlendOptFlag      = 0x8,
7322b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        /**
7332b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         * Emit transparent black instead of the src color, no need to compute coverage.
7342b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com         */
7352b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com        kEmitTransBlack_BlendOptFlag    = 0x10,
7362b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    };
7372b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
7382b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
7392b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    /**
7402b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Determines what optimizations can be applied based on the blend. The coefficients may have
7412b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
7422b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * params that receive the tweaked coefficients. Normally the function looks at the current
7432b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
7442b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * determine the blend optimizations that would be used if there was partial pixel coverage.
7452b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     *
7462b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
7472b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     * playback) must call this function and respect the flags that replace the output color.
7482b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com     */
7492b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    BlendOptFlags getBlendOpts(bool forceCoverage = false,
7502b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com                               GrBlendCoeff* srcCoeff = NULL,
7512b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com                               GrBlendCoeff* dstCoeff = NULL) const;
7522b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
7538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
7548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
7568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name View Matrix
7578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
7588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
760a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com     * Sets the matrix applied to vertex positions.
7618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * In the post-view-matrix space the rectangle [0,w]x[0,h]
7638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * fully covers the render target. (w and h are the width and height of the
764ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the render-target.)
7658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
766ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
7678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets a writable pointer to the view matrix.
7708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
771ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
7728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
7758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = V*m where V is the old view matrix,
7778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
7788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
7798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
7808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
7828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
783ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
7848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Multiplies the current view matrix by a matrix
7878f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  After this call V' = m*V where V is the old view matrix,
7898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  m is the parameter to this function, and V' is the new view matrix.
7908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  (We consider positions to be column vectors so position vector p is
7918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  transformed by matrix X as p' = X*p.)
7928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
7938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  @param m the matrix used to modify the view matrix.
7948f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
795ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
7968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
7978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
7988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Retrieves the current view matrix
7998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current view matrix.
8008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
801ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
8028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
8048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Retrieves the inverse of the current view matrix.
8058f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
8068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  If the current view matrix is invertible, return true, and if matrix
8078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  is non-null, copy the inverse into it. If the current view matrix is
8088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  non-invertible, return false and ignore the matrix parameter.
8098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
8108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param matrix if not null, will receive a copy of the current inverse.
8118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
812b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    bool getViewInverse(SkMatrix* matrix) const {
8138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // TODO: determine whether we really need to leave matrix unmodified
8148f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // at call sites when inversion fails.
815b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix inverse;
816ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fCommon.fViewMatrix.invert(&inverse)) {
8178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (matrix) {
8188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                *matrix = inverse;
8198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
8208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            return true;
8218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
8228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        return false;
8238f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
8248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
8255b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
8265b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
8275b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
8282fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * Preconcats the current view matrix and restores the previous view matrix in the destructor.
829c196b522d06919885c6bbe28b7b06d2e5b2cb9bfbsalomon@google.com     * Effect matrices are automatically adjusted to compensate.
8305b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
8318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoViewMatrixRestore : public ::GrNoncopyable {
8328f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
8338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoViewMatrixRestore() : fDrawState(NULL) {}
8342fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8352fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoViewMatrixRestore(GrDrawState* ds,
836b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                              const SkMatrix& preconcatMatrix,
8372fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                              uint32_t explicitCoordStageMask = 0) {
8388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
8392fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(ds, preconcatMatrix, explicitCoordStageMask);
8408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
8412fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8422fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        ~AutoViewMatrixRestore() { this->restore(); }
8432fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
844a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
845a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
846a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
8472fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void restore();
848f467ce7bc33af5f496e0619387551aedec6d2517skia.committer@gmail.com
8492fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        void set(GrDrawState* drawState,
850b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                 const SkMatrix& preconcatMatrix,
8512fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                 uint32_t explicitCoordStageMask = 0);
8522fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
853ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com        bool isSet() const { return NULL != fDrawState; }
8542fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
8558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
856288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
857b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
85808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
859288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
8609381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
8619381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
8625b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    ////////////////////////////////////////////////////////////////////////////
8635b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
8645b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    /**
8652fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * This sets the view matrix to identity and adjusts stage matrices to compensate. The
8662fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * destructor undoes the changes, restoring the view matrix that was set before the
8672fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * constructor. It is similar to passing the inverse of the current view matrix to
8682fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com     * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
8695b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com     */
8705b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    class AutoDeviceCoordDraw : ::GrNoncopyable {
8715b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    public:
8722fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        AutoDeviceCoordDraw() : fDrawState(NULL) {}
8735b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        /**
8742fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
8752fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
8762fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com         * to specify such stages.
8775b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com         */
8785b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        AutoDeviceCoordDraw(GrDrawState* drawState,
8792fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com                            uint32_t explicitCoordStageMask = 0) {
8802fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            fDrawState = NULL;
8812fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            this->set(drawState, explicitCoordStageMask);
8822fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        }
8832fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
884a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        ~AutoDeviceCoordDraw() { this->restore(); }
885a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com
8862fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com        bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
8872fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
888a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
889a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns true if this object was successfully initialized on to a GrDrawState. It may
890a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * return false because a non-default constructor or set() were never called or because
891a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * the view matrix was not invertible.
892a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
8935b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com        bool succeeded() const { return NULL != fDrawState; }
8942fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
895a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
896a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Returns the matrix that was set previously set on the drawState. This is only valid
897a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * if succeeded returns true.
898a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
899b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        const SkMatrix& getOriginalMatrix() const {
900a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            GrAssert(this->succeeded());
901a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com            return fViewMatrix;
902a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        }
9032fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
904a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        /**
905a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         * Can be called prior to destructor to restore the original matrix.
906a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com         */
907a834746cc1bd92301fd0840a221ca1623c0bbb29bsalomon@google.com        void restore();
9082fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com
9095b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    private:
910288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        GrDrawState*                        fDrawState;
911b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com        SkMatrix                            fViewMatrix;
91208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        GrEffectStage::SavedCoordChange     fSavedCoordChanges[GrDrawState::kNumStages];
913288d9549b42a4eb934e814790f2b7a81f017a9c5bsalomon@google.com        uint32_t                            fRestoreMask;
9145b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com    };
9155b3e890c376f2211218c43edd11939cfc78fd60absalomon@google.com
9168f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
9178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9188f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
9198f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Render Target
9208f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
9218f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9228f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
923ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Sets the render-target used at the next drawing call
9248f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
9258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param target  The render target to set.
9268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
927d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com    void setRenderTarget(GrRenderTarget* target) {
928ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fRenderTarget.reset(SkSafeRef(target));
9299ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com    }
9308f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
932ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * Retrieves the currently set render-target.
9338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
9348f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return    The currently set render target.
9358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
936ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
937ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
9388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    class AutoRenderTargetRestore : public ::GrNoncopyable {
9408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    public:
941cadbcb8e536f89babb4e165bfdca18384e97d582bsalomon@google.com        AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
9428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
9438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            fDrawState = NULL;
9447460b378d68217167013ca889a4cdcae742908e7robertphillips@google.com            fSavedTarget = NULL;
9458f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            this->set(ds, newTarget);
9468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
9479ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        ~AutoRenderTargetRestore() { this->restore(); }
9489ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9499ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void restore() {
9508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != fDrawState) {
9518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fDrawState->setRenderTarget(fSavedTarget);
9529ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = NULL;
9538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
9549ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            GrSafeSetNull(fSavedTarget);
9559ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        }
9569ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9579ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com        void set(GrDrawState* ds, GrRenderTarget* newTarget) {
9589ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com            this->restore();
9599ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com
9608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            if (NULL != ds) {
9619ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                GrAssert(NULL == fSavedTarget);
9628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                fSavedTarget = ds->getRenderTarget();
9639ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                SkSafeRef(fSavedTarget);
9648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com                ds->setRenderTarget(newTarget);
9659ec075366ed94802a142fc5e948d19a774f85b43robertphillips@google.com                fDrawState = ds;
9668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            }
9678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        }
9688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    private:
9698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState* fDrawState;
9708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrRenderTarget* fSavedTarget;
9718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
9728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
9748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
9768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Stencil
9778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
9788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
9808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Sets the stencil settings to use for the next draw.
9818f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Changing the clip has the side-effect of possibly zeroing
9828f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * out the client settable stencil bits. So multipass algorithms
9838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * using stencil should not change the clip between passes.
9848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param settings  the stencil settings to use.
9858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
9868f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setStencil(const GrStencilSettings& settings) {
987ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings = settings;
9888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
9898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
9908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
9918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Shortcut to disable stencil testing and ops.
9928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
9938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableStencil() {
994ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fStencilSettings.setDisabled();
9958f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
9968f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
997ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
9988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
999ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
10008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
10028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10038f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
10048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    // @name Edge AA
10051e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com    // Edge equations can be specified to perform anti-aliasing. Because the
10067ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // edges are specified as per-vertex data, vertices that are shared by
10077ffe6810c6787f7a353ef3fe8fab3fc6440aae19bsalomon@google.com    // multiple edges must be split.
10088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    //
10098f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
10108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * When specifying edges as vertex data this enum specifies what type of
101381712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com     * edges are in use. The edges are always 4 SkScalars in memory, even when
10149381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the edge type requires fewer than 4.
101593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *
101693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
101793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com     *       (either adjust in VS or use origin_upper_left in GLSL)
10189381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
10199381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum VertexEdgeType {
10209381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        /* 1-pixel wide line
10219381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com           2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
10229381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kHairLine_EdgeType,
1023d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        /* Quadratic specified by u^2-v canonical coords (only 2
102469cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           components used). Coverage based on signed distance with negative
102593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           being inside, positive outside. Edge specified in window space
102693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com           (y-down) */
102769cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kQuad_EdgeType,
102869cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        /* Same as above but for hairline quadratics. Uses unsigned distance.
102969cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com           Coverage is min(0, 1-distance). */
103069cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kHairQuad_EdgeType,
103169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com
103269cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        kVertexEdgeTypeCnt
10339381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
10349381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
10359381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
1036d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com     * Determines the interpretation per-vertex edge data when the
10379b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com     * kEdge_AttribBindingsBit is set (see GrDrawTarget). When per-vertex edges
10388f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * are not specified the value of this setting has no effect.
10398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10408f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setVertexEdgeType(VertexEdgeType type) {
104169cc6ad20ed03f35f9d3c8119a2c32187669a22bbsalomon@google.com        GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
1042ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fVertexEdgeType = type;
10438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
10448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1045ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
10468f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10478f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
10488f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
10508f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name State Flags
10518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
10528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  Flags that affect rendering. Controlled using enable/disableState(). All
10558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *  default to disabled.
10568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
10578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum StateBits {
10588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Perform dithering. TODO: Re-evaluate whether we need this bit
10608f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10618f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDither_StateBit        = 0x01,
10628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
1063cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
1064cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
1065cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * the 3D API.
10668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kHWAntialias_StateBit   = 0x02,
10688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Draws will respect the clip, otherwise the clip is ignored.
10708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kClip_StateBit          = 0x04,
10728f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        /**
10738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * Disables writing to the color buffer. Useful when performing stencil
10748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         * operations.
10758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com         */
10768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kNoColorWrites_StateBit = 0x08,
10770342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com
1078cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com        /**
1079cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * Usually coverage is applied after color blending. The color is blended using the coeffs
1080cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
1081cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
1082cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * this case there is no distinction between coverage and color and the caller needs direct
1083cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * control over the blend coeffs. When set, there will be a single blend step controlled by
1084cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         * setBlendFunc() which will use coverage*color as the src color.
1085cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         */
1086cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com         kCoverageDrawing_StateBit = 0x10,
1087cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
10888f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        // Users of the class may add additional bits to the vector
10898f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kDummyStateBit,
10908f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kLastPublicStateBit = kDummyStateBit-1,
10918f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
10928f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
10938f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void resetStateFlags() {
1094ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits = 0;
10950fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com    }
10960fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
10978f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
10988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Enable render state settings.
10998f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
11001e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to enable
11018f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
11028f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void enableState(uint32_t stateBits) {
1103ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits |= stateBits;
11048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11050fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11068f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
11078f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Disable render state settings.
11088f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     *
11091e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits specifying the states to disable
11108f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
11118f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void disableState(uint32_t stateBits) {
1112ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fFlagBits &= ~(stateBits);
11138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11140fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1115d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    /**
1116d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * Enable or disable stateBits based on a boolean.
1117d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     *
11181e269b5a08610da13c3aee23809bb45b17e7b663bsalomon@google.com     * @param stateBits bitfield of StateBits to enable or disable
1119d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     * @param enable    if true enable stateBits, otherwise disable
1120d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com     */
1121d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    void setState(uint32_t stateBits, bool enable) {
1122d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        if (enable) {
1123d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->enableState(stateBits);
1124d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        } else {
1125d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com            this->disableState(stateBits);
1126d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com        }
1127d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com    }
1128d5d69ffaea117428972db48796f7e75f0d1dab34bsalomon@google.com
11298f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isDitherState() const {
1130ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kDither_StateBit);
11318f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11320fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11338f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isHWAntialiasState() const {
1134ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
11358f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11360fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11378f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isClipState() const {
1138ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kClip_StateBit);
11398f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11400fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
11418f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isColorWriteDisabled() const {
1142ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
11438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11448f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1145cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    bool isCoverageDrawing() const {
1146ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
1147cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com    }
1148cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com
11498f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    bool isStateFlagEnabled(uint32_t stateBit) const {
1150ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        return 0 != (stateBit & fCommon.fFlagBits);
11518f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11528f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11538f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
11548f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11558f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
11568f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @name Face Culling
11578f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ////
11588f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    enum DrawFace {
1160978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        kInvalid_DrawFace = -1,
1161978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com
11628f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kBoth_DrawFace,
11638f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCCW_DrawFace,
11648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        kCW_DrawFace,
11658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    };
11668f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11678f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
11688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Controls whether clockwise, counterclockwise, or both faces are drawn.
11698f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @param face  the face(s) to draw.
11708f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
11718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    void setDrawFace(DrawFace face) {
1172978c8c61ba1e792567e9d8e6629c2c4ee59727b7bsalomon@google.com        GrAssert(kInvalid_DrawFace != face);
1173ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon.fDrawFace = face;
11748f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    }
11758f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11768f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /**
11778f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * Gets whether the target is drawing clockwise, counterclockwise,
11788f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * or both faces.
11798f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     * @return the current draw face(s).
11808f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com     */
1181ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    DrawFace getDrawFace() const { return fCommon.fDrawFace; }
1182d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
11838f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    /// @}
11848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
11858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    ///////////////////////////////////////////////////////////////////////////
118662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
1187f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    bool isStageEnabled(int s) const {
1188f13f58804659175925042a291304d483a4fd9278tomhudson@google.com        GrAssert((unsigned)s < kNumStages);
118908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        return (NULL != fStages[s].getEffect());
1190f13f58804659175925042a291304d483a4fd9278tomhudson@google.com    }
1191f13f58804659175925042a291304d483a4fd9278tomhudson@google.com
11929381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator ==(const GrDrawState& s) const {
1193ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
11948fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com            return false;
11958fe84b53a64b5d92f3aabdd8e7fc7b2ee15c0a75bsalomon@google.com        }
1196ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        if (fVertexAttribs != s.fVertexAttribs) {
11979b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            return false;
11989b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        }
11999b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        for (int i = 0; i < kAttribIndexCount; ++i) {
1200f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com            if ((i == kPosition_AttribIndex ||
12019b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                    s.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
12029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                fAttribIndices[i] != s.fAttribIndices[i]) {
12039b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                return false;
12049b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            }
12059b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        }
120662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
1207f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            bool enabled = this->isStageEnabled(i);
1208f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            if (enabled != s.isStageEnabled(i)) {
1209f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com                return false;
1210f2f8fc37265a6ef06897117451a3a9238287c13bbsalomon@google.com            }
121108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com            if (enabled && this->fStages[i] != s.fStages[i]) {
121262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                return false;
121362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
121462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
121562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return true;
12169381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    }
12179381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator !=(const GrDrawState& s) const { return !(*this == s); }
121862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
1219ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    GrDrawState& operator= (const GrDrawState& s) {
1220ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        this->setRenderTarget(s.fRenderTarget.get());
1221ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        fCommon = s.fCommon;
12229b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        fVertexAttribs = s.fVertexAttribs;
12239b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        for (int i = 0; i < kAttribIndexCount; i++) {
12249b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            fAttribIndices[i] = s.fAttribIndices[i];
12259b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        }
122662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
1227e742bf0ab19659145325ac894f7e0b78c8efbd89tomhudson@google.com            if (s.isStageEnabled(i)) {
122808283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                this->fStages[i] = s.fStages[i];
122962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
123062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
123162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return *this;
123262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    }
123362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
123462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.comprivate:
12352e3d144dfdbc4596d33baef7396316f88f412cc8bsalomon@google.com
1236ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1237ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct CommonState {
1238ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // These fields are roughly sorted by decreasing likelihood of being different in op==
1239ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColor;
12409b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        GrAttribBindings                fAttribBindings;
1241ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkMatrix                        fViewMatrix;
1242ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fSrcBlend;
1243ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrBlendCoeff                    fDstBlend;
1244ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fBlendConstant;
1245ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        uint32_t                        fFlagBits;
1246ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        VertexEdgeType                  fVertexEdgeType;
1247ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrStencilSettings               fStencilSettings;
1248ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        int                             fFirstCoverageStage;
1249ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fCoverage;
1250ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SkXfermode::Mode                fColorFilterMode;
1251ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrColor                         fColorFilterColor;
1252ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DrawFace                        fDrawFace;
1253ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator== (const CommonState& other) const {
1254ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return fColor == other.fColor &&
12559b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                   fAttribBindings == other.fAttribBindings &&
1256ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1257ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fSrcBlend == other.fSrcBlend &&
1258ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDstBlend == other.fDstBlend &&
1259ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fBlendConstant == other.fBlendConstant &&
1260ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFlagBits == other.fFlagBits &&
1261ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fVertexEdgeType == other.fVertexEdgeType &&
1262ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fStencilSettings == other.fStencilSettings &&
1263ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fFirstCoverageStage == other.fFirstCoverageStage &&
1264ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fCoverage == other.fCoverage &&
1265ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterMode == other.fColorFilterMode &&
1266ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fColorFilterColor == other.fColorFilterColor &&
1267ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                   fDrawFace == other.fDrawFace;
1268ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1269ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool operator!= (const CommonState& other) const { return !(*this == other); }
1270ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1271ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1272ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1273ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState must directly reference GrEffects, however. */
1274ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    struct SavedEffectStage {
1275ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        SavedEffectStage() : fEffect(NULL) {}
1276ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        const GrEffect*                    fEffect;
1277ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GrEffectStage::SavedCoordChange    fCoordChange;
1278ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1279ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1280ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.compublic:
1281ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    /**
1282ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1283ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1284ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * dispose mechanism returns them to the cache. This allows recycling resources through the
1285ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     * the cache while they are in a deferred draw queue.
1286ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com     */
1287ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    class DeferredState {
1288ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    public:
1289ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        DeferredState() : fRenderTarget(NULL) {
1290ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = false;)
1291ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1292ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        // TODO: Remove this when DeferredState no longer holds a ref to the RT
1293ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        ~DeferredState() { SkSafeUnref(fRenderTarget); }
1294ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1295ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void saveFrom(const GrDrawState& drawState) {
1296ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fCommon = drawState.fCommon;
1297ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1298ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            fRenderTarget = drawState.fRenderTarget.get();
1299ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            SkSafeRef(fRenderTarget);
13009b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            fVertexAttribs = drawState.fVertexAttribs;
13019b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            for (int i = 0; i < kAttribIndexCount; i++) {
13029b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                fAttribIndices[i] = drawState.fAttribIndices[i];
13039b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            }
1304ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1305ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1306ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            // and recycle them to the cache (if no one else is holding a ref to the resources).
1307ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1308ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].saveFrom(drawState.fStages[i]);
1309ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1310ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GR_DEBUGCODE(fInitialized = true;)
1311ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1312ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1313ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        void restoreTo(GrDrawState* drawState) {
1314ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            GrAssert(fInitialized);
1315ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->fCommon = fCommon;
1316ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            drawState->setRenderTarget(fRenderTarget);
13179b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            drawState->fVertexAttribs = fVertexAttribs;
13189b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            for (int i = 0; i < kAttribIndexCount; i++) {
13199b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                drawState->fAttribIndices[i] = fAttribIndices[i];
13209b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            }
1321ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1322ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                fStages[i].restoreTo(&drawState->fStages[i]);
1323ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1324ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1325ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1326ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        bool isEqual(const GrDrawState& state) const {
1327ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1328ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                return false;
1329ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
13309b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            for (int i = 0; i < kAttribIndexCount; ++i) {
1331f140f18878215d6b4f21a94485cd1d2dbce8e976skia.committer@gmail.com                if ((i == kPosition_AttribIndex ||
13329b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                     state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
13339b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                    fAttribIndices[i] != state.fAttribIndices[i]) {
13349b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                    return false;
13359b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                }
13369b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            }
1337ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            if (fVertexAttribs != state.fVertexAttribs) {
13389b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com                return false;
13399b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            }
1340ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            for (int i = 0; i < kNumStages; ++i) {
1341dcd69bfca1d8e85ef5abc4e54f1e4b820d38e428bsalomon@google.com                if (!fStages[i].isEqual(state.fStages[i])) {
1342ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                    return false;
1343ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com                }
1344ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            }
1345ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com            return true;
1346ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        }
1347ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1348ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    private:
13499b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        GrRenderTarget*                       fRenderTarget;
13509b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        CommonState                           fCommon;
13519b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        int                                   fAttribIndices[kAttribIndexCount];
13529b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
13539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        GrEffectStage::DeferredStage          fStages[kNumStages];
1354ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1355ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com        GR_DEBUGCODE(bool fInitialized;)
1356ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com    };
1357ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.com
1358ca43208e4aaac817fbc8265542f995f24a3fb7bfbsalomon@google.comprivate:
13599b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // helper array to let us check the current bindings so we know what bound attrib indices
13609b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    // we care about
13619b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
13629b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
13639b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    SkAutoTUnref<GrRenderTarget>           fRenderTarget;
13649b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    CommonState                            fCommon;
13659b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    int                                    fAttribIndices[kAttribIndexCount];
13669b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrVertexAttribArray<kVertexAttribCnt>  fVertexAttribs;
13679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrEffectStage                          fStages[kNumStages];
13688f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
1369fa35e3ddcc9d130ce87c927218bdf27879c38711reed@google.com    typedef GrRefCnt INHERITED;
13709381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com};
13719381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
13722b446734cfa8201e5478648988de86b646cb9544bsalomon@google.comGR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
13732b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com
13749381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#endif
1375