GrDrawState.h revision 3d0835b6ac0003c18147b6e9ca76a497b92d1d40
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
119381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrColor.h"
129381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrMatrix.h"
139381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrSamplerState.h"
149381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "GrStencil.h"
159381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
169381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#include "SkXfermode.h"
179381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
189381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.comclass GrRenderTarget;
199381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.comclass GrTexture;
209381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
219381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.comstruct GrDrawState {
229381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
239381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
249381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * Number of texture stages. Each stage takes as input a color and
259381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * 2D texture coordinates. The color input to the first enabled stage is the
269381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * per-vertex color or the constant color (setColor/setAlpha) if there are
279381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * no per-vertex colors. For subsequent stages the input color is the output
289381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * color from the previous enabled stage. The output color of each stage is
299381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the input color modulated with the result of a texture lookup. Texture
309381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * lookups are specified by a texture a sampler (setSamplerState). Texture
319381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * coordinates for each stage come from the vertices based on a
329381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * GrVertexLayout bitfield. The output fragment color is the output color of
339381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the last enabled stage. The presence or absence of texture coordinates
349381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * for each stage in the vertex layout indicates whether a stage is enabled
359381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * or not.
369381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
379381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum {
389381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kNumStages = 3,
399381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kMaxTexCoords = kNumStages
409381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
419381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
4239ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com    /**
4339ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com     *  Bitfield used to indicate a set of stages.
4439ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com     */
4539ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com    typedef uint32_t StageMask;
4639ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com    GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
4739ee0ffa72fbd5df6d3ec6db4fdad0c1bc3946fdbsalomon@google.com
483d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    enum DrawFace {
493d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        kBoth_DrawFace,
503d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        kCCW_DrawFace,
513d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        kCW_DrawFace,
529381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
539381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
543d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com     /**
559381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * When specifying edges as vertex data this enum specifies what type of
569381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * edges are in use. The edges are always 4 GrScalars in memory, even when
579381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the edge type requires fewer than 4.
589381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
599381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum VertexEdgeType {
609381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        /* 1-pixel wide line
619381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com           2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
629381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kHairLine_EdgeType,
639381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        /* 1-pixel wide quadratic
649381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com           u^2-v canonical coords (only 2 components used) */
659381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        kHairQuad_EdgeType
669381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
679381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
689381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    /**
699381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * The absolute maximum number of edges that may be specified for
709381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * a single draw call when performing edge antialiasing.  This is used for
719381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * the size of several static buffers, so implementations of getMaxEdges()
729381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     * (below) should clamp to this value.
739381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com     */
749381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    enum {
7562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // TODO: this should be 32 when GrTesselatedPathRenderer is used
7662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // Visual Studio 2010 does not permit a member array of size 0.
7762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        kMaxEdges = 1
789381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
799381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
809381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    class Edge {
819381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com      public:
829381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        Edge() {}
839381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        Edge(float x, float y, float z) : fX(x), fY(y), fZ(z) {}
849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        GrPoint intersect(const Edge& other) {
859381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com            return GrPoint::Make(
8672e49b8982586a5d8b0425f16d909c05a36ea8c3bsalomon@google.com                SkFloatToScalar((fY * other.fZ - other.fY * fZ) /
8772e49b8982586a5d8b0425f16d909c05a36ea8c3bsalomon@google.com                                (fX * other.fY - other.fX * fY)),
8872e49b8982586a5d8b0425f16d909c05a36ea8c3bsalomon@google.com                SkFloatToScalar((fX * other.fZ - other.fX * fZ) /
8972e49b8982586a5d8b0425f16d909c05a36ea8c3bsalomon@google.com                                (other.fX * fY - fX * other.fY)));
909381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        }
919381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com        float fX, fY, fZ;
929381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    };
939381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
943d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrDrawState() {
953d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // make sure any pad is zero for memcmp
963d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // all GrDrawState members should default to something
973d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // valid by the memset
983d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        memset(this, 0, sizeof(GrDrawState));
993d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com
1003d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // memset exceptions
1013d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        fColorFilterXfermode = SkXfermode::kDstIn_Mode;
1023d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        fFirstCoverageStage = kNumStages;
1030fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1043d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // pedantic assertion that our ptrs will
1053d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // be NULL (0 ptr is mem addr 0)
1063d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        GrAssert((intptr_t)(void*)NULL == 0LL);
1070fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1083d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        // default stencil setting should be disabled
1093d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        GrAssert(fStencilSettings.isDisabled());
1103d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com        fFirstCoverageStage = kNumStages;
1110fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com    }
1120fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1133d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    uint8_t                 fFlagBits;
1143d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrBlendCoeff            fSrcBlend : 8;
1153d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrBlendCoeff            fDstBlend : 8;
1163d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    DrawFace                fDrawFace : 8;
1173d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    uint8_t                 fFirstCoverageStage;
1183d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    SkXfermode::Mode        fColorFilterXfermode : 8;
1193d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrColor                 fBlendConstant;
1203d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrTexture*              fTextures[kNumStages];
1213d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrRenderTarget*         fRenderTarget;
1223d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrColor                 fColor;
1233d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrColor                 fColorFilterColor;
1240fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1253d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrStencilSettings       fStencilSettings;
1263d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrMatrix                fViewMatrix;
1270fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1283d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // @{ Data for GrTesselatedPathRenderer
1293d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // TODO: currently ignored in copying & comparison for performance.
1303d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // Must be considered if GrTesselatedPathRenderer is being used.
1310fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1323d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    int                     fEdgeAANumEdges;
1333d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    VertexEdgeType          fVertexEdgeType;
1343d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    Edge                    fEdgeAAEdges[kMaxEdges];
1350fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1363d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // @}
1370fec61d19ca9088d54f58bd0a67150171b83d66cbsalomon@google.com
1383d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // This field must be last; it will not be copied or compared
1393d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    // if the corresponding fTexture[] is NULL.
1403d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com    GrSamplerState          fSamplerStates[kNumStages];
14162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
14262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // Most stages are usually not used, so conditionals here
14362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // reduce the expected number of bytes touched by 50%.
1449381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator ==(const GrDrawState& s) const {
14562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        if (memcmp(this, &s, this->leadingBytes())) return false;
14662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
14762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
14862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            if (fTextures[i] &&
1493d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com                memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i],
15062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                       sizeof(GrSamplerState))) {
15162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                return false;
15262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
15362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
15462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
15562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return true;
1569381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    }
1579381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com    bool operator !=(const GrDrawState& s) const { return !(*this == s); }
15862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
15962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // Most stages are usually not used, so conditionals here
16062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    // reduce the expected number of bytes touched by 50%.
16162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    GrDrawState& operator =(const GrDrawState& s) {
16262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        memcpy(this, &s, this->leadingBytes());
16362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
16462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        for (int i = 0; i < kNumStages; i++) {
16562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            if (s.fTextures[i]) {
1663d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com                memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i],
16762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                       sizeof(GrSamplerState));
16862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com            }
16962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        }
17062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
17162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return *this;
17262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    }
17362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
17462b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.comprivate:
17562b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    size_t leadingBytes() const {
17662b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // Can't use offsetof() with non-POD types, so stuck with pointer math.
17762b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // TODO: ignores GrTesselatedPathRenderer data structures. We don't
17862b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // have a compile-time flag that lets us know if it's being used, and
17962b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        // checking at runtime seems to cost 5% performance.
18062b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com        return (size_t) ((unsigned char*)&fEdgeAANumEdges -
18162b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com                         (unsigned char*)&fFlagBits);
18262b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com    }
18362b09687857c923b1044be0aef4dd900f8379b22tomhudson@google.com
1849381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com};
1859381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com
1869381363050ec9d3e724076a8e9152bfa9a8de1d1tomhudson@google.com#endif
1873d0835b6ac0003c18147b6e9ca76a497b92d1d40bsalomon@google.com
188