blob: 5b1194d0c2672da56904c819b50349fb2906b4fb [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"
bsalomon@google.com73818dc2013-03-28 13:23:29 +000014#include "GrPaint.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000015#include "GrRefCnt.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000016#include "GrRenderTarget.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000017#include "GrStencil.h"
18#include "GrTemplates.h"
19#include "GrTexture.h"
bsalomon@google.com31ec7982013-03-27 18:14:57 +000020#include "GrTypesPriv.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000021#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000022
jvanverth@google.comcc782382013-01-28 20:39:48 +000023#include "SkMatrix.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000024#include "SkXfermode.h"
25
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000026class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000027public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000028 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000029
tomhudson@google.com93813632011-10-27 20:21:16 +000030 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000031 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
32 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
33 * output from the previous enabled stage and a position. The position is either derived from
34 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
jvanverth@google.com9b855c72013-03-01 18:21:22 +000035 * GrAttribBindings used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000036 *
bsalomon@google.com13221342012-10-26 13:41:59 +000037 * The stages are divided into two sets, color-computing and coverage-computing. The final color
38 * stage produces the final pixel color. The coverage-computing stages function exactly as the
39 * color-computing but the output of the final coverage stage is treated as a fractional pixel
40 * coverage rather than as input to the src/dst color blend step.
41 *
42 * The input color to the first enabled color-stage is either the constant color or interpolated
jvanverth@google.com054ae992013-04-01 20:06:51 +000043 * per-vertex colors. The input to the first coverage stage is either a constant coverage
44 * (usually full-coverage) or interpolated per-vertex coverage.
bsalomon@google.com13221342012-10-26 13:41:59 +000045 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000046 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
47 * the color / coverage distinction.
48 *
bsalomon@google.com13221342012-10-26 13:41:59 +000049 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
bsalomon@google.com73818dc2013-03-28 13:23:29 +000050 * GrPaint. Stage GrPaint::kTotalStages is earmarked for use by GrTextContext, GrPathRenderer-
51 * derived classes, and the rect/oval helper classes. GrPaint::kTotalStages+1 is earmarked for
52 * clipping by GrClipMaskManager. TODO: replace fixed size array of stages with variable size
53 * arrays of color and coverage stages.
tomhudson@google.com93813632011-10-27 20:21:16 +000054 */
55 enum {
bsalomon@google.com73818dc2013-03-28 13:23:29 +000056 kNumStages = GrPaint::kTotalStages + 2,
tomhudson@google.com93813632011-10-27 20:21:16 +000057 };
58
bsalomon@google.com137f1342013-05-29 21:27:53 +000059 GrDrawState() { this->reset(); }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000060
bsalomon@google.com137f1342013-05-29 21:27:53 +000061 GrDrawState(const SkMatrix& initialViewMatrix) { this->reset(initialViewMatrix); }
62
63 /**
64 * Copies another draw state.
65 **/
bsalomon@google.comca432082013-01-23 19:53:46 +000066 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000067 *this = state;
68 }
69
bsalomon@google.com137f1342013-05-29 21:27:53 +000070 /**
71 * Copies another draw state with a preconcat to the view matrix.
72 **/
73 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
74 *this = state;
75 if (!preConcatMatrix.isIdentity()) {
76 for (int i = 0; i < kNumStages; ++i) {
77 if (this->isStageEnabled(i)) {
78 fStages[i].localCoordChange(preConcatMatrix);
79 }
80 }
81 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000082 }
83
bsalomon@google.com137f1342013-05-29 21:27:53 +000084 virtual ~GrDrawState() { this->disableStages(); }
85
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000086 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +000087 * Resets to the default state. GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000088 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000089 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000090
bsalomon@google.com137f1342013-05-29 21:27:53 +000091 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000092
93 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000094 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
95 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
96 * equivalents are set to default values. GrPaint has fewer stages than GrDrawState. The extra
bsalomon@google.com21c10c52013-06-13 17:44:07 +000097 * GrDrawState stages are disabled. Clipping will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000098 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000099 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000100
101 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000102 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000103 ////
104
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000105 enum {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000106 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000107 };
108
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000109 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000110 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
111 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
112 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000113 *
jvanverth@google.com054ae992013-04-01 20:06:51 +0000114 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
115 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000116 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000117
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000118 /**
robertphillips@google.com42903302013-04-20 12:26:07 +0000119 * Sets vertex attributes for next draw. The object driving the templatization
120 * should be a global GrVertexAttrib array that is never changed.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000121 */
robertphillips@google.com42903302013-04-20 12:26:07 +0000122 template <const GrVertexAttrib A[]> void setVertexAttribs(int count) {
123 this->setVertexAttribs(A, count);
124 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000125
robertphillips@google.com42903302013-04-20 12:26:07 +0000126 const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVAPtr; }
127 int getVertexAttribCount() const { return fCommon.fVACount; }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000128
129 size_t getVertexSize() const;
130
131 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000132 * Sets default vertex attributes for next draw. The default is a single attribute:
133 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000134 */
135 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000136
jvanverth@google.com054ae992013-04-01 20:06:51 +0000137 /**
138 * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
139 * binding does not appear in the current attribs. These bindings should appear only once in
140 * the attrib array.
141 */
142
143 int positionAttributeIndex() const {
144 return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
145 }
146 int localCoordAttributeIndex() const {
147 return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
148 }
149 int colorVertexAttributeIndex() const {
150 return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
151 }
152 int coverageVertexAttributeIndex() const {
153 return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
154 }
155
156 bool hasLocalCoordAttribute() const {
157 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
158 }
159 bool hasColorVertexAttribute() const {
160 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
161 }
162 bool hasCoverageVertexAttribute() const {
163 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
164 }
165
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000166 bool validateVertexAttribs() const;
167
jvanverth@google.comcc782382013-01-28 20:39:48 +0000168 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000169 * Helper to save/restore vertex attribs
170 */
171 class AutoVertexAttribRestore {
172 public:
173 AutoVertexAttribRestore(GrDrawState* drawState) {
174 GrAssert(NULL != drawState);
175 fDrawState = drawState;
robertphillips@google.com42903302013-04-20 12:26:07 +0000176 fVAPtr = drawState->fCommon.fVAPtr;
177 fVACount = drawState->fCommon.fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000178 fDrawState->setDefaultVertexAttribs();
179 }
180
181 ~AutoVertexAttribRestore(){
robertphillips@google.com42903302013-04-20 12:26:07 +0000182 fDrawState->fCommon.fVAPtr = fVAPtr;
183 fDrawState->fCommon.fVACount = fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000184 }
185
186 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000187 GrDrawState* fDrawState;
188 const GrVertexAttrib* fVAPtr;
189 int fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000190 };
191
192 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000193 * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
194 * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
195 * nicer looking.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000196 */
197
198 /**
199 * Gets a pointer to a GrPoint of a vertex's position or texture
200 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000201 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000202 * @param vertexIndex the index of the vertex in the array
203 * @param vertexSize the size of each vertex in the array
204 * @param offset the offset in bytes of the vertex component.
205 * Defaults to zero (corresponding to vertex position)
206 * @return pointer to the vertex component as a GrPoint
207 */
208 static GrPoint* GetVertexPoint(void* vertices,
209 int vertexIndex,
210 int vertexSize,
211 int offset = 0) {
212 intptr_t start = GrTCast<intptr_t>(vertices);
213 return GrTCast<GrPoint*>(start + offset +
214 vertexIndex * vertexSize);
215 }
216 static const GrPoint* GetVertexPoint(const void* vertices,
217 int vertexIndex,
218 int vertexSize,
219 int offset = 0) {
220 intptr_t start = GrTCast<intptr_t>(vertices);
221 return GrTCast<const GrPoint*>(start + offset +
222 vertexIndex * vertexSize);
223 }
224
225 /**
226 * Gets a pointer to a GrColor inside a vertex within a vertex array.
227 * @param vertices the vetex array
228 * @param vertexIndex the index of the vertex in the array
229 * @param vertexSize the size of each vertex in the array
230 * @param offset the offset in bytes of the vertex color
231 * @return pointer to the vertex component as a GrColor
232 */
233 static GrColor* GetVertexColor(void* vertices,
234 int vertexIndex,
235 int vertexSize,
236 int offset) {
237 intptr_t start = GrTCast<intptr_t>(vertices);
238 return GrTCast<GrColor*>(start + offset +
239 vertexIndex * vertexSize);
240 }
241 static const GrColor* GetVertexColor(const void* vertices,
242 int vertexIndex,
243 int vertexSize,
244 int offset) {
245 const intptr_t start = GrTCast<intptr_t>(vertices);
246 return GrTCast<const GrColor*>(start + offset +
247 vertexIndex * vertexSize);
248 }
249
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000250 /// @}
251
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000252 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000253 * Determines whether src alpha is guaranteed to be one for all src pixels
254 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000255 bool srcAlphaWillBeOne() const;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000256
257 /**
258 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
259 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000260 bool hasSolidCoverage() const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000261
262 /// @}
263
264 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000265 /// @name Color
266 ////
267
268 /**
269 * Sets color for next draw to a premultiplied-alpha color.
270 *
271 * @param color the color to set.
272 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000273 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000274
bsalomon@google.comca432082013-01-23 19:53:46 +0000275 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000276
277 /**
278 * Sets the color to be used for the next draw to be
279 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
280 *
281 * @param alpha The alpha value to set as the color.
282 */
283 void setAlpha(uint8_t a) {
284 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
285 }
286
287 /**
288 * Add a color filter that can be represented by a color and a mode. Applied
bsalomon@google.comc7818882013-03-20 19:19:53 +0000289 * after color-computing effect stages.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000290 */
291 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000292 fCommon.fColorFilterColor = c;
293 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000294 }
295
bsalomon@google.comca432082013-01-23 19:53:46 +0000296 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
297 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000298
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000299 /**
300 * Constructor sets the color to be 'color' which is undone by the destructor.
301 */
302 class AutoColorRestore : public ::GrNoncopyable {
303 public:
sugoi@google.com66a58ac2013-03-05 20:40:52 +0000304 AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000305
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000306 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000307 fDrawState = NULL;
308 this->set(drawState, color);
309 }
310
311 void reset() {
312 if (NULL != fDrawState) {
313 fDrawState->setColor(fOldColor);
314 fDrawState = NULL;
315 }
316 }
317
318 void set(GrDrawState* drawState, GrColor color) {
319 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000320 fDrawState = drawState;
321 fOldColor = fDrawState->getColor();
322 fDrawState->setColor(color);
323 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000324
325 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000326 private:
327 GrDrawState* fDrawState;
328 GrColor fOldColor;
329 };
330
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000331 /// @}
332
333 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000334 /// @name Coverage
335 ////
336
337 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000338 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000339 * initial value (after construction or reset()) is 0xff. The constant
340 * coverage is ignored when per-vertex coverage is provided.
341 */
342 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000343 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000344 }
345
346 /**
347 * Version of above that specifies 4 channel per-vertex color. The value
348 * should be premultiplied.
349 */
350 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000351 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000352 }
353
354 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000355 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000356 }
357
358 /// @}
359
360 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000361 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000362 ////
363
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000364 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
365 fStages[stageIdx].setEffect(effect);
366 return effect;
367 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000368
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000369 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000370 int attr0, int attr1 = -1) {
371 fStages[stageIdx].setEffect(effect, attr0, attr1);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000372 return effect;
373 }
374
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000375 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000376 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000377 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000378 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000379 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000380 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000381 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000382 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000383 void createTextureEffect(int stageIdx,
384 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000385 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000386 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000387 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000388 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000389 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000390 }
391
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000392 bool stagesDisabled() {
393 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000394 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000395 return false;
396 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000397 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000398 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000399 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000400
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000401 void disableStage(int stageIdx) {
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000402 this->setEffect(stageIdx, NULL);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000403 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000404
robertphillips@google.com972265d2012-06-13 18:49:30 +0000405 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000406 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000407 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000408 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000409 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000410 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000411 }
412 }
413
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000414 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000415 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000416 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
417 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000418 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000419 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000420 }
421 }
422 private:
423 GrDrawState* fDrawState;
424 };
425
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000426 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000427 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000428 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000429 const GrEffectStage& getStage(int stageIdx) const {
430 GrAssert((unsigned)stageIdx < kNumStages);
431 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000432 }
433
434 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000435 * Called when the source coord system is changing. This ensures that effects will see the
436 * correct local coordinates. oldToNew gives the transformation from the old coord system in
437 * which the geometry was specified to the new coordinate system from which it will be rendered.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000438 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000439 void localCoordChange(const SkMatrix& oldToNew) {
reed@google.com67e7cde2013-03-20 17:47:16 +0000440 for (int i = 0; i < kNumStages; ++i) {
441 if (this->isStageEnabled(i)) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000442 fStages[i].localCoordChange(oldToNew);
reed@google.com67e7cde2013-03-20 17:47:16 +0000443 }
444 }
reed@google.com67e7cde2013-03-20 17:47:16 +0000445 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000446
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000447 /**
448 * Checks whether any of the effects will read the dst pixel color.
449 */
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000450 bool willEffectReadDstColor() const;
reed@google.com67e7cde2013-03-20 17:47:16 +0000451
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000452 /// @}
453
454 ///////////////////////////////////////////////////////////////////////////
455 /// @name Coverage / Color Stages
456 ////
457
458 /**
459 * A common pattern is to compute a color with the initial stages and then
460 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000461 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
462 * computed based on the pre-coverage-modulated color. The division of
463 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000464 * this method. Initially this is kNumStages (all stages
465 * are color-computing).
466 */
467 void setFirstCoverageStage(int firstCoverageStage) {
468 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000469 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000470 }
471
472 /**
473 * Gets the index of the first coverage-computing stage.
474 */
475 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000476 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 }
478
479 ///@}
480
481 ///////////////////////////////////////////////////////////////////////////
482 /// @name Blending
483 ////
484
485 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000486 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487 *
488 * The blend function will be:
489 * D' = sat(S*srcCoef + D*dstCoef)
490 *
491 * where D is the existing destination color, S is the incoming source
492 * color, and D' is the new destination color that will be written. sat()
493 * is the saturation function.
494 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000495 * @param srcCoef coefficient applied to the src color.
496 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000497 */
498 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000499 fCommon.fSrcBlend = srcCoeff;
500 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000501 #if GR_DEBUG
502 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000503 case kDC_GrBlendCoeff:
504 case kIDC_GrBlendCoeff:
505 case kDA_GrBlendCoeff:
506 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000507 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
508 "coverage stages.\n");
509 break;
510 default:
511 break;
512 }
513 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000514 case kSC_GrBlendCoeff:
515 case kISC_GrBlendCoeff:
516 case kSA_GrBlendCoeff:
517 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000518 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
519 "coverage stages.\n");
520 break;
521 default:
522 break;
523 }
524 #endif
525 }
526
bsalomon@google.comca432082013-01-23 19:53:46 +0000527 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
528 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529
530 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
531 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000532 *srcBlendCoeff = fCommon.fSrcBlend;
533 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000534 }
535
536 /**
537 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000538 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000539 * kConstC_GrBlendCoeff
540 * kIConstC_GrBlendCoeff
541 * kConstA_GrBlendCoeff
542 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543 *
544 * @param constant the constant to set
545 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000546 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000547
548 /**
549 * Retrieves the last value set by setBlendConstant()
550 * @return the blending constant value
551 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000552 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000553
bsalomon@google.com2b446732013-02-12 16:47:41 +0000554 /**
555 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
556 * coverage before the blend will give the correct final destination color. In general it
557 * will not as coverage is applied after blending.
558 */
559 bool canTweakAlphaForCoverage() const;
560
561 /**
562 * Optimizations for blending / coverage to that can be applied based on the current state.
563 */
564 enum BlendOptFlags {
565 /**
566 * No optimization
567 */
568 kNone_BlendOpt = 0,
569 /**
570 * Don't draw at all
571 */
572 kSkipDraw_BlendOptFlag = 0x1,
573 /**
574 * Emit the src color, disable HW blending (replace dst with src)
575 */
576 kDisableBlend_BlendOptFlag = 0x2,
577 /**
578 * The coverage value does not have to be computed separately from alpha, the the output
579 * color can be the modulation of the two.
580 */
581 kCoverageAsAlpha_BlendOptFlag = 0x4,
582 /**
583 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
584 * "don't cares".
585 */
586 kEmitCoverage_BlendOptFlag = 0x8,
587 /**
588 * Emit transparent black instead of the src color, no need to compute coverage.
589 */
590 kEmitTransBlack_BlendOptFlag = 0x10,
591 };
592 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
593
594 /**
595 * Determines what optimizations can be applied based on the blend. The coefficients may have
596 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
597 * params that receive the tweaked coefficients. Normally the function looks at the current
598 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
599 * determine the blend optimizations that would be used if there was partial pixel coverage.
600 *
601 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
602 * playback) must call this function and respect the flags that replace the output color.
603 */
604 BlendOptFlags getBlendOpts(bool forceCoverage = false,
605 GrBlendCoeff* srcCoeff = NULL,
606 GrBlendCoeff* dstCoeff = NULL) const;
607
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 /// @}
609
610 ///////////////////////////////////////////////////////////////////////////
611 /// @name View Matrix
612 ////
613
614 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000615 * Sets the view matrix to identity and updates any installed effects to compensate for the
616 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000618 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619
620 /**
621 * Retrieves the current view matrix
622 * @return the current view matrix.
623 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000624 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000625
626 /**
627 * Retrieves the inverse of the current view matrix.
628 *
629 * If the current view matrix is invertible, return true, and if matrix
630 * is non-null, copy the inverse into it. If the current view matrix is
631 * non-invertible, return false and ignore the matrix parameter.
632 *
633 * @param matrix if not null, will receive a copy of the current inverse.
634 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000635 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000636 // TODO: determine whether we really need to leave matrix unmodified
637 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000638 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000639 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000640 if (matrix) {
641 *matrix = inverse;
642 }
643 return true;
644 }
645 return false;
646 }
647
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000648 ////////////////////////////////////////////////////////////////////////////
649
650 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000651 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000652 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000653 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 class AutoViewMatrixRestore : public ::GrNoncopyable {
655 public:
656 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000657
bsalomon@google.comc7818882013-03-20 19:19:53 +0000658 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000659 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000660 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000661 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000662
663 ~AutoViewMatrixRestore() { this->restore(); }
664
bsalomon@google.coma8347462012-10-08 18:59:39 +0000665 /**
666 * Can be called prior to destructor to restore the original matrix.
667 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000668 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000669
bsalomon@google.comc7818882013-03-20 19:19:53 +0000670 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000671
bsalomon@google.com137f1342013-05-29 21:27:53 +0000672 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
673 is not invertible. */
674 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000675
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000676 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000677 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000678 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000679 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000680 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000681 };
682
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000683 /// @}
684
685 ///////////////////////////////////////////////////////////////////////////
686 /// @name Render Target
687 ////
688
689 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000690 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000691 *
692 * @param target The render target to set.
693 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000694 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000695 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000696 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000697
698 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000699 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700 *
701 * @return The currently set render target.
702 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000703 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
704 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000705
706 class AutoRenderTargetRestore : public ::GrNoncopyable {
707 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000708 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000709 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
710 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000711 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000712 this->set(ds, newTarget);
713 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000714 ~AutoRenderTargetRestore() { this->restore(); }
715
716 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000717 if (NULL != fDrawState) {
718 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000719 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000720 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000721 GrSafeSetNull(fSavedTarget);
722 }
723
724 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
725 this->restore();
726
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000727 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000728 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000729 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000730 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000731 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000732 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000733 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000734 }
735 private:
736 GrDrawState* fDrawState;
737 GrRenderTarget* fSavedTarget;
738 };
739
740 /// @}
741
742 ///////////////////////////////////////////////////////////////////////////
743 /// @name Stencil
744 ////
745
746 /**
747 * Sets the stencil settings to use for the next draw.
748 * Changing the clip has the side-effect of possibly zeroing
749 * out the client settable stencil bits. So multipass algorithms
750 * using stencil should not change the clip between passes.
751 * @param settings the stencil settings to use.
752 */
753 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000754 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755 }
756
757 /**
758 * Shortcut to disable stencil testing and ops.
759 */
760 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000761 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762 }
763
bsalomon@google.comca432082013-01-23 19:53:46 +0000764 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765
bsalomon@google.comca432082013-01-23 19:53:46 +0000766 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000767
768 /// @}
769
770 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000771 /// @name State Flags
772 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000773
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000774 /**
775 * Flags that affect rendering. Controlled using enable/disableState(). All
776 * default to disabled.
777 */
778 enum StateBits {
779 /**
780 * Perform dithering. TODO: Re-evaluate whether we need this bit
781 */
782 kDither_StateBit = 0x01,
783 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000784 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
785 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
786 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000787 */
788 kHWAntialias_StateBit = 0x02,
789 /**
790 * Draws will respect the clip, otherwise the clip is ignored.
791 */
792 kClip_StateBit = 0x04,
793 /**
794 * Disables writing to the color buffer. Useful when performing stencil
795 * operations.
796 */
797 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000798
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000799 /**
800 * Usually coverage is applied after color blending. The color is blended using the coeffs
801 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
802 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
803 * this case there is no distinction between coverage and color and the caller needs direct
804 * control over the blend coeffs. When set, there will be a single blend step controlled by
805 * setBlendFunc() which will use coverage*color as the src color.
806 */
807 kCoverageDrawing_StateBit = 0x10,
808
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000809 // Users of the class may add additional bits to the vector
810 kDummyStateBit,
811 kLastPublicStateBit = kDummyStateBit-1,
812 };
813
814 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000815 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000816 }
817
818 /**
819 * Enable render state settings.
820 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000821 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000822 */
823 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000824 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000825 }
826
827 /**
828 * Disable render state settings.
829 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000830 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000831 */
832 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000833 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000834 }
835
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000836 /**
837 * Enable or disable stateBits based on a boolean.
838 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000839 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000840 * @param enable if true enable stateBits, otherwise disable
841 */
842 void setState(uint32_t stateBits, bool enable) {
843 if (enable) {
844 this->enableState(stateBits);
845 } else {
846 this->disableState(stateBits);
847 }
848 }
849
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000850 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000851 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000852 }
853
854 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000855 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000856 }
857
858 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000859 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000860 }
861
862 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000863 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000864 }
865
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000866 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000867 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000868 }
869
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000871 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000872 }
873
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000874 /// @}
875
876 ///////////////////////////////////////////////////////////////////////////
877 /// @name Face Culling
878 ////
879
880 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000881 kInvalid_DrawFace = -1,
882
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000883 kBoth_DrawFace,
884 kCCW_DrawFace,
885 kCW_DrawFace,
886 };
887
888 /**
889 * Controls whether clockwise, counterclockwise, or both faces are drawn.
890 * @param face the face(s) to draw.
891 */
892 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000893 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +0000894 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000895 }
896
897 /**
898 * Gets whether the target is drawing clockwise, counterclockwise,
899 * or both faces.
900 * @return the current draw face(s).
901 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000902 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000903
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 /// @}
905
906 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000907
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000908 bool isStageEnabled(int s) const {
909 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +0000910 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000911 }
912
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000913 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000914 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000915 return false;
916 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000917 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000918 bool enabled = this->isStageEnabled(i);
919 if (enabled != s.isStageEnabled(i)) {
920 return false;
921 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000922 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000923 return false;
924 }
925 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000926 return true;
927 }
928 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
929
bsalomon@google.comca432082013-01-23 19:53:46 +0000930 GrDrawState& operator= (const GrDrawState& s) {
931 this->setRenderTarget(s.fRenderTarget.get());
932 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000933 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000934 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000935 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000936 }
937 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000938 return *this;
939 }
940
941private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000942
bsalomon@google.com137f1342013-05-29 21:27:53 +0000943 void onReset(const SkMatrix* initialViewMatrix) {
944
945 this->disableStages();
946
947 fRenderTarget.reset(NULL);
948
949 this->setDefaultVertexAttribs();
950
951 fCommon.fColor = 0xffffffff;
952 if (NULL == initialViewMatrix) {
953 fCommon.fViewMatrix.reset();
954 } else {
955 fCommon.fViewMatrix = *initialViewMatrix;
956 }
957 fCommon.fSrcBlend = kOne_GrBlendCoeff;
958 fCommon.fDstBlend = kZero_GrBlendCoeff;
959 fCommon.fBlendConstant = 0x0;
960 fCommon.fFlagBits = 0x0;
961 fCommon.fStencilSettings.setDisabled();
962 fCommon.fFirstCoverageStage = kNumStages;
963 fCommon.fCoverage = 0xffffffff;
964 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
965 fCommon.fColorFilterColor = 0x0;
966 fCommon.fDrawFace = kBoth_DrawFace;
967 }
968
bsalomon@google.comca432082013-01-23 19:53:46 +0000969 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
970 struct CommonState {
971 // These fields are roughly sorted by decreasing likelihood of being different in op==
robertphillips@google.com42903302013-04-20 12:26:07 +0000972 GrColor fColor;
973 SkMatrix fViewMatrix;
974 GrBlendCoeff fSrcBlend;
975 GrBlendCoeff fDstBlend;
976 GrColor fBlendConstant;
977 uint32_t fFlagBits;
978 const GrVertexAttrib* fVAPtr;
979 int fVACount;
980 GrStencilSettings fStencilSettings;
981 int fFirstCoverageStage;
982 GrColor fCoverage;
983 SkXfermode::Mode fColorFilterMode;
984 GrColor fColorFilterColor;
985 DrawFace fDrawFace;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000986
987 // This is simply a different representation of info in fVertexAttribs and thus does
988 // not need to be compared in op==.
989 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
990
bsalomon@google.comca432082013-01-23 19:53:46 +0000991 bool operator== (const CommonState& other) const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000992 bool result = fColor == other.fColor &&
993 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
994 fSrcBlend == other.fSrcBlend &&
995 fDstBlend == other.fDstBlend &&
996 fBlendConstant == other.fBlendConstant &&
997 fFlagBits == other.fFlagBits &&
robertphillips@google.com42903302013-04-20 12:26:07 +0000998 fVACount == other.fVACount &&
999 !memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
jvanverth@google.com054ae992013-04-01 20:06:51 +00001000 fStencilSettings == other.fStencilSettings &&
1001 fFirstCoverageStage == other.fFirstCoverageStage &&
1002 fCoverage == other.fCoverage &&
1003 fColorFilterMode == other.fColorFilterMode &&
1004 fColorFilterColor == other.fColorFilterColor &&
1005 fDrawFace == other.fDrawFace;
1006 GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
1007 other.fFixedFunctionVertexAttribIndices,
1008 sizeof(fFixedFunctionVertexAttribIndices)));
1009 return result;
bsalomon@google.comca432082013-01-23 19:53:46 +00001010 }
1011 bool operator!= (const CommonState& other) const { return !(*this == other); }
1012 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001013
bsalomon@google.comca432082013-01-23 19:53:46 +00001014 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1015 DeferredState must directly reference GrEffects, however. */
1016 struct SavedEffectStage {
1017 SavedEffectStage() : fEffect(NULL) {}
1018 const GrEffect* fEffect;
1019 GrEffectStage::SavedCoordChange fCoordChange;
1020 };
1021
1022public:
1023 /**
1024 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1025 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1026 * dispose mechanism returns them to the cache. This allows recycling resources through the
1027 * the cache while they are in a deferred draw queue.
1028 */
1029 class DeferredState {
1030 public:
1031 DeferredState() : fRenderTarget(NULL) {
1032 GR_DEBUGCODE(fInitialized = false;)
1033 }
1034 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1035 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1036
1037 void saveFrom(const GrDrawState& drawState) {
1038 fCommon = drawState.fCommon;
1039 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1040 fRenderTarget = drawState.fRenderTarget.get();
1041 SkSafeRef(fRenderTarget);
1042 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1043 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1044 // and recycle them to the cache (if no one else is holding a ref to the resources).
1045 for (int i = 0; i < kNumStages; ++i) {
1046 fStages[i].saveFrom(drawState.fStages[i]);
1047 }
1048 GR_DEBUGCODE(fInitialized = true;)
1049 }
1050
1051 void restoreTo(GrDrawState* drawState) {
1052 GrAssert(fInitialized);
1053 drawState->fCommon = fCommon;
1054 drawState->setRenderTarget(fRenderTarget);
1055 for (int i = 0; i < kNumStages; ++i) {
1056 fStages[i].restoreTo(&drawState->fStages[i]);
1057 }
1058 }
1059
1060 bool isEqual(const GrDrawState& state) const {
1061 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1062 return false;
1063 }
1064 for (int i = 0; i < kNumStages; ++i) {
robertphillips@google.com5f9f2b02013-06-10 22:07:19 +00001065 if (!fStages[i].isEqual(state.fStages[i], state.hasLocalCoordAttribute())) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001066 return false;
1067 }
1068 }
1069 return true;
1070 }
1071
1072 private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001073 GrRenderTarget* fRenderTarget;
1074 CommonState fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001075 GrEffectStage::DeferredStage fStages[kNumStages];
bsalomon@google.comca432082013-01-23 19:53:46 +00001076
1077 GR_DEBUGCODE(bool fInitialized;)
1078 };
1079
1080private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001081
1082 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1083 CommonState fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001084 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001085
robertphillips@google.com42903302013-04-20 12:26:07 +00001086 /**
1087 * Sets vertex attributes for next draw.
1088 *
1089 * @param attribs the array of vertex attributes to set.
1090 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
1091 */
1092 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
1093
reed@google.comfa35e3d2012-06-26 20:16:17 +00001094 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001095};
1096
bsalomon@google.com2b446732013-02-12 16:47:41 +00001097GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1098
tomhudson@google.com93813632011-10-27 20:21:16 +00001099#endif