blob: 4b1016001a130d9b38c8e28f70aeab1c27d23706 [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
egdaniel89af44a2014-09-26 06:15:04 -070011
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +000012#include "GrBlend.h"
egdanielc0648242014-09-22 13:17:02 -070013#include "GrDrawTargetCaps.h"
bsalomon6251d172014-10-15 10:50:36 -070014#include "GrGeometryProcessor.h"
bsalomonf96ba022014-09-17 08:05:40 -070015#include "GrGpuResourceRef.h"
bsalomonae59b772014-11-19 08:23:49 -080016#include "GrFragmentStage.h"
egdanielb6cbc382014-11-13 11:00:34 -080017#include "GrProcOptInfo.h"
egdaniel89af44a2014-09-26 06:15:04 -070018#include "GrRenderTarget.h"
19#include "GrStencil.h"
20#include "SkMatrix.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000021#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000022
egdaniel89af44a2014-09-26 06:15:04 -070023class GrDrawTargetCaps;
egdaniel170f90b2014-09-16 12:54:40 -070024class GrOptDrawState;
egdaniel89af44a2014-09-26 06:15:04 -070025class GrPaint;
26class GrTexture;
egdaniel170f90b2014-09-16 12:54:40 -070027
joshualitt9853cce2014-11-17 14:22:48 -080028class GrDrawState {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000029public:
egdaniel69bb90c2014-11-11 07:32:45 -080030 GrDrawState() {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000031 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000032 this->reset();
33 }
tomhudson@google.com93813632011-10-27 20:21:16 +000034
egdaniel69bb90c2014-11-11 07:32:45 -080035 GrDrawState(const SkMatrix& initialViewMatrix) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000036 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000037 this->reset(initialViewMatrix);
38 }
bsalomon@google.com137f1342013-05-29 21:27:53 +000039
40 /**
41 * Copies another draw state.
42 **/
joshualitt9853cce2014-11-17 14:22:48 -080043 GrDrawState(const GrDrawState& state) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000044 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000045 *this = state;
46 }
47
bsalomon@google.com137f1342013-05-29 21:27:53 +000048 /**
49 * Copies another draw state with a preconcat to the view matrix.
50 **/
bsalomon8f727332014-08-05 07:50:06 -070051 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix);
robertphillips@google.com9ec07532012-06-22 12:01:30 +000052
egdaniel170f90b2014-09-16 12:54:40 -070053 virtual ~GrDrawState();
bsalomon@google.com137f1342013-05-29 21:27:53 +000054
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000055 /**
joshualittb0a8a372014-09-23 09:50:21 -070056 * Resets to the default state. GrProcessors will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000057 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000058 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000059
bsalomon@google.com137f1342013-05-29 21:27:53 +000060 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000061
62 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000063 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
64 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
bsalomon9c0822a2014-08-11 11:07:48 -070065 * equivalents are set to default values with the exception of vertex attribute state which
66 * is unmodified by this function and clipping which will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000067 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000068 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069
70 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +000071 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +000072 ////
73
egdaniel89af44a2014-09-26 06:15:04 -070074 enum {
75 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
76 };
77
78 const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
79 int getVertexAttribCount() const { return fVACount; }
80
81 size_t getVertexStride() const { return fVAStride; }
82
83 bool hasLocalCoordAttribute() const {
84 return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
85 }
86 bool hasColorVertexAttribute() const {
87 return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
88 }
89 bool hasCoverageVertexAttribute() const {
90 return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
91 }
92
93 const int* getFixedFunctionVertexAttribIndices() const {
94 return fFixedFunctionVertexAttribIndices;
95 }
96
97 bool validateVertexAttribs() const;
98
jvanverth@google.com9b855c72013-03-01 18:21:22 +000099 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000100 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
101 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
102 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000103 *
joshualittb0a8a372014-09-23 09:50:21 -0700104 * The mapping of attributes with kEffect bindings to GrProcessor inputs is specified when
jvanverth@google.com054ae992013-04-01 20:06:51 +0000105 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000106 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000107
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000108 /**
robertphillips@google.com42903302013-04-20 12:26:07 +0000109 * Sets vertex attributes for next draw. The object driving the templatization
110 * should be a global GrVertexAttrib array that is never changed.
egdaniel7b3d5ee2014-08-28 05:41:14 -0700111 *
112 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
113 * @param stride the number of bytes between successive vertex data.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000114 */
egdaniel7b3d5ee2014-08-28 05:41:14 -0700115 template <const GrVertexAttrib A[]> void setVertexAttribs(int count, size_t stride) {
116 this->internalSetVertexAttribs(A, count, stride);
robertphillips@google.com42903302013-04-20 12:26:07 +0000117 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000118
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000119 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000120 * Sets default vertex attributes for next draw. The default is a single attribute:
121 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000122 */
123 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000124
jvanverth@google.com054ae992013-04-01 20:06:51 +0000125 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000126 * Helper to save/restore vertex attribs
127 */
128 class AutoVertexAttribRestore {
129 public:
bsalomon8f727332014-08-05 07:50:06 -0700130 AutoVertexAttribRestore(GrDrawState* drawState);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000131
egdaniel3658f382014-09-15 07:01:59 -0700132 ~AutoVertexAttribRestore() { fDrawState->internalSetVertexAttribs(fVAPtr, fVACount,
133 fVAStride); }
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000134
135 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000136 GrDrawState* fDrawState;
137 const GrVertexAttrib* fVAPtr;
138 int fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700139 size_t fVAStride;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000140 };
141
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000142 /// @}
143
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000144 /**
bsalomon62c447d2014-08-08 08:08:50 -0700145 * Depending on features available in the underlying 3D API and the color blend mode requested
146 * it may or may not be possible to correctly blend with fractional pixel coverage generated by
147 * the fragment shader.
148 *
149 * This function considers the current draw state and the draw target's capabilities to
150 * determine whether coverage can be handled correctly. This function assumes that the caller
151 * intends to specify fractional pixel coverage (via setCoverage(), through a coverage vertex
152 * attribute, or a coverage effect) but may not have specified it yet.
153 */
154 bool couldApplyCoverage(const GrDrawTargetCaps& caps) const;
155
egdaniel89af44a2014-09-26 06:15:04 -0700156 /**
157 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
158 */
159 bool hasSolidCoverage() const;
160
egdanielcd8b6302014-11-11 14:46:05 -0800161 /**
162 * This function returns true if the render target destination pixel values will be read for
163 * blending during draw.
164 */
165 bool willBlendWithDst() const;
166
jvanverth@google.comcc782382013-01-28 20:39:48 +0000167 /// @}
168
169 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000170 /// @name Color
171 ////
172
egdaniel89af44a2014-09-26 06:15:04 -0700173 GrColor getColor() const { return fColor; }
174
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000175 /**
176 * Sets color for next draw to a premultiplied-alpha color.
177 *
178 * @param color the color to set.
179 */
egdaniel9514d242014-07-18 06:15:43 -0700180 void setColor(GrColor color) {
egdaniel3658f382014-09-15 07:01:59 -0700181 if (color != fColor) {
182 fColor = color;
egdanielb6cbc382014-11-13 11:00:34 -0800183 fColorProcInfoValid = false;
egdaniel3658f382014-09-15 07:01:59 -0700184 }
egdaniel9514d242014-07-18 06:15:43 -0700185 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000186
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000187 /**
188 * Sets the color to be used for the next draw to be
189 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
190 *
191 * @param alpha The alpha value to set as the color.
192 */
bsalomon62c447d2014-08-08 08:08:50 -0700193 void setAlpha(uint8_t a) { this->setColor((a << 24) | (a << 16) | (a << 8) | a); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000194
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000195 /// @}
196
197 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000198 /// @name Coverage
199 ////
200
egdaniel89af44a2014-09-26 06:15:04 -0700201 uint8_t getCoverage() const { return fCoverage; }
202
203 GrColor getCoverageColor() const {
204 return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
205 }
206
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000207 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000208 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000209 * initial value (after construction or reset()) is 0xff. The constant
210 * coverage is ignored when per-vertex coverage is provided.
211 */
212 void setCoverage(uint8_t coverage) {
egdaniel3658f382014-09-15 07:01:59 -0700213 if (coverage != fCoverage) {
214 fCoverage = coverage;
egdanielb6cbc382014-11-13 11:00:34 -0800215 fCoverageProcInfoValid = false;
egdaniel3658f382014-09-15 07:01:59 -0700216 }
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000217 }
218
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000219 /// @}
220
joshualittbd769d02014-09-04 08:56:46 -0700221 /**
222 * The geometry processor is the sole element of the skia pipeline which can use the vertex,
223 * geometry, and tesselation shaders. The GP may also compute a coverage in its fragment shader
224 * but is never put in the color processing pipeline.
225 */
226
joshualittb0a8a372014-09-23 09:50:21 -0700227 const GrGeometryProcessor* setGeometryProcessor(const GrGeometryProcessor* geometryProcessor) {
228 SkASSERT(geometryProcessor);
joshualittbd769d02014-09-04 08:56:46 -0700229 SkASSERT(!this->hasGeometryProcessor());
joshualitta5305a12014-10-10 17:47:00 -0700230 fGeometryProcessor.reset(SkRef(geometryProcessor));
egdanielb6cbc382014-11-13 11:00:34 -0800231 fCoverageProcInfoValid = false;
joshualittb0a8a372014-09-23 09:50:21 -0700232 return geometryProcessor;
joshualittbd769d02014-09-04 08:56:46 -0700233 }
234
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000235 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000236 /// @name Effect Stages
joshualittb0a8a372014-09-23 09:50:21 -0700237 /// Each stage hosts a GrProcessor. The effect produces an output color or coverage in the
238 /// fragment shader. Its inputs are the output from the previous stage as well as some variables
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000239 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
240 /// the fragment position, local coordinates).
241 ///
242 /// The stages are divided into two sets, color-computing and coverage-computing. The final
243 /// color stage produces the final pixel color. The coverage-computing stages function exactly
244 /// as the color-computing but the output of the final coverage stage is treated as a fractional
245 /// pixel coverage rather than as input to the src/dst color blend step.
246 ///
247 /// The input color to the first color-stage is either the constant color or interpolated
248 /// per-vertex colors. The input to the first coverage stage is either a constant coverage
249 /// (usually full-coverage) or interpolated per-vertex coverage.
250 ///
251 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
252 /// the color / coverage distinction.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000253 ////
254
egdaniel89af44a2014-09-26 06:15:04 -0700255 int numColorStages() const { return fColorStages.count(); }
256 int numCoverageStages() const { return fCoverageStages.count(); }
joshualitt4dd99882014-11-11 08:51:30 -0800257 int numFragmentStages() const { return this->numColorStages() + this->numCoverageStages(); }
egdaniel89af44a2014-09-26 06:15:04 -0700258 int numTotalStages() const {
joshualitt4dd99882014-11-11 08:51:30 -0800259 return this->numFragmentStages() + (this->hasGeometryProcessor() ? 1 : 0);
egdaniel89af44a2014-09-26 06:15:04 -0700260 }
261
262 bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
joshualitta5305a12014-10-10 17:47:00 -0700263 const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
egdaniel89af44a2014-09-26 06:15:04 -0700264 const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
265 const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
266
267 /**
268 * Checks whether any of the effects will read the dst pixel color.
269 */
270 bool willEffectReadDstColor() const;
271
joshualittb0a8a372014-09-23 09:50:21 -0700272 const GrFragmentProcessor* addColorProcessor(const GrFragmentProcessor* effect) {
bsalomon49f085d2014-09-05 13:34:00 -0700273 SkASSERT(effect);
joshualittb0a8a372014-09-23 09:50:21 -0700274 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrFragmentStage, (effect));
egdanielb6cbc382014-11-13 11:00:34 -0800275 fColorProcInfoValid = false;
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000276 return effect;
277 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000278
joshualittb0a8a372014-09-23 09:50:21 -0700279 const GrFragmentProcessor* addCoverageProcessor(const GrFragmentProcessor* effect) {
bsalomon49f085d2014-09-05 13:34:00 -0700280 SkASSERT(effect);
joshualittb0a8a372014-09-23 09:50:21 -0700281 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrFragmentStage, (effect));
egdanielb6cbc382014-11-13 11:00:34 -0800282 fCoverageProcInfoValid = false;
bsalomon@google.comadc65362013-01-28 14:26:09 +0000283 return effect;
284 }
285
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000286 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000287 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000288 */
joshualittb0a8a372014-09-23 09:50:21 -0700289 void addColorTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
290 this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000291 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000292
joshualittb0a8a372014-09-23 09:50:21 -0700293 void addCoverageTextureProcessor(GrTexture* texture, const SkMatrix& matrix) {
294 this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000295 }
296
joshualittb0a8a372014-09-23 09:50:21 -0700297 void addColorTextureProcessor(GrTexture* texture,
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000298 const SkMatrix& matrix,
299 const GrTextureParams& params) {
joshualittb0a8a372014-09-23 09:50:21 -0700300 this->addColorProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
301 }
302
303 void addCoverageTextureProcessor(GrTexture* texture,
304 const SkMatrix& matrix,
305 const GrTextureParams& params) {
306 this->addCoverageProcessor(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000307 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000308
robertphillips@google.com972265d2012-06-13 18:49:30 +0000309 /**
bsalomon9b536522014-09-05 09:18:51 -0700310 * When this object is destroyed it will remove any color/coverage effects from the draw state
311 * that were added after its constructor.
312 *
313 * This class has strange behavior around geometry processor. If there is a GP on the draw state
314 * it will assert that the GP is not modified until after the destructor of the ARE. If the
315 * draw state has a NULL GP when the ARE is constructed then it will reset it to null in the
316 * destructor.
317 *
318 * TODO: We'd prefer for the ARE to just save and restore the GP. However, this would add
319 * significant complexity to the multi-ref architecture for deferred drawing. Once GrDrawState
320 * and GrOptDrawState are fully separated then GrDrawState will never be in the deferred
321 * execution state and GrOptDrawState always will be (and will be immutable and therefore
322 * unable to have an ARE). At this point we can restore sanity and have the ARE save and restore
323 * the GP.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000324 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000325 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000326 public:
bsalomon9b536522014-09-05 09:18:51 -0700327 AutoRestoreEffects()
328 : fDrawState(NULL)
bsalomon52e9d632014-09-05 12:23:12 -0700329 , fOriginalGPID(SK_InvalidUniqueID)
bsalomon9b536522014-09-05 09:18:51 -0700330 , fColorEffectCnt(0)
331 , fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000332
bsalomon9b536522014-09-05 09:18:51 -0700333 AutoRestoreEffects(GrDrawState* ds)
334 : fDrawState(NULL)
bsalomon52e9d632014-09-05 12:23:12 -0700335 , fOriginalGPID(SK_InvalidUniqueID)
bsalomon9b536522014-09-05 09:18:51 -0700336 , fColorEffectCnt(0)
337 , fCoverageEffectCnt(0) {
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000338 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000339 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000340
341 ~AutoRestoreEffects() { this->set(NULL); }
342
bsalomon8f727332014-08-05 07:50:06 -0700343 void set(GrDrawState* ds);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000344
bsalomon49f085d2014-09-05 13:34:00 -0700345 bool isSet() const { return SkToBool(fDrawState); }
bsalomon8af05232014-06-03 06:34:58 -0700346
robertphillips@google.com972265d2012-06-13 18:49:30 +0000347 private:
bsalomon9b536522014-09-05 09:18:51 -0700348 GrDrawState* fDrawState;
bsalomon52e9d632014-09-05 12:23:12 -0700349 uint32_t fOriginalGPID;
bsalomon9b536522014-09-05 09:18:51 -0700350 int fColorEffectCnt;
351 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000352 };
353
joshualitta58fe352014-10-27 08:39:00 -0700354 /**
355 * AutoRestoreStencil
356 *
357 * This simple struct saves and restores the stencil settings
358 */
359 class AutoRestoreStencil : public ::SkNoncopyable {
360 public:
361 AutoRestoreStencil() : fDrawState(NULL) {}
362
363 AutoRestoreStencil(GrDrawState* ds) : fDrawState(NULL) { this->set(ds); }
364
365 ~AutoRestoreStencil() { this->set(NULL); }
366
367 void set(GrDrawState* ds) {
368 if (fDrawState) {
369 fDrawState->setStencil(fStencilSettings);
370 }
371 fDrawState = ds;
372 if (ds) {
373 fStencilSettings = ds->getStencil();
374 }
375 }
376
377 bool isSet() const { return SkToBool(fDrawState); }
378
379 private:
380 GrDrawState* fDrawState;
381 GrStencilSettings fStencilSettings;
382 };
383
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000384 /// @}
385
386 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000387 /// @name Blending
388 ////
389
egdaniel89af44a2014-09-26 06:15:04 -0700390 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
391 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
392
393 /**
394 * Retrieves the last value set by setBlendConstant()
395 * @return the blending constant value
396 */
397 GrColor getBlendConstant() const { return fBlendConstant; }
398
399 /**
400 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
401 * coverage before the blend will give the correct final destination color. In general it
402 * will not as coverage is applied after blending.
403 */
404 bool canTweakAlphaForCoverage() const;
405
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000406 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000407 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000408 *
409 * The blend function will be:
410 * D' = sat(S*srcCoef + D*dstCoef)
411 *
412 * where D is the existing destination color, S is the incoming source
413 * color, and D' is the new destination color that will be written. sat()
414 * is the saturation function.
415 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000416 * @param srcCoef coefficient applied to the src color.
417 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000418 */
419 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
egdaniel3658f382014-09-15 07:01:59 -0700420 if (srcCoeff != fSrcBlend || dstCoeff != fDstBlend) {
421 fSrcBlend = srcCoeff;
422 fDstBlend = dstCoeff;
egdaniel3658f382014-09-15 07:01:59 -0700423 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000424 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000425 if (GrBlendCoeffRefsDst(dstCoeff)) {
tfarina38406c82014-10-31 07:11:12 -0700426 SkDebugf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000427 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000428 if (GrBlendCoeffRefsSrc(srcCoeff)) {
tfarina38406c82014-10-31 07:11:12 -0700429 SkDebugf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000430 }
431 #endif
432 }
433
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000434 /**
435 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000436 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000437 * kConstC_GrBlendCoeff
438 * kIConstC_GrBlendCoeff
439 * kConstA_GrBlendCoeff
440 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000441 *
442 * @param constant the constant to set
443 */
egdaniel9514d242014-07-18 06:15:43 -0700444 void setBlendConstant(GrColor constant) {
egdaniel3658f382014-09-15 07:01:59 -0700445 if (constant != fBlendConstant) {
446 fBlendConstant = constant;
egdaniel3658f382014-09-15 07:01:59 -0700447 }
egdaniel9514d242014-07-18 06:15:43 -0700448 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000449
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000450 /// @}
451
452 ///////////////////////////////////////////////////////////////////////////
453 /// @name View Matrix
454 ////
455
456 /**
egdaniel89af44a2014-09-26 06:15:04 -0700457 * Retrieves the current view matrix
458 * @return the current view matrix.
459 */
460 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
461
462 /**
463 * Retrieves the inverse of the current view matrix.
464 *
465 * If the current view matrix is invertible, return true, and if matrix
466 * is non-null, copy the inverse into it. If the current view matrix is
467 * non-invertible, return false and ignore the matrix parameter.
468 *
469 * @param matrix if not null, will receive a copy of the current inverse.
470 */
471 bool getViewInverse(SkMatrix* matrix) const {
472 SkMatrix inverse;
473 if (fViewMatrix.invert(&inverse)) {
474 if (matrix) {
475 *matrix = inverse;
476 }
477 return true;
478 }
479 return false;
480 }
481
482 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000483 * Sets the view matrix to identity and updates any installed effects to compensate for the
484 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000485 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000486 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000488 ////////////////////////////////////////////////////////////////////////////
489
490 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000492 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000493 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000494 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000495 public:
496 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000497
bsalomon@google.comc7818882013-03-20 19:19:53 +0000498 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000499 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000500 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000501 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000502
503 ~AutoViewMatrixRestore() { this->restore(); }
504
bsalomon@google.coma8347462012-10-08 18:59:39 +0000505 /**
506 * Can be called prior to destructor to restore the original matrix.
507 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000508 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000509
bsalomon@google.comc7818882013-03-20 19:19:53 +0000510 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000511
bsalomon@google.com137f1342013-05-29 21:27:53 +0000512 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
513 is not invertible. */
514 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000515
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000516 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000517 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
518
joshualittb0a8a372014-09-23 09:50:21 -0700519 GrDrawState* fDrawState;
520 SkMatrix fViewMatrix;
521 int fNumColorStages;
joshualitta5305a12014-10-10 17:47:00 -0700522 SkAutoSTArray<8, GrFragmentStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000523 };
524
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000525 /// @}
526
527 ///////////////////////////////////////////////////////////////////////////
528 /// @name Render Target
529 ////
530
531 /**
egdaniel89af44a2014-09-26 06:15:04 -0700532 * Retrieves the currently set render-target.
533 *
534 * @return The currently set render target.
535 */
bsalomon37dd3312014-11-03 08:47:23 -0800536 GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
egdaniel89af44a2014-09-26 06:15:04 -0700537
538 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000539 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 *
541 * @param target The render target to set.
542 */
bsalomonae59b772014-11-19 08:23:49 -0800543 void setRenderTarget(GrRenderTarget* target) { fRenderTarget.reset(SkSafeRef(target)); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000545 /// @}
546
547 ///////////////////////////////////////////////////////////////////////////
548 /// @name Stencil
549 ////
550
egdaniel89af44a2014-09-26 06:15:04 -0700551 const GrStencilSettings& getStencil() const { return fStencilSettings; }
552
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000553 /**
554 * Sets the stencil settings to use for the next draw.
555 * Changing the clip has the side-effect of possibly zeroing
556 * out the client settable stencil bits. So multipass algorithms
557 * using stencil should not change the clip between passes.
558 * @param settings the stencil settings to use.
559 */
560 void setStencil(const GrStencilSettings& settings) {
egdaniel3658f382014-09-15 07:01:59 -0700561 if (settings != fStencilSettings) {
562 fStencilSettings = settings;
egdaniel3658f382014-09-15 07:01:59 -0700563 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000564 }
565
566 /**
567 * Shortcut to disable stencil testing and ops.
568 */
569 void disableStencil() {
egdaniel3658f382014-09-15 07:01:59 -0700570 if (!fStencilSettings.isDisabled()) {
571 fStencilSettings.setDisabled();
egdaniel3658f382014-09-15 07:01:59 -0700572 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000573 }
574
bsalomon2ed5ef82014-07-07 08:44:05 -0700575 GrStencilSettings* stencil() { return &fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000576
577 /// @}
578
579 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580 /// @name State Flags
581 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000582
egdaniel89af44a2014-09-26 06:15:04 -0700583 /**
584 * Flags that affect rendering. Controlled using enable/disableState(). All
585 * default to disabled.
586 */
587 enum StateBits {
588 /**
589 * Perform dithering. TODO: Re-evaluate whether we need this bit
590 */
591 kDither_StateBit = 0x01,
592 /**
593 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
594 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
595 * the 3D API.
596 */
597 kHWAntialias_StateBit = 0x02,
598 /**
599 * Draws will respect the clip, otherwise the clip is ignored.
600 */
601 kClip_StateBit = 0x04,
602 /**
603 * Disables writing to the color buffer. Useful when performing stencil
604 * operations.
605 */
606 kNoColorWrites_StateBit = 0x08,
607
608 /**
609 * Usually coverage is applied after color blending. The color is blended using the coeffs
610 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
611 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
612 * this case there is no distinction between coverage and color and the caller needs direct
613 * control over the blend coeffs. When set, there will be a single blend step controlled by
614 * setBlendFunc() which will use coverage*color as the src color.
615 */
616 kCoverageDrawing_StateBit = 0x10,
joshualitt7a6184f2014-10-29 18:29:27 -0700617 kLast_StateBit = kCoverageDrawing_StateBit,
egdaniel89af44a2014-09-26 06:15:04 -0700618 };
619
620 uint32_t getFlagBits() const { return fFlagBits; }
621
622 bool isStateFlagEnabled(uint32_t stateBit) const { return 0 != (stateBit & fFlagBits); }
623
624 bool isClipState() const { return 0 != (fFlagBits & kClip_StateBit); }
625 bool isColorWriteDisabled() const { return 0 != (fFlagBits & kNoColorWrites_StateBit); }
626 bool isCoverageDrawing() const { return 0 != (fFlagBits & kCoverageDrawing_StateBit); }
627
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 void resetStateFlags() {
egdaniel3658f382014-09-15 07:01:59 -0700629 if (0 != fFlagBits) {
630 fFlagBits = 0;
egdaniel3658f382014-09-15 07:01:59 -0700631 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632 }
633
634 /**
635 * Enable render state settings.
636 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000637 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 */
639 void enableState(uint32_t stateBits) {
egdaniel3658f382014-09-15 07:01:59 -0700640 if (stateBits & ~fFlagBits) {
641 fFlagBits |= stateBits;
egdaniel3658f382014-09-15 07:01:59 -0700642 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000643 }
644
645 /**
646 * Disable render state settings.
647 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000648 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000649 */
650 void disableState(uint32_t stateBits) {
egdaniel3658f382014-09-15 07:01:59 -0700651 if (stateBits & fFlagBits) {
652 fFlagBits &= ~(stateBits);
egdaniel3658f382014-09-15 07:01:59 -0700653 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 }
655
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000656 /**
657 * Enable or disable stateBits based on a boolean.
658 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000659 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000660 * @param enable if true enable stateBits, otherwise disable
661 */
662 void setState(uint32_t stateBits, bool enable) {
663 if (enable) {
664 this->enableState(stateBits);
665 } else {
666 this->disableState(stateBits);
667 }
668 }
669
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 /// @}
671
672 ///////////////////////////////////////////////////////////////////////////
673 /// @name Face Culling
674 ////
675
egdaniel89af44a2014-09-26 06:15:04 -0700676 enum DrawFace {
677 kInvalid_DrawFace = -1,
678
679 kBoth_DrawFace,
680 kCCW_DrawFace,
681 kCW_DrawFace,
682 };
683
684 /**
685 * Gets whether the target is drawing clockwise, counterclockwise,
686 * or both faces.
687 * @return the current draw face(s).
688 */
689 DrawFace getDrawFace() const { return fDrawFace; }
690
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000691 /**
692 * Controls whether clockwise, counterclockwise, or both faces are drawn.
693 * @param face the face(s) to draw.
694 */
695 void setDrawFace(DrawFace face) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000696 SkASSERT(kInvalid_DrawFace != face);
bsalomon2ed5ef82014-07-07 08:44:05 -0700697 fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000698 }
699
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700 /// @}
701
702 ///////////////////////////////////////////////////////////////////////////
bsalomon62c447d2014-08-08 08:08:50 -0700703 /// @name Hints
704 /// Hints that when provided can enable optimizations.
705 ////
706
joshualitt65171342014-10-09 07:25:36 -0700707 enum Hints {
708 kVertexColorsAreOpaque_Hint = 0x1,
709 kLast_Hint = kVertexColorsAreOpaque_Hint
710 };
egdaniel89af44a2014-09-26 06:15:04 -0700711
bsalomon62c447d2014-08-08 08:08:50 -0700712 void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
713
egdaniel89af44a2014-09-26 06:15:04 -0700714 bool vertexColorsAreOpaque() const { return kVertexColorsAreOpaque_Hint & fHints; }
715
bsalomon62c447d2014-08-08 08:08:50 -0700716 /// @}
717
718 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000719
bsalomon8f727332014-08-05 07:50:06 -0700720 GrDrawState& operator= (const GrDrawState& that);
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000721
722private:
egdaniel89af44a2014-09-26 06:15:04 -0700723 bool isEqual(const GrDrawState& that) const;
724
725 /**
726 * Optimizations for blending / coverage to that can be applied based on the current state.
727 */
728 enum BlendOptFlags {
729 /**
730 * No optimization
731 */
732 kNone_BlendOpt = 0,
733 /**
734 * Don't draw at all
735 */
736 kSkipDraw_BlendOptFlag = 0x1,
737 /**
738 * The coverage value does not have to be computed separately from alpha, the the output
739 * color can be the modulation of the two.
740 */
741 kCoverageAsAlpha_BlendOptFlag = 0x2,
742 /**
743 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
744 * "don't cares".
745 */
746 kEmitCoverage_BlendOptFlag = 0x4,
747 /**
748 * Emit transparent black instead of the src color, no need to compute coverage.
749 */
750 kEmitTransBlack_BlendOptFlag = 0x8,
751 };
752 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
753
754 /**
755 * Determines what optimizations can be applied based on the blend. The coefficients may have
756 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
757 * params that receive the tweaked coefficients. Normally the function looks at the current
758 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
759 * determine the blend optimizations that would be used if there was partial pixel coverage.
760 *
761 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
762 * playback) must call this function and respect the flags that replace the output color.
763 *
764 * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
765 * simply returned the cached flags and coefficients. Otherwise it will calculate the values.
766 */
767 BlendOptFlags getBlendOpts(bool forceCoverage = false,
768 GrBlendCoeff* srcCoeff = NULL,
769 GrBlendCoeff* dstCoeff = NULL) const;
770
egdaniel912b3d22014-11-17 07:45:53 -0800771 const GrProcOptInfo& colorProcInfo() const {
772 this->calcColorInvariantOutput();
773 return fColorProcInfo;
774 }
775
776 const GrProcOptInfo& coverageProcInfo() const {
777 this->calcCoverageInvariantOutput();
778 return fCoverageProcInfo;
779 }
780
egdaniel89af44a2014-09-26 06:15:04 -0700781 /**
782 * Determines whether src alpha is guaranteed to be one for all src pixels
783 */
784 bool srcAlphaWillBeOne() const;
785
egdanielb6cbc382014-11-13 11:00:34 -0800786 /**
787 * If fColorProcInfoValid is false, function calculates the invariant output for the color
788 * stages and results are stored in fColorProcInfo.
789 */
790 void calcColorInvariantOutput() const;
791
792 /**
793 * If fCoverageProcInfoValid is false, function calculates the invariant output for the coverage
794 * stages and results are stored in fCoverageProcInfo.
795 */
796 void calcCoverageInvariantOutput() const;
797
bsalomon8f727332014-08-05 07:50:06 -0700798 void onReset(const SkMatrix* initialViewMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000799
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000800 // Some of the auto restore objects assume that no effects are removed during their lifetime.
801 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000802 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000803
egdaniel7b3d5ee2014-08-28 05:41:14 -0700804 void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride);
robertphillips@google.com42903302013-04-20 12:26:07 +0000805
joshualitta5305a12014-10-10 17:47:00 -0700806 typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
egdaniel89af44a2014-09-26 06:15:04 -0700807
bsalomonae59b772014-11-19 08:23:49 -0800808 SkAutoTUnref<GrRenderTarget> fRenderTarget;
809 GrColor fColor;
810 SkMatrix fViewMatrix;
811 GrColor fBlendConstant;
812 uint32_t fFlagBits;
813 const GrVertexAttrib* fVAPtr;
814 int fVACount;
815 size_t fVAStride;
816 GrStencilSettings fStencilSettings;
817 uint8_t fCoverage;
818 DrawFace fDrawFace;
819 GrBlendCoeff fSrcBlend;
820 GrBlendCoeff fDstBlend;
821 SkAutoTUnref<const GrGeometryProcessor> fGeometryProcessor;
822 FragmentStageArray fColorStages;
823 FragmentStageArray fCoverageStages;
824 uint32_t fHints;
egdaniel89af44a2014-09-26 06:15:04 -0700825
826 // This is simply a different representation of info in fVertexAttribs and thus does
827 // not need to be compared in op==.
828 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
829
egdanielb6cbc382014-11-13 11:00:34 -0800830 mutable GrProcOptInfo fColorProcInfo;
831 mutable GrProcOptInfo fCoverageProcInfo;
832 mutable bool fColorProcInfoValid;
833 mutable bool fCoverageProcInfoValid;
834
egdanielb109ac22014-10-07 06:45:44 -0700835 friend class GrOptDrawState;
tomhudson@google.com93813632011-10-27 20:21:16 +0000836};
837
egdanielb109ac22014-10-07 06:45:44 -0700838GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
egdaniel89af44a2014-09-26 06:15:04 -0700839
tomhudson@google.com93813632011-10-27 20:21:16 +0000840#endif