blob: 8b7a36e4662a0710e7b9586ecbc692656feaf7ba [file] [log] [blame]
tomhudson@google.com93813632011-10-27 20:21:16 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000011#include "GrBackendEffectFactory.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000012#include "GrColor.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000013#include "GrEffectStage.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000014#include "GrRefCnt.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000015#include "GrRenderTarget.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000016#include "GrStencil.h"
17#include "GrTemplates.h"
18#include "GrTexture.h"
bsalomon@google.com31ec7982013-03-27 18:14:57 +000019#include "GrTypesPriv.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000020#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000021
jvanverth@google.comcc782382013-01-28 20:39:48 +000022#include "SkMatrix.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000023#include "SkXfermode.h"
24
bsalomon@google.comaf84e742012-10-05 13:23:24 +000025class GrPaint;
tomhudson@google.com93813632011-10-27 20:21:16 +000026
jvanverth@google.com9b855c72013-03-01 18:21:22 +000027/**
jvanverth@google.com9b855c72013-03-01 18:21:22 +000028 * Type used to describe how attributes bind to program usage
29 */
30typedef int GrAttribBindings;
31
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000032class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000033public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000034 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000035
tomhudson@google.com93813632011-10-27 20:21:16 +000036 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000037 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
38 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
39 * output from the previous enabled stage and a position. The position is either derived from
40 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
jvanverth@google.com9b855c72013-03-01 18:21:22 +000041 * GrAttribBindings used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000042 *
bsalomon@google.com13221342012-10-26 13:41:59 +000043 * The stages are divided into two sets, color-computing and coverage-computing. The final color
44 * stage produces the final pixel color. The coverage-computing stages function exactly as the
45 * color-computing but the output of the final coverage stage is treated as a fractional pixel
46 * coverage rather than as input to the src/dst color blend step.
47 *
48 * The input color to the first enabled color-stage is either the constant color or interpolated
jvanverth@google.com9b855c72013-03-01 18:21:22 +000049 * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
bsalomon@google.com4647f902013-03-26 14:45:27 +000050 * either a constant coverage (usually full-coverage) or interpolated per-vertex coverage.
bsalomon@google.com13221342012-10-26 13:41:59 +000051 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000052 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
53 * the color / coverage distinction.
54 *
bsalomon@google.com13221342012-10-26 13:41:59 +000055 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
56 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
57 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000058 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000059 */
60 enum {
twiz@google.com58071162012-07-18 21:41:50 +000061 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000062 };
63
bsalomon@google.comca432082013-01-23 19:53:46 +000064 GrDrawState() {
reed@google.com75847192013-01-28 20:53:22 +000065#if GR_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000066 VertexAttributesUnitTest();
reed@google.com75847192013-01-28 20:53:22 +000067#endif
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000068 this->reset();
69 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000070
bsalomon@google.comca432082013-01-23 19:53:46 +000071 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000072 *this = state;
73 }
74
robertphillips@google.com9ec07532012-06-22 12:01:30 +000075 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000076 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000077 }
78
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000080 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000081 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000082 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000083 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000084
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000085 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000086
bsalomon@google.comca432082013-01-23 19:53:46 +000087 fRenderTarget.reset(NULL);
88
jvanverth@google.com9b855c72013-03-01 18:21:22 +000089 this->setDefaultVertexAttribs();
90
bsalomon@google.comca432082013-01-23 19:53:46 +000091 fCommon.fColor = 0xffffffff;
92 fCommon.fViewMatrix.reset();
93 fCommon.fSrcBlend = kOne_GrBlendCoeff;
94 fCommon.fDstBlend = kZero_GrBlendCoeff;
95 fCommon.fBlendConstant = 0x0;
96 fCommon.fFlagBits = 0x0;
bsalomon@google.comca432082013-01-23 19:53:46 +000097 fCommon.fStencilSettings.setDisabled();
98 fCommon.fFirstCoverageStage = kNumStages;
99 fCommon.fCoverage = 0xffffffff;
100 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
101 fCommon.fColorFilterColor = 0x0;
102 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000103 }
104
105 /**
106 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000107 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000108 * GrPaint equivalents are not modified. GrPaint has fewer stages than
109 * GrDrawState. The extra GrDrawState stages are disabled.
110 */
111 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000112
113 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000114 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000115 ////
116
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000117 enum {
118 kVertexAttribCnt = 6,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000119 };
120
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121 /**
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000122 * The format of vertices is represented as an array of vertex attribute
123 * pair, with each pair representing the type of the attribute and the
124 * offset in the vertex structure (see GrVertexAttrib, above).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000125 *
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000126 * This will only set up the vertex geometry. To bind the attributes in
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000127 * the shaders, attribute indices and attribute bindings need to be set
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000128 * as well.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000129 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000130
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000131 /**
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000132 * Sets vertex attributes for next draw.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000133 *
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000134 * @param attribs the array of vertex attributes to set.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000135 * @param count the number of attributes being set.
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000136 * limited to a count of kVertexAttribCnt.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000137 */
138 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000139
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000140 const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
141 int getVertexAttribCount() const { return fVertexAttribs.count(); }
142
143 size_t getVertexSize() const;
144
145 /**
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000146 * Sets default vertex attributes for next draw.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000147 *
148 * This will also set default vertex attribute indices and bindings
149 */
150 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000151
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000152 bool validateVertexAttribs() const;
153
jvanverth@google.comcc782382013-01-28 20:39:48 +0000154 ////////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000155 // Helpers for picking apart vertex attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000156
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000157 // helper array to let us check the expected so we know what bound attrib indices
158 // we care about
159 static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
jvanverth@google.comcc782382013-01-28 20:39:48 +0000160
161 /**
162 * Accessing positions, texture coords, or colors, of a vertex within an
163 * array is a hassle involving casts and simple math. These helpers exist
164 * to keep GrDrawTarget clients' code a bit nicer looking.
165 */
166
167 /**
168 * Gets a pointer to a GrPoint of a vertex's position or texture
169 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000170 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000171 * @param vertexIndex the index of the vertex in the array
172 * @param vertexSize the size of each vertex in the array
173 * @param offset the offset in bytes of the vertex component.
174 * Defaults to zero (corresponding to vertex position)
175 * @return pointer to the vertex component as a GrPoint
176 */
177 static GrPoint* GetVertexPoint(void* vertices,
178 int vertexIndex,
179 int vertexSize,
180 int offset = 0) {
181 intptr_t start = GrTCast<intptr_t>(vertices);
182 return GrTCast<GrPoint*>(start + offset +
183 vertexIndex * vertexSize);
184 }
185 static const GrPoint* GetVertexPoint(const void* vertices,
186 int vertexIndex,
187 int vertexSize,
188 int offset = 0) {
189 intptr_t start = GrTCast<intptr_t>(vertices);
190 return GrTCast<const GrPoint*>(start + offset +
191 vertexIndex * vertexSize);
192 }
193
194 /**
195 * Gets a pointer to a GrColor inside a vertex within a vertex array.
196 * @param vertices the vetex array
197 * @param vertexIndex the index of the vertex in the array
198 * @param vertexSize the size of each vertex in the array
199 * @param offset the offset in bytes of the vertex color
200 * @return pointer to the vertex component as a GrColor
201 */
202 static GrColor* GetVertexColor(void* vertices,
203 int vertexIndex,
204 int vertexSize,
205 int offset) {
206 intptr_t start = GrTCast<intptr_t>(vertices);
207 return GrTCast<GrColor*>(start + offset +
208 vertexIndex * vertexSize);
209 }
210 static const GrColor* GetVertexColor(const void* vertices,
211 int vertexIndex,
212 int vertexSize,
213 int offset) {
214 const intptr_t start = GrTCast<intptr_t>(vertices);
215 return GrTCast<const GrColor*>(start + offset +
216 vertexIndex * vertexSize);
217 }
218
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000219 /// @}
220
221 ///////////////////////////////////////////////////////////////////////////
222 /// @name Attribute Bindings
223 ////
224
225 /**
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000226 * The vertex data used by the current program is represented as a bitfield
227 * of flags. Programs always use positions and may also use texture
bsalomon@google.comc7818882013-03-20 19:19:53 +0000228 * coordinates, per-vertex colors, per-vertex coverage and edge data. The
229 * local coords accessible by effects may either come from positions or
230 * be specified explicitly.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000231 */
232
233 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000234 * Additional Bits that can be specified in GrAttribBindings.
235 */
236 enum AttribBindingsBits {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000237 /** explicit local coords are provided (instead of using pre-view-matrix positions) */
238 kLocalCoords_AttribBindingsBit = 0x1,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000239 /* program uses colors (GrColor) */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000240 kColor_AttribBindingsBit = 0x2,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000241 /* program uses coverage (GrColor)
242 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000243 kCoverage_AttribBindingsBit = 0x4,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000244 // for below assert
245 kDummyAttribBindingsBit,
246 kHighAttribBindingsBit = kDummyAttribBindingsBit - 1
247 };
248 // make sure we haven't exceeded the number of bits in GrAttribBindings.
249 GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings)));
250
251 enum AttribBindings {
252 kDefault_AttribBindings = 0
253 };
254
255 /**
256 * Sets attribute bindings for next draw.
257 *
258 * @param bindings the attribute bindings to set.
259 */
260 void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; }
261
262 GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; }
263
264 ////////////////////////////////////////////////////////////////////////////
265 // Helpers for picking apart attribute bindings
266
267 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000268 * Determines whether src alpha is guaranteed to be one for all src pixels
269 */
270 bool srcAlphaWillBeOne(GrAttribBindings) const;
271
272 /**
273 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
274 */
275 bool hasSolidCoverage(GrAttribBindings) const;
276
277 static void VertexAttributesUnitTest();
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000278
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000279 /// @}
280
281 ///////////////////////////////////////////////////////////////////////////
282 /// @name Vertex Attribute Indices
283 ////
284
285 /**
286 * Vertex attribute indices map the data set in the vertex attribute array
287 * to the bindings specified in the attribute bindings. Each binding type
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000288 * has an associated index in the attribute array. This index is used to
289 * look up the vertex attribute data from the array, and potentially as the
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000290 * attribute index if we're binding attributes in GL.
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000291 *
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000292 * Indices which do not have active attribute bindings will be ignored.
293 */
294
295 enum AttribIndex {
296 kPosition_AttribIndex = 0,
297 kColor_AttribIndex,
298 kCoverage_AttribIndex,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000299 kLocalCoords_AttribIndex,
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000300
bsalomon@google.comc7818882013-03-20 19:19:53 +0000301 kLast_AttribIndex = kLocalCoords_AttribIndex
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000302 };
303 static const int kAttribIndexCount = kLast_AttribIndex + 1;
304
305 // these are used when vertex color and coverage isn't set
306 enum {
307 kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt,
308 kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1,
309 };
310
311 ////////////////////////////////////////////////////////////////////////////
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000312 // Helpers to set attribute indices. These should match the index in the
313 // current attribute index array.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000314
315 /**
skia.committer@gmail.comf140f182013-03-02 07:01:56 +0000316 * Sets index for next draw. This is used to look up the offset
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000317 * from the current vertex attribute array and to bind the attributes.
318 *
319 * @param index the attribute index we're setting
320 * @param value the value of the index
321 */
322 void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; }
323
324 int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000325
326 /// @}
327
328 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000329 /// @name Color
330 ////
331
332 /**
333 * Sets color for next draw to a premultiplied-alpha color.
334 *
335 * @param color the color to set.
336 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000337 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000338
bsalomon@google.comca432082013-01-23 19:53:46 +0000339 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000340
341 /**
342 * Sets the color to be used for the next draw to be
343 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
344 *
345 * @param alpha The alpha value to set as the color.
346 */
347 void setAlpha(uint8_t a) {
348 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
349 }
350
351 /**
352 * Add a color filter that can be represented by a color and a mode. Applied
bsalomon@google.comc7818882013-03-20 19:19:53 +0000353 * after color-computing effect stages.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000354 */
355 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000356 fCommon.fColorFilterColor = c;
357 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000358 }
359
bsalomon@google.comca432082013-01-23 19:53:46 +0000360 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
361 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000362
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000363 /**
364 * Constructor sets the color to be 'color' which is undone by the destructor.
365 */
366 class AutoColorRestore : public ::GrNoncopyable {
367 public:
sugoi@google.com66a58ac2013-03-05 20:40:52 +0000368 AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000369
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000370 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000371 fDrawState = NULL;
372 this->set(drawState, color);
373 }
374
375 void reset() {
376 if (NULL != fDrawState) {
377 fDrawState->setColor(fOldColor);
378 fDrawState = NULL;
379 }
380 }
381
382 void set(GrDrawState* drawState, GrColor color) {
383 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000384 fDrawState = drawState;
385 fOldColor = fDrawState->getColor();
386 fDrawState->setColor(color);
387 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000388
389 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000390 private:
391 GrDrawState* fDrawState;
392 GrColor fOldColor;
393 };
394
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000395 /// @}
396
397 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000398 /// @name Coverage
399 ////
400
401 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000402 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000403 * initial value (after construction or reset()) is 0xff. The constant
404 * coverage is ignored when per-vertex coverage is provided.
405 */
406 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000407 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000408 }
409
410 /**
411 * Version of above that specifies 4 channel per-vertex color. The value
412 * should be premultiplied.
413 */
414 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000415 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000416 }
417
418 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000419 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000420 }
421
422 /// @}
423
424 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000425 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000426 ////
427
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000428 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
429 fStages[stageIdx].setEffect(effect);
430 return effect;
431 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000432
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000433 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000434 int attr0, int attr1 = -1) {
435 fStages[stageIdx].setEffect(effect, attr0, attr1);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000436 return effect;
437 }
438
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000439 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000440 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000441 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000442 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000443 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000444 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000445 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000446 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000447 void createTextureEffect(int stageIdx,
448 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000449 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000450 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000451 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000452 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000453 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000454 }
455
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000456 bool stagesDisabled() {
457 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000458 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000459 return false;
460 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000461 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000462 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000463 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000464
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000465 void disableStage(int stageIdx) {
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000466 this->setEffect(stageIdx, NULL);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000467 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000468
robertphillips@google.com972265d2012-06-13 18:49:30 +0000469 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000470 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000471 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000472 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000473 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000474 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000475 }
476 }
477
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000478 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000479 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000480 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
481 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000482 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000483 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000484 }
485 }
486 private:
487 GrDrawState* fDrawState;
488 };
489
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000490 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000491 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000492 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000493 const GrEffectStage& getStage(int stageIdx) const {
494 GrAssert((unsigned)stageIdx < kNumStages);
495 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000496 }
497
498 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000499 * Called when the source coord system is changing. This ensures that effects will see the
500 * correct local coordinates. oldToNew gives the transformation from the old coord system in
501 * which the geometry was specified to the new coordinate system from which it will be rendered.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000502 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000503 void localCoordChange(const SkMatrix& oldToNew) {
reed@google.com67e7cde2013-03-20 17:47:16 +0000504 for (int i = 0; i < kNumStages; ++i) {
505 if (this->isStageEnabled(i)) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000506 fStages[i].localCoordChange(oldToNew);
reed@google.com67e7cde2013-03-20 17:47:16 +0000507 }
508 }
reed@google.com67e7cde2013-03-20 17:47:16 +0000509 }
510
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000511 /// @}
512
513 ///////////////////////////////////////////////////////////////////////////
514 /// @name Coverage / Color Stages
515 ////
516
517 /**
518 * A common pattern is to compute a color with the initial stages and then
519 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000520 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
521 * computed based on the pre-coverage-modulated color. The division of
522 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000523 * this method. Initially this is kNumStages (all stages
524 * are color-computing).
525 */
526 void setFirstCoverageStage(int firstCoverageStage) {
527 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000528 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 }
530
531 /**
532 * Gets the index of the first coverage-computing stage.
533 */
534 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000535 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000536 }
537
538 ///@}
539
540 ///////////////////////////////////////////////////////////////////////////
541 /// @name Blending
542 ////
543
544 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000545 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000546 *
547 * The blend function will be:
548 * D' = sat(S*srcCoef + D*dstCoef)
549 *
550 * where D is the existing destination color, S is the incoming source
551 * color, and D' is the new destination color that will be written. sat()
552 * is the saturation function.
553 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000554 * @param srcCoef coefficient applied to the src color.
555 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000556 */
557 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000558 fCommon.fSrcBlend = srcCoeff;
559 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000560 #if GR_DEBUG
561 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000562 case kDC_GrBlendCoeff:
563 case kIDC_GrBlendCoeff:
564 case kDA_GrBlendCoeff:
565 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000566 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
567 "coverage stages.\n");
568 break;
569 default:
570 break;
571 }
572 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000573 case kSC_GrBlendCoeff:
574 case kISC_GrBlendCoeff:
575 case kSA_GrBlendCoeff:
576 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000577 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
578 "coverage stages.\n");
579 break;
580 default:
581 break;
582 }
583 #endif
584 }
585
bsalomon@google.comca432082013-01-23 19:53:46 +0000586 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
587 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000588
589 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
590 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000591 *srcBlendCoeff = fCommon.fSrcBlend;
592 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000593 }
594
595 /**
596 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000597 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000598 * kConstC_GrBlendCoeff
599 * kIConstC_GrBlendCoeff
600 * kConstA_GrBlendCoeff
601 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000602 *
603 * @param constant the constant to set
604 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000605 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000606
607 /**
608 * Retrieves the last value set by setBlendConstant()
609 * @return the blending constant value
610 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000611 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612
bsalomon@google.com2b446732013-02-12 16:47:41 +0000613 /**
614 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
615 * coverage before the blend will give the correct final destination color. In general it
616 * will not as coverage is applied after blending.
617 */
618 bool canTweakAlphaForCoverage() const;
619
620 /**
621 * Optimizations for blending / coverage to that can be applied based on the current state.
622 */
623 enum BlendOptFlags {
624 /**
625 * No optimization
626 */
627 kNone_BlendOpt = 0,
628 /**
629 * Don't draw at all
630 */
631 kSkipDraw_BlendOptFlag = 0x1,
632 /**
633 * Emit the src color, disable HW blending (replace dst with src)
634 */
635 kDisableBlend_BlendOptFlag = 0x2,
636 /**
637 * The coverage value does not have to be computed separately from alpha, the the output
638 * color can be the modulation of the two.
639 */
640 kCoverageAsAlpha_BlendOptFlag = 0x4,
641 /**
642 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
643 * "don't cares".
644 */
645 kEmitCoverage_BlendOptFlag = 0x8,
646 /**
647 * Emit transparent black instead of the src color, no need to compute coverage.
648 */
649 kEmitTransBlack_BlendOptFlag = 0x10,
650 };
651 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
652
653 /**
654 * Determines what optimizations can be applied based on the blend. The coefficients may have
655 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
656 * params that receive the tweaked coefficients. Normally the function looks at the current
657 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
658 * determine the blend optimizations that would be used if there was partial pixel coverage.
659 *
660 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
661 * playback) must call this function and respect the flags that replace the output color.
662 */
663 BlendOptFlags getBlendOpts(bool forceCoverage = false,
664 GrBlendCoeff* srcCoeff = NULL,
665 GrBlendCoeff* dstCoeff = NULL) const;
666
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000667 /// @}
668
669 ///////////////////////////////////////////////////////////////////////////
670 /// @name View Matrix
671 ////
672
673 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000674 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675 *
676 * In the post-view-matrix space the rectangle [0,w]x[0,h]
677 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000678 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000679 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000680 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000681
682 /**
683 * Gets a writable pointer to the view matrix.
684 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000685 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000686
687 /**
688 * Multiplies the current view matrix by a matrix
689 *
690 * After this call V' = V*m where V is the old view matrix,
691 * m is the parameter to this function, and V' is the new view matrix.
692 * (We consider positions to be column vectors so position vector p is
693 * transformed by matrix X as p' = X*p.)
694 *
695 * @param m the matrix used to modify the view matrix.
696 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000697 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000698
699 /**
700 * Multiplies the current view matrix by a matrix
701 *
702 * After this call V' = m*V where V is the old view matrix,
703 * m is the parameter to this function, and V' is the new view matrix.
704 * (We consider positions to be column vectors so position vector p is
705 * transformed by matrix X as p' = X*p.)
706 *
707 * @param m the matrix used to modify the view matrix.
708 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000709 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000710
711 /**
712 * Retrieves the current view matrix
713 * @return the current view matrix.
714 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000715 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000716
717 /**
718 * Retrieves the inverse of the current view matrix.
719 *
720 * If the current view matrix is invertible, return true, and if matrix
721 * is non-null, copy the inverse into it. If the current view matrix is
722 * non-invertible, return false and ignore the matrix parameter.
723 *
724 * @param matrix if not null, will receive a copy of the current inverse.
725 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000726 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000727 // TODO: determine whether we really need to leave matrix unmodified
728 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000729 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000730 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000731 if (matrix) {
732 *matrix = inverse;
733 }
734 return true;
735 }
736 return false;
737 }
738
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000739 ////////////////////////////////////////////////////////////////////////////
740
741 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000742 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000743 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000744 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000745 class AutoViewMatrixRestore : public ::GrNoncopyable {
746 public:
747 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000748
bsalomon@google.comc7818882013-03-20 19:19:53 +0000749 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000750 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000751 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000752 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000753
754 ~AutoViewMatrixRestore() { this->restore(); }
755
bsalomon@google.coma8347462012-10-08 18:59:39 +0000756 /**
757 * Can be called prior to destructor to restore the original matrix.
758 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000759 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000760
bsalomon@google.comc7818882013-03-20 19:19:53 +0000761 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000762
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000763 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000764
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000766 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000767 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000768 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000769 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000770 };
771
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000772 ////////////////////////////////////////////////////////////////////////////
773
774 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000775 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
776 * destructor undoes the changes, restoring the view matrix that was set before the
777 * constructor. It is similar to passing the inverse of the current view matrix to
778 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000779 */
780 class AutoDeviceCoordDraw : ::GrNoncopyable {
781 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000782 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000783 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000784 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
785 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
786 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000787 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000788 AutoDeviceCoordDraw(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000789 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000790 this->set(drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000791 }
792
bsalomon@google.coma8347462012-10-08 18:59:39 +0000793 ~AutoDeviceCoordDraw() { this->restore(); }
794
bsalomon@google.comc7818882013-03-20 19:19:53 +0000795 bool set(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000796
bsalomon@google.coma8347462012-10-08 18:59:39 +0000797 /**
798 * Returns true if this object was successfully initialized on to a GrDrawState. It may
799 * return false because a non-default constructor or set() were never called or because
800 * the view matrix was not invertible.
801 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000802 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000803
bsalomon@google.coma8347462012-10-08 18:59:39 +0000804 /**
805 * Returns the matrix that was set previously set on the drawState. This is only valid
806 * if succeeded returns true.
807 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000808 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000809 GrAssert(this->succeeded());
810 return fViewMatrix;
811 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000812
bsalomon@google.coma8347462012-10-08 18:59:39 +0000813 /**
814 * Can be called prior to destructor to restore the original matrix.
815 */
816 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000817
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000818 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000819 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000820 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000821 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000822 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000823 };
824
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000825 /// @}
826
827 ///////////////////////////////////////////////////////////////////////////
828 /// @name Render Target
829 ////
830
831 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000832 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000833 *
834 * @param target The render target to set.
835 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000836 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000837 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000838 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000839
840 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000841 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000842 *
843 * @return The currently set render target.
844 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000845 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
846 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000847
848 class AutoRenderTargetRestore : public ::GrNoncopyable {
849 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000850 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000851 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
852 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000853 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000854 this->set(ds, newTarget);
855 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000856 ~AutoRenderTargetRestore() { this->restore(); }
857
858 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000859 if (NULL != fDrawState) {
860 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000861 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000862 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000863 GrSafeSetNull(fSavedTarget);
864 }
865
866 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
867 this->restore();
868
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000869 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000870 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000871 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000872 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000873 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000874 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000875 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000876 }
877 private:
878 GrDrawState* fDrawState;
879 GrRenderTarget* fSavedTarget;
880 };
881
882 /// @}
883
884 ///////////////////////////////////////////////////////////////////////////
885 /// @name Stencil
886 ////
887
888 /**
889 * Sets the stencil settings to use for the next draw.
890 * Changing the clip has the side-effect of possibly zeroing
891 * out the client settable stencil bits. So multipass algorithms
892 * using stencil should not change the clip between passes.
893 * @param settings the stencil settings to use.
894 */
895 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000896 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000897 }
898
899 /**
900 * Shortcut to disable stencil testing and ops.
901 */
902 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000903 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 }
905
bsalomon@google.comca432082013-01-23 19:53:46 +0000906 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000907
bsalomon@google.comca432082013-01-23 19:53:46 +0000908 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000909
910 /// @}
911
912 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000913 /// @name State Flags
914 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000915
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916 /**
917 * Flags that affect rendering. Controlled using enable/disableState(). All
918 * default to disabled.
919 */
920 enum StateBits {
921 /**
922 * Perform dithering. TODO: Re-evaluate whether we need this bit
923 */
924 kDither_StateBit = 0x01,
925 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000926 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
927 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
928 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000929 */
930 kHWAntialias_StateBit = 0x02,
931 /**
932 * Draws will respect the clip, otherwise the clip is ignored.
933 */
934 kClip_StateBit = 0x04,
935 /**
936 * Disables writing to the color buffer. Useful when performing stencil
937 * operations.
938 */
939 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000940
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000941 /**
942 * Usually coverage is applied after color blending. The color is blended using the coeffs
943 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
944 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
945 * this case there is no distinction between coverage and color and the caller needs direct
946 * control over the blend coeffs. When set, there will be a single blend step controlled by
947 * setBlendFunc() which will use coverage*color as the src color.
948 */
949 kCoverageDrawing_StateBit = 0x10,
950
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000951 // Users of the class may add additional bits to the vector
952 kDummyStateBit,
953 kLastPublicStateBit = kDummyStateBit-1,
954 };
955
956 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000957 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000958 }
959
960 /**
961 * Enable render state settings.
962 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000963 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000964 */
965 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000966 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000967 }
968
969 /**
970 * Disable render state settings.
971 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000972 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000973 */
974 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000975 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000976 }
977
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000978 /**
979 * Enable or disable stateBits based on a boolean.
980 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000981 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000982 * @param enable if true enable stateBits, otherwise disable
983 */
984 void setState(uint32_t stateBits, bool enable) {
985 if (enable) {
986 this->enableState(stateBits);
987 } else {
988 this->disableState(stateBits);
989 }
990 }
991
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000992 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000993 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000994 }
995
996 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000997 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000998 }
999
1000 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001001 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001002 }
1003
1004 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001005 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001006 }
1007
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001008 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001009 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001010 }
1011
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001012 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001013 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001014 }
1015
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001016 /// @}
1017
1018 ///////////////////////////////////////////////////////////////////////////
1019 /// @name Face Culling
1020 ////
1021
1022 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001023 kInvalid_DrawFace = -1,
1024
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001025 kBoth_DrawFace,
1026 kCCW_DrawFace,
1027 kCW_DrawFace,
1028 };
1029
1030 /**
1031 * Controls whether clockwise, counterclockwise, or both faces are drawn.
1032 * @param face the face(s) to draw.
1033 */
1034 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001035 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +00001036 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001037 }
1038
1039 /**
1040 * Gets whether the target is drawing clockwise, counterclockwise,
1041 * or both faces.
1042 * @return the current draw face(s).
1043 */
bsalomon@google.comca432082013-01-23 19:53:46 +00001044 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +00001045
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001046 /// @}
1047
1048 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001049
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001050 bool isStageEnabled(int s) const {
1051 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001052 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001053 }
1054
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001055 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001056 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001057 return false;
1058 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +00001059 if (fVertexAttribs != s.fVertexAttribs) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001060 return false;
1061 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001062 for (int i = 0; i < kAttribIndexCount; ++i) {
bsalomon@google.comc7818882013-03-20 19:19:53 +00001063 if ((i == kPosition_AttribIndex || s.fCommon.fAttribBindings & (1 << i)) &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001064 fAttribIndices[i] != s.fAttribIndices[i]) {
1065 return false;
1066 }
1067 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001068 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001069 bool enabled = this->isStageEnabled(i);
1070 if (enabled != s.isStageEnabled(i)) {
1071 return false;
1072 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001073 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001074 return false;
1075 }
1076 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001077 return true;
1078 }
1079 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1080
bsalomon@google.comca432082013-01-23 19:53:46 +00001081 GrDrawState& operator= (const GrDrawState& s) {
1082 this->setRenderTarget(s.fRenderTarget.get());
1083 fCommon = s.fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001084 fVertexAttribs = s.fVertexAttribs;
1085 for (int i = 0; i < kAttribIndexCount; i++) {
1086 fAttribIndices[i] = s.fAttribIndices[i];
1087 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001088 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001089 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001090 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001091 }
1092 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001093 return *this;
1094 }
1095
1096private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001097
bsalomon@google.comca432082013-01-23 19:53:46 +00001098 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1099 struct CommonState {
1100 // These fields are roughly sorted by decreasing likelihood of being different in op==
1101 GrColor fColor;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001102 GrAttribBindings fAttribBindings;
bsalomon@google.comca432082013-01-23 19:53:46 +00001103 SkMatrix fViewMatrix;
1104 GrBlendCoeff fSrcBlend;
1105 GrBlendCoeff fDstBlend;
1106 GrColor fBlendConstant;
1107 uint32_t fFlagBits;
bsalomon@google.comca432082013-01-23 19:53:46 +00001108 GrStencilSettings fStencilSettings;
1109 int fFirstCoverageStage;
1110 GrColor fCoverage;
1111 SkXfermode::Mode fColorFilterMode;
1112 GrColor fColorFilterColor;
1113 DrawFace fDrawFace;
1114 bool operator== (const CommonState& other) const {
1115 return fColor == other.fColor &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001116 fAttribBindings == other.fAttribBindings &&
bsalomon@google.comca432082013-01-23 19:53:46 +00001117 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1118 fSrcBlend == other.fSrcBlend &&
1119 fDstBlend == other.fDstBlend &&
1120 fBlendConstant == other.fBlendConstant &&
1121 fFlagBits == other.fFlagBits &&
bsalomon@google.comca432082013-01-23 19:53:46 +00001122 fStencilSettings == other.fStencilSettings &&
1123 fFirstCoverageStage == other.fFirstCoverageStage &&
1124 fCoverage == other.fCoverage &&
1125 fColorFilterMode == other.fColorFilterMode &&
1126 fColorFilterColor == other.fColorFilterColor &&
1127 fDrawFace == other.fDrawFace;
1128 }
1129 bool operator!= (const CommonState& other) const { return !(*this == other); }
1130 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001131
bsalomon@google.comca432082013-01-23 19:53:46 +00001132 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1133 DeferredState must directly reference GrEffects, however. */
1134 struct SavedEffectStage {
1135 SavedEffectStage() : fEffect(NULL) {}
1136 const GrEffect* fEffect;
1137 GrEffectStage::SavedCoordChange fCoordChange;
1138 };
1139
1140public:
1141 /**
1142 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1143 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1144 * dispose mechanism returns them to the cache. This allows recycling resources through the
1145 * the cache while they are in a deferred draw queue.
1146 */
1147 class DeferredState {
1148 public:
1149 DeferredState() : fRenderTarget(NULL) {
1150 GR_DEBUGCODE(fInitialized = false;)
1151 }
1152 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1153 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1154
1155 void saveFrom(const GrDrawState& drawState) {
1156 fCommon = drawState.fCommon;
1157 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1158 fRenderTarget = drawState.fRenderTarget.get();
1159 SkSafeRef(fRenderTarget);
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001160 fVertexAttribs = drawState.fVertexAttribs;
1161 for (int i = 0; i < kAttribIndexCount; i++) {
1162 fAttribIndices[i] = drawState.fAttribIndices[i];
1163 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001164 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1165 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1166 // and recycle them to the cache (if no one else is holding a ref to the resources).
1167 for (int i = 0; i < kNumStages; ++i) {
1168 fStages[i].saveFrom(drawState.fStages[i]);
1169 }
1170 GR_DEBUGCODE(fInitialized = true;)
1171 }
1172
1173 void restoreTo(GrDrawState* drawState) {
1174 GrAssert(fInitialized);
1175 drawState->fCommon = fCommon;
1176 drawState->setRenderTarget(fRenderTarget);
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001177 drawState->fVertexAttribs = fVertexAttribs;
1178 for (int i = 0; i < kAttribIndexCount; i++) {
1179 drawState->fAttribIndices[i] = fAttribIndices[i];
1180 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001181 for (int i = 0; i < kNumStages; ++i) {
1182 fStages[i].restoreTo(&drawState->fStages[i]);
1183 }
1184 }
1185
1186 bool isEqual(const GrDrawState& state) const {
1187 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1188 return false;
1189 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001190 for (int i = 0; i < kAttribIndexCount; ++i) {
skia.committer@gmail.comf140f182013-03-02 07:01:56 +00001191 if ((i == kPosition_AttribIndex ||
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001192 state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
1193 fAttribIndices[i] != state.fAttribIndices[i]) {
1194 return false;
1195 }
1196 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +00001197 if (fVertexAttribs != state.fVertexAttribs) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001198 return false;
1199 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001200 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001201 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001202 return false;
1203 }
1204 }
1205 return true;
1206 }
1207
1208 private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001209 GrRenderTarget* fRenderTarget;
1210 CommonState fCommon;
1211 int fAttribIndices[kAttribIndexCount];
1212 GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
1213 GrEffectStage::DeferredStage fStages[kNumStages];
bsalomon@google.comca432082013-01-23 19:53:46 +00001214
1215 GR_DEBUGCODE(bool fInitialized;)
1216 };
1217
1218private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001219 // helper array to let us check the current bindings so we know what bound attrib indices
1220 // we care about
1221 static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
1222
1223 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1224 CommonState fCommon;
1225 int fAttribIndices[kAttribIndexCount];
1226 GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
1227 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001228
reed@google.comfa35e3d2012-06-26 20:16:17 +00001229 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001230};
1231
bsalomon@google.com2b446732013-02-12 16:47:41 +00001232GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1233
tomhudson@google.com93813632011-10-27 20:21:16 +00001234#endif