blob: e34e4ab0e1d59365ca1df0a7cbc35b07e633c753 [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.comca432082013-01-23 19:53:46 +000059 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000060 this->reset();
61 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000062
bsalomon@google.comca432082013-01-23 19:53:46 +000063 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000064 *this = state;
65 }
66
robertphillips@google.com9ec07532012-06-22 12:01:30 +000067 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000068 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000069 }
70
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000071 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000072 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000073 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000074 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000075 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000076
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078
bsalomon@google.comca432082013-01-23 19:53:46 +000079 fRenderTarget.reset(NULL);
80
jvanverth@google.com9b855c72013-03-01 18:21:22 +000081 this->setDefaultVertexAttribs();
82
bsalomon@google.comca432082013-01-23 19:53:46 +000083 fCommon.fColor = 0xffffffff;
84 fCommon.fViewMatrix.reset();
85 fCommon.fSrcBlend = kOne_GrBlendCoeff;
86 fCommon.fDstBlend = kZero_GrBlendCoeff;
87 fCommon.fBlendConstant = 0x0;
88 fCommon.fFlagBits = 0x0;
bsalomon@google.comca432082013-01-23 19:53:46 +000089 fCommon.fStencilSettings.setDisabled();
90 fCommon.fFirstCoverageStage = kNumStages;
91 fCommon.fCoverage = 0xffffffff;
92 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
93 fCommon.fColorFilterColor = 0x0;
94 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000095 }
96
97 /**
98 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +000099 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000100 * GrPaint equivalents are not modified. GrPaint has fewer stages than
101 * GrDrawState. The extra GrDrawState stages are disabled.
102 */
103 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000104
105 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000106 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000107 ////
108
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000109 enum {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000110 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000111 };
112
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000113 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000114 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
115 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
116 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000117 *
jvanverth@google.com054ae992013-04-01 20:06:51 +0000118 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
119 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000120 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000121
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000122 /**
robertphillips@google.com42903302013-04-20 12:26:07 +0000123 * Sets vertex attributes for next draw. The object driving the templatization
124 * should be a global GrVertexAttrib array that is never changed.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000125 */
robertphillips@google.com42903302013-04-20 12:26:07 +0000126 template <const GrVertexAttrib A[]> void setVertexAttribs(int count) {
127 this->setVertexAttribs(A, count);
128 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000129
robertphillips@google.com42903302013-04-20 12:26:07 +0000130 const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVAPtr; }
131 int getVertexAttribCount() const { return fCommon.fVACount; }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000132
133 size_t getVertexSize() const;
134
135 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000136 * Sets default vertex attributes for next draw. The default is a single attribute:
137 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000138 */
139 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000140
jvanverth@google.com054ae992013-04-01 20:06:51 +0000141 /**
142 * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
143 * binding does not appear in the current attribs. These bindings should appear only once in
144 * the attrib array.
145 */
146
147 int positionAttributeIndex() const {
148 return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
149 }
150 int localCoordAttributeIndex() const {
151 return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
152 }
153 int colorVertexAttributeIndex() const {
154 return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
155 }
156 int coverageVertexAttributeIndex() const {
157 return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
158 }
159
160 bool hasLocalCoordAttribute() const {
161 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
162 }
163 bool hasColorVertexAttribute() const {
164 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
165 }
166 bool hasCoverageVertexAttribute() const {
167 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
168 }
169
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000170 bool validateVertexAttribs() const;
171
jvanverth@google.comcc782382013-01-28 20:39:48 +0000172 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000173 * Helper to save/restore vertex attribs
174 */
175 class AutoVertexAttribRestore {
176 public:
177 AutoVertexAttribRestore(GrDrawState* drawState) {
178 GrAssert(NULL != drawState);
179 fDrawState = drawState;
robertphillips@google.com42903302013-04-20 12:26:07 +0000180 fVAPtr = drawState->fCommon.fVAPtr;
181 fVACount = drawState->fCommon.fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000182 fDrawState->setDefaultVertexAttribs();
183 }
184
185 ~AutoVertexAttribRestore(){
robertphillips@google.com42903302013-04-20 12:26:07 +0000186 fDrawState->fCommon.fVAPtr = fVAPtr;
187 fDrawState->fCommon.fVACount = fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000188 }
189
190 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000191 GrDrawState* fDrawState;
192 const GrVertexAttrib* fVAPtr;
193 int fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000194 };
195
196 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000197 * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
198 * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
199 * nicer looking.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000200 */
201
202 /**
203 * Gets a pointer to a GrPoint of a vertex's position or texture
204 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000205 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000206 * @param vertexIndex the index of the vertex in the array
207 * @param vertexSize the size of each vertex in the array
208 * @param offset the offset in bytes of the vertex component.
209 * Defaults to zero (corresponding to vertex position)
210 * @return pointer to the vertex component as a GrPoint
211 */
212 static GrPoint* GetVertexPoint(void* vertices,
213 int vertexIndex,
214 int vertexSize,
215 int offset = 0) {
216 intptr_t start = GrTCast<intptr_t>(vertices);
217 return GrTCast<GrPoint*>(start + offset +
218 vertexIndex * vertexSize);
219 }
220 static const GrPoint* GetVertexPoint(const void* vertices,
221 int vertexIndex,
222 int vertexSize,
223 int offset = 0) {
224 intptr_t start = GrTCast<intptr_t>(vertices);
225 return GrTCast<const GrPoint*>(start + offset +
226 vertexIndex * vertexSize);
227 }
228
229 /**
230 * Gets a pointer to a GrColor inside a vertex within a vertex array.
231 * @param vertices the vetex array
232 * @param vertexIndex the index of the vertex in the array
233 * @param vertexSize the size of each vertex in the array
234 * @param offset the offset in bytes of the vertex color
235 * @return pointer to the vertex component as a GrColor
236 */
237 static GrColor* GetVertexColor(void* vertices,
238 int vertexIndex,
239 int vertexSize,
240 int offset) {
241 intptr_t start = GrTCast<intptr_t>(vertices);
242 return GrTCast<GrColor*>(start + offset +
243 vertexIndex * vertexSize);
244 }
245 static const GrColor* GetVertexColor(const void* vertices,
246 int vertexIndex,
247 int vertexSize,
248 int offset) {
249 const intptr_t start = GrTCast<intptr_t>(vertices);
250 return GrTCast<const GrColor*>(start + offset +
251 vertexIndex * vertexSize);
252 }
253
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000254 /// @}
255
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000256 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000257 * Determines whether src alpha is guaranteed to be one for all src pixels
258 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000259 bool srcAlphaWillBeOne() const;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000260
261 /**
262 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
263 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000264 bool hasSolidCoverage() const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000265
266 /// @}
267
268 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000269 /// @name Color
270 ////
271
272 /**
273 * Sets color for next draw to a premultiplied-alpha color.
274 *
275 * @param color the color to set.
276 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000277 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000278
bsalomon@google.comca432082013-01-23 19:53:46 +0000279 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000280
281 /**
282 * Sets the color to be used for the next draw to be
283 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
284 *
285 * @param alpha The alpha value to set as the color.
286 */
287 void setAlpha(uint8_t a) {
288 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
289 }
290
291 /**
292 * Add a color filter that can be represented by a color and a mode. Applied
bsalomon@google.comc7818882013-03-20 19:19:53 +0000293 * after color-computing effect stages.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000294 */
295 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000296 fCommon.fColorFilterColor = c;
297 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000298 }
299
bsalomon@google.comca432082013-01-23 19:53:46 +0000300 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
301 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000302
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000303 /**
304 * Constructor sets the color to be 'color' which is undone by the destructor.
305 */
306 class AutoColorRestore : public ::GrNoncopyable {
307 public:
sugoi@google.com66a58ac2013-03-05 20:40:52 +0000308 AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000309
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000310 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000311 fDrawState = NULL;
312 this->set(drawState, color);
313 }
314
315 void reset() {
316 if (NULL != fDrawState) {
317 fDrawState->setColor(fOldColor);
318 fDrawState = NULL;
319 }
320 }
321
322 void set(GrDrawState* drawState, GrColor color) {
323 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000324 fDrawState = drawState;
325 fOldColor = fDrawState->getColor();
326 fDrawState->setColor(color);
327 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000328
329 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000330 private:
331 GrDrawState* fDrawState;
332 GrColor fOldColor;
333 };
334
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000335 /// @}
336
337 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000338 /// @name Coverage
339 ////
340
341 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000342 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000343 * initial value (after construction or reset()) is 0xff. The constant
344 * coverage is ignored when per-vertex coverage is provided.
345 */
346 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000347 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000348 }
349
350 /**
351 * Version of above that specifies 4 channel per-vertex color. The value
352 * should be premultiplied.
353 */
354 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000355 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000356 }
357
358 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000359 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000360 }
361
362 /// @}
363
364 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000365 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000366 ////
367
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000368 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
369 fStages[stageIdx].setEffect(effect);
370 return effect;
371 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000372
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000373 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000374 int attr0, int attr1 = -1) {
375 fStages[stageIdx].setEffect(effect, attr0, attr1);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000376 return effect;
377 }
378
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000379 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000380 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000381 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000382 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000383 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000384 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000385 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000386 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000387 void createTextureEffect(int stageIdx,
388 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000389 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000390 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000391 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000392 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000393 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000394 }
395
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000396 bool stagesDisabled() {
397 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000398 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000399 return false;
400 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000401 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000402 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000403 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000404
skia.committer@gmail.com91274b92013-03-13 07:01:04 +0000405 void disableStage(int stageIdx) {
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000406 this->setEffect(stageIdx, NULL);
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000407 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000408
robertphillips@google.com972265d2012-06-13 18:49:30 +0000409 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000410 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000411 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000412 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000413 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000414 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000415 }
416 }
417
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000418 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000419 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000420 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
421 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000422 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000423 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000424 }
425 }
426 private:
427 GrDrawState* fDrawState;
428 };
429
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000430 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000431 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000432 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000433 const GrEffectStage& getStage(int stageIdx) const {
434 GrAssert((unsigned)stageIdx < kNumStages);
435 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000436 }
437
438 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000439 * Called when the source coord system is changing. This ensures that effects will see the
440 * correct local coordinates. oldToNew gives the transformation from the old coord system in
441 * which the geometry was specified to the new coordinate system from which it will be rendered.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000442 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000443 void localCoordChange(const SkMatrix& oldToNew) {
reed@google.com67e7cde2013-03-20 17:47:16 +0000444 for (int i = 0; i < kNumStages; ++i) {
445 if (this->isStageEnabled(i)) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000446 fStages[i].localCoordChange(oldToNew);
reed@google.com67e7cde2013-03-20 17:47:16 +0000447 }
448 }
reed@google.com67e7cde2013-03-20 17:47:16 +0000449 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000450
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000451 /**
452 * Checks whether any of the effects will read the dst pixel color.
453 */
454 bool willEffectReadDst() const {
455 for (int s = 0; s < kNumStages; ++s) {
456 if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDst()) {
457 return true;
458 }
459 }
460 return false;
461 }
reed@google.com67e7cde2013-03-20 17:47:16 +0000462
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000463 /// @}
464
465 ///////////////////////////////////////////////////////////////////////////
466 /// @name Coverage / Color Stages
467 ////
468
469 /**
470 * A common pattern is to compute a color with the initial stages and then
471 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000472 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
473 * computed based on the pre-coverage-modulated color. The division of
474 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000475 * this method. Initially this is kNumStages (all stages
476 * are color-computing).
477 */
478 void setFirstCoverageStage(int firstCoverageStage) {
479 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000480 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 }
482
483 /**
484 * Gets the index of the first coverage-computing stage.
485 */
486 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000487 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488 }
489
490 ///@}
491
492 ///////////////////////////////////////////////////////////////////////////
493 /// @name Blending
494 ////
495
496 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000497 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000498 *
499 * The blend function will be:
500 * D' = sat(S*srcCoef + D*dstCoef)
501 *
502 * where D is the existing destination color, S is the incoming source
503 * color, and D' is the new destination color that will be written. sat()
504 * is the saturation function.
505 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000506 * @param srcCoef coefficient applied to the src color.
507 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000508 */
509 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000510 fCommon.fSrcBlend = srcCoeff;
511 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 #if GR_DEBUG
513 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000514 case kDC_GrBlendCoeff:
515 case kIDC_GrBlendCoeff:
516 case kDA_GrBlendCoeff:
517 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000518 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
519 "coverage stages.\n");
520 break;
521 default:
522 break;
523 }
524 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000525 case kSC_GrBlendCoeff:
526 case kISC_GrBlendCoeff:
527 case kSA_GrBlendCoeff:
528 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
530 "coverage stages.\n");
531 break;
532 default:
533 break;
534 }
535 #endif
536 }
537
bsalomon@google.comca432082013-01-23 19:53:46 +0000538 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
539 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540
541 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
542 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000543 *srcBlendCoeff = fCommon.fSrcBlend;
544 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000545 }
546
547 /**
548 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000549 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000550 * kConstC_GrBlendCoeff
551 * kIConstC_GrBlendCoeff
552 * kConstA_GrBlendCoeff
553 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000554 *
555 * @param constant the constant to set
556 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000557 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000558
559 /**
560 * Retrieves the last value set by setBlendConstant()
561 * @return the blending constant value
562 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000563 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000564
bsalomon@google.com2b446732013-02-12 16:47:41 +0000565 /**
566 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
567 * coverage before the blend will give the correct final destination color. In general it
568 * will not as coverage is applied after blending.
569 */
570 bool canTweakAlphaForCoverage() const;
571
572 /**
573 * Optimizations for blending / coverage to that can be applied based on the current state.
574 */
575 enum BlendOptFlags {
576 /**
577 * No optimization
578 */
579 kNone_BlendOpt = 0,
580 /**
581 * Don't draw at all
582 */
583 kSkipDraw_BlendOptFlag = 0x1,
584 /**
585 * Emit the src color, disable HW blending (replace dst with src)
586 */
587 kDisableBlend_BlendOptFlag = 0x2,
588 /**
589 * The coverage value does not have to be computed separately from alpha, the the output
590 * color can be the modulation of the two.
591 */
592 kCoverageAsAlpha_BlendOptFlag = 0x4,
593 /**
594 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
595 * "don't cares".
596 */
597 kEmitCoverage_BlendOptFlag = 0x8,
598 /**
599 * Emit transparent black instead of the src color, no need to compute coverage.
600 */
601 kEmitTransBlack_BlendOptFlag = 0x10,
602 };
603 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
604
605 /**
606 * Determines what optimizations can be applied based on the blend. The coefficients may have
607 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
608 * params that receive the tweaked coefficients. Normally the function looks at the current
609 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
610 * determine the blend optimizations that would be used if there was partial pixel coverage.
611 *
612 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
613 * playback) must call this function and respect the flags that replace the output color.
614 */
615 BlendOptFlags getBlendOpts(bool forceCoverage = false,
616 GrBlendCoeff* srcCoeff = NULL,
617 GrBlendCoeff* dstCoeff = NULL) const;
618
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 /// @}
620
621 ///////////////////////////////////////////////////////////////////////////
622 /// @name View Matrix
623 ////
624
625 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000626 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000627 *
628 * In the post-view-matrix space the rectangle [0,w]x[0,h]
629 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000630 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000631 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000632 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633
634 /**
635 * Gets a writable pointer to the view matrix.
636 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000637 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638
639 /**
640 * Multiplies the current view matrix by a matrix
641 *
642 * After this call V' = V*m where V is the old view matrix,
643 * m is the parameter to this function, and V' is the new view matrix.
644 * (We consider positions to be column vectors so position vector p is
645 * transformed by matrix X as p' = X*p.)
646 *
647 * @param m the matrix used to modify the view matrix.
648 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000649 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000650
651 /**
652 * Multiplies the current view matrix by a matrix
653 *
654 * After this call V' = m*V where V is the old view matrix,
655 * m is the parameter to this function, and V' is the new view matrix.
656 * (We consider positions to be column vectors so position vector p is
657 * transformed by matrix X as p' = X*p.)
658 *
659 * @param m the matrix used to modify the view matrix.
660 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000661 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000662
663 /**
664 * Retrieves the current view matrix
665 * @return the current view matrix.
666 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000667 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000668
669 /**
670 * Retrieves the inverse of the current view matrix.
671 *
672 * If the current view matrix is invertible, return true, and if matrix
673 * is non-null, copy the inverse into it. If the current view matrix is
674 * non-invertible, return false and ignore the matrix parameter.
675 *
676 * @param matrix if not null, will receive a copy of the current inverse.
677 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000678 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000679 // TODO: determine whether we really need to leave matrix unmodified
680 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000681 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000682 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000683 if (matrix) {
684 *matrix = inverse;
685 }
686 return true;
687 }
688 return false;
689 }
690
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000691 ////////////////////////////////////////////////////////////////////////////
692
693 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000694 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000695 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000696 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000697 class AutoViewMatrixRestore : public ::GrNoncopyable {
698 public:
699 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000700
bsalomon@google.comc7818882013-03-20 19:19:53 +0000701 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000702 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000703 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000704 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000705
706 ~AutoViewMatrixRestore() { this->restore(); }
707
bsalomon@google.coma8347462012-10-08 18:59:39 +0000708 /**
709 * Can be called prior to destructor to restore the original matrix.
710 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000711 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000712
bsalomon@google.comc7818882013-03-20 19:19:53 +0000713 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000714
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000715 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000716
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000717 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000718 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000719 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000720 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000721 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000722 };
723
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000724 ////////////////////////////////////////////////////////////////////////////
725
726 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000727 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
728 * destructor undoes the changes, restoring the view matrix that was set before the
729 * constructor. It is similar to passing the inverse of the current view matrix to
730 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000731 */
732 class AutoDeviceCoordDraw : ::GrNoncopyable {
733 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000734 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000735 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000736 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
737 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
738 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000739 */
bsalomon@google.comc7818882013-03-20 19:19:53 +0000740 AutoDeviceCoordDraw(GrDrawState* drawState) {
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000741 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000742 this->set(drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000743 }
744
bsalomon@google.coma8347462012-10-08 18:59:39 +0000745 ~AutoDeviceCoordDraw() { this->restore(); }
746
bsalomon@google.comc7818882013-03-20 19:19:53 +0000747 bool set(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000748
bsalomon@google.coma8347462012-10-08 18:59:39 +0000749 /**
750 * Returns true if this object was successfully initialized on to a GrDrawState. It may
751 * return false because a non-default constructor or set() were never called or because
752 * the view matrix was not invertible.
753 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000754 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000755
bsalomon@google.coma8347462012-10-08 18:59:39 +0000756 /**
757 * Returns the matrix that was set previously set on the drawState. This is only valid
758 * if succeeded returns true.
759 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000760 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000761 GrAssert(this->succeeded());
762 return fViewMatrix;
763 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000764
bsalomon@google.coma8347462012-10-08 18:59:39 +0000765 /**
766 * Can be called prior to destructor to restore the original matrix.
767 */
768 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000769
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000770 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000771 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000772 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000773 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000774 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000775 };
776
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000777 /// @}
778
779 ///////////////////////////////////////////////////////////////////////////
780 /// @name Render Target
781 ////
782
783 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000784 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000785 *
786 * @param target The render target to set.
787 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000788 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000789 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000790 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791
792 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000793 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000794 *
795 * @return The currently set render target.
796 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000797 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
798 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000799
800 class AutoRenderTargetRestore : public ::GrNoncopyable {
801 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000802 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000803 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
804 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000805 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000806 this->set(ds, newTarget);
807 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000808 ~AutoRenderTargetRestore() { this->restore(); }
809
810 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000811 if (NULL != fDrawState) {
812 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000813 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000814 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000815 GrSafeSetNull(fSavedTarget);
816 }
817
818 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
819 this->restore();
820
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000822 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000823 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000824 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000825 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000826 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000827 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000828 }
829 private:
830 GrDrawState* fDrawState;
831 GrRenderTarget* fSavedTarget;
832 };
833
834 /// @}
835
836 ///////////////////////////////////////////////////////////////////////////
837 /// @name Stencil
838 ////
839
840 /**
841 * Sets the stencil settings to use for the next draw.
842 * Changing the clip has the side-effect of possibly zeroing
843 * out the client settable stencil bits. So multipass algorithms
844 * using stencil should not change the clip between passes.
845 * @param settings the stencil settings to use.
846 */
847 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000848 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000849 }
850
851 /**
852 * Shortcut to disable stencil testing and ops.
853 */
854 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000855 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000856 }
857
bsalomon@google.comca432082013-01-23 19:53:46 +0000858 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000859
bsalomon@google.comca432082013-01-23 19:53:46 +0000860 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000861
862 /// @}
863
864 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000865 /// @name State Flags
866 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000867
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000868 /**
869 * Flags that affect rendering. Controlled using enable/disableState(). All
870 * default to disabled.
871 */
872 enum StateBits {
873 /**
874 * Perform dithering. TODO: Re-evaluate whether we need this bit
875 */
876 kDither_StateBit = 0x01,
877 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000878 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
879 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
880 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000881 */
882 kHWAntialias_StateBit = 0x02,
883 /**
884 * Draws will respect the clip, otherwise the clip is ignored.
885 */
886 kClip_StateBit = 0x04,
887 /**
888 * Disables writing to the color buffer. Useful when performing stencil
889 * operations.
890 */
891 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000892
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000893 /**
894 * Usually coverage is applied after color blending. The color is blended using the coeffs
895 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
896 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
897 * this case there is no distinction between coverage and color and the caller needs direct
898 * control over the blend coeffs. When set, there will be a single blend step controlled by
899 * setBlendFunc() which will use coverage*color as the src color.
900 */
901 kCoverageDrawing_StateBit = 0x10,
902
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000903 // Users of the class may add additional bits to the vector
904 kDummyStateBit,
905 kLastPublicStateBit = kDummyStateBit-1,
906 };
907
908 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000909 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000910 }
911
912 /**
913 * Enable render state settings.
914 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000915 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916 */
917 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000918 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000919 }
920
921 /**
922 * Disable render state settings.
923 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000924 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000925 */
926 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000927 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928 }
929
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000930 /**
931 * Enable or disable stateBits based on a boolean.
932 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000933 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000934 * @param enable if true enable stateBits, otherwise disable
935 */
936 void setState(uint32_t stateBits, bool enable) {
937 if (enable) {
938 this->enableState(stateBits);
939 } else {
940 this->disableState(stateBits);
941 }
942 }
943
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000944 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000945 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000946 }
947
948 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000949 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000950 }
951
952 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000953 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000954 }
955
956 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000957 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000958 }
959
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000960 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000961 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000962 }
963
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000964 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000965 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000966 }
967
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000968 /// @}
969
970 ///////////////////////////////////////////////////////////////////////////
971 /// @name Face Culling
972 ////
973
974 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000975 kInvalid_DrawFace = -1,
976
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000977 kBoth_DrawFace,
978 kCCW_DrawFace,
979 kCW_DrawFace,
980 };
981
982 /**
983 * Controls whether clockwise, counterclockwise, or both faces are drawn.
984 * @param face the face(s) to draw.
985 */
986 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000987 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +0000988 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000989 }
990
991 /**
992 * Gets whether the target is drawing clockwise, counterclockwise,
993 * or both faces.
994 * @return the current draw face(s).
995 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000996 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000997
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000998 /// @}
999
1000 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001001
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001002 bool isStageEnabled(int s) const {
1003 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001004 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001005 }
1006
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001007 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001008 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001009 return false;
1010 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001011 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001012 bool enabled = this->isStageEnabled(i);
1013 if (enabled != s.isStageEnabled(i)) {
1014 return false;
1015 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001016 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001017 return false;
1018 }
1019 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001020 return true;
1021 }
1022 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1023
bsalomon@google.comca432082013-01-23 19:53:46 +00001024 GrDrawState& operator= (const GrDrawState& s) {
1025 this->setRenderTarget(s.fRenderTarget.get());
1026 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001027 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001028 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001029 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001030 }
1031 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001032 return *this;
1033 }
1034
1035private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001036
bsalomon@google.comca432082013-01-23 19:53:46 +00001037 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1038 struct CommonState {
1039 // These fields are roughly sorted by decreasing likelihood of being different in op==
robertphillips@google.com42903302013-04-20 12:26:07 +00001040 GrColor fColor;
1041 SkMatrix fViewMatrix;
1042 GrBlendCoeff fSrcBlend;
1043 GrBlendCoeff fDstBlend;
1044 GrColor fBlendConstant;
1045 uint32_t fFlagBits;
1046 const GrVertexAttrib* fVAPtr;
1047 int fVACount;
1048 GrStencilSettings fStencilSettings;
1049 int fFirstCoverageStage;
1050 GrColor fCoverage;
1051 SkXfermode::Mode fColorFilterMode;
1052 GrColor fColorFilterColor;
1053 DrawFace fDrawFace;
jvanverth@google.com054ae992013-04-01 20:06:51 +00001054
1055 // This is simply a different representation of info in fVertexAttribs and thus does
1056 // not need to be compared in op==.
1057 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
1058
bsalomon@google.comca432082013-01-23 19:53:46 +00001059 bool operator== (const CommonState& other) const {
jvanverth@google.com054ae992013-04-01 20:06:51 +00001060 bool result = fColor == other.fColor &&
1061 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1062 fSrcBlend == other.fSrcBlend &&
1063 fDstBlend == other.fDstBlend &&
1064 fBlendConstant == other.fBlendConstant &&
1065 fFlagBits == other.fFlagBits &&
robertphillips@google.com42903302013-04-20 12:26:07 +00001066 fVACount == other.fVACount &&
1067 !memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
jvanverth@google.com054ae992013-04-01 20:06:51 +00001068 fStencilSettings == other.fStencilSettings &&
1069 fFirstCoverageStage == other.fFirstCoverageStage &&
1070 fCoverage == other.fCoverage &&
1071 fColorFilterMode == other.fColorFilterMode &&
1072 fColorFilterColor == other.fColorFilterColor &&
1073 fDrawFace == other.fDrawFace;
1074 GrAssert(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
1075 other.fFixedFunctionVertexAttribIndices,
1076 sizeof(fFixedFunctionVertexAttribIndices)));
1077 return result;
bsalomon@google.comca432082013-01-23 19:53:46 +00001078 }
1079 bool operator!= (const CommonState& other) const { return !(*this == other); }
1080 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001081
bsalomon@google.comca432082013-01-23 19:53:46 +00001082 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1083 DeferredState must directly reference GrEffects, however. */
1084 struct SavedEffectStage {
1085 SavedEffectStage() : fEffect(NULL) {}
1086 const GrEffect* fEffect;
1087 GrEffectStage::SavedCoordChange fCoordChange;
1088 };
1089
1090public:
1091 /**
1092 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1093 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1094 * dispose mechanism returns them to the cache. This allows recycling resources through the
1095 * the cache while they are in a deferred draw queue.
1096 */
1097 class DeferredState {
1098 public:
1099 DeferredState() : fRenderTarget(NULL) {
1100 GR_DEBUGCODE(fInitialized = false;)
1101 }
1102 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1103 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1104
1105 void saveFrom(const GrDrawState& drawState) {
1106 fCommon = drawState.fCommon;
1107 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1108 fRenderTarget = drawState.fRenderTarget.get();
1109 SkSafeRef(fRenderTarget);
1110 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1111 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1112 // and recycle them to the cache (if no one else is holding a ref to the resources).
1113 for (int i = 0; i < kNumStages; ++i) {
1114 fStages[i].saveFrom(drawState.fStages[i]);
1115 }
1116 GR_DEBUGCODE(fInitialized = true;)
1117 }
1118
1119 void restoreTo(GrDrawState* drawState) {
1120 GrAssert(fInitialized);
1121 drawState->fCommon = fCommon;
1122 drawState->setRenderTarget(fRenderTarget);
1123 for (int i = 0; i < kNumStages; ++i) {
1124 fStages[i].restoreTo(&drawState->fStages[i]);
1125 }
1126 }
1127
1128 bool isEqual(const GrDrawState& state) const {
1129 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1130 return false;
1131 }
1132 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001133 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001134 return false;
1135 }
1136 }
1137 return true;
1138 }
1139
1140 private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001141 GrRenderTarget* fRenderTarget;
1142 CommonState fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001143 GrEffectStage::DeferredStage fStages[kNumStages];
bsalomon@google.comca432082013-01-23 19:53:46 +00001144
1145 GR_DEBUGCODE(bool fInitialized;)
1146 };
1147
1148private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001149
1150 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1151 CommonState fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001152 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001153
robertphillips@google.com42903302013-04-20 12:26:07 +00001154 /**
1155 * Sets vertex attributes for next draw.
1156 *
1157 * @param attribs the array of vertex attributes to set.
1158 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
1159 */
1160 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
1161
reed@google.comfa35e3d2012-06-26 20:16:17 +00001162 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001163};
1164
bsalomon@google.com2b446732013-02-12 16:47:41 +00001165GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1166
tomhudson@google.com93813632011-10-27 20:21:16 +00001167#endif