blob: de14763a0508fd71ca17c8587aca41b7b0618549 [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"
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +000012#include "GrBlend.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000013#include "GrColor.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000014#include "GrEffectStage.h"
bsalomon@google.com73818dc2013-03-28 13:23:29 +000015#include "GrPaint.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"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000024#include "SkTypes.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000025#include "SkXfermode.h"
26
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +000027class GrDrawState : public SkRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000028public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000029 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000030
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000031 GrDrawState() {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000032 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000033 this->reset();
34 }
tomhudson@google.com93813632011-10-27 20:21:16 +000035
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000036 GrDrawState(const SkMatrix& initialViewMatrix) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000037 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000038 this->reset(initialViewMatrix);
39 }
bsalomon@google.com137f1342013-05-29 21:27:53 +000040
41 /**
42 * Copies another draw state.
43 **/
commit-bot@chromium.orgfaa5ae42013-07-23 11:13:56 +000044 GrDrawState(const GrDrawState& state) : INHERITED() {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000045 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000046 *this = state;
47 }
48
bsalomon@google.com137f1342013-05-29 21:27:53 +000049 /**
50 * Copies another draw state with a preconcat to the view matrix.
51 **/
52 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000053 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com137f1342013-05-29 21:27:53 +000054 *this = state;
55 if (!preConcatMatrix.isIdentity()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000056 for (int i = 0; i < fColorStages.count(); ++i) {
57 fColorStages[i].localCoordChange(preConcatMatrix);
58 }
59 for (int i = 0; i < fCoverageStages.count(); ++i) {
60 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +000061 }
62 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000063 }
64
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000065 virtual ~GrDrawState() { SkASSERT(0 == fBlockEffectRemovalCnt); }
bsalomon@google.com137f1342013-05-29 21:27:53 +000066
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000067 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +000068 * Resets to the default state. GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000069 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000070 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000071
bsalomon@google.com137f1342013-05-29 21:27:53 +000072 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000073
74 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000075 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
76 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000077 * equivalents are set to default values. Clipping will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000078 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000079 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000080
81 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +000082 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +000083 ////
84
jvanverth@google.com9b855c72013-03-01 18:21:22 +000085 enum {
jvanverth@google.com054ae992013-04-01 20:06:51 +000086 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000087 };
88
jvanverth@google.com9b855c72013-03-01 18:21:22 +000089 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +000090 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
91 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
92 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000093 *
jvanverth@google.com054ae992013-04-01 20:06:51 +000094 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
95 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000096 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000097
jvanverth@google.com9b855c72013-03-01 18:21:22 +000098 /**
robertphillips@google.com42903302013-04-20 12:26:07 +000099 * Sets vertex attributes for next draw. The object driving the templatization
100 * should be a global GrVertexAttrib array that is never changed.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000101 */
robertphillips@google.com42903302013-04-20 12:26:07 +0000102 template <const GrVertexAttrib A[]> void setVertexAttribs(int count) {
103 this->setVertexAttribs(A, count);
104 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000105
bsalomon2ed5ef82014-07-07 08:44:05 -0700106 const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
107 int getVertexAttribCount() const { return fVACount; }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000108
109 size_t getVertexSize() const;
110
111 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000112 * Sets default vertex attributes for next draw. The default is a single attribute:
113 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000114 */
115 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000116
jvanverth@google.com054ae992013-04-01 20:06:51 +0000117 /**
118 * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
119 * binding does not appear in the current attribs. These bindings should appear only once in
120 * the attrib array.
121 */
122
123 int positionAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700124 return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000125 }
126 int localCoordAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700127 return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000128 }
129 int colorVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700130 return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000131 }
132 int coverageVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700133 return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000134 }
135
136 bool hasLocalCoordAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700137 return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000138 }
139 bool hasColorVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700140 return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000141 }
142 bool hasCoverageVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700143 return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000144 }
145
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000146 bool validateVertexAttribs() const;
147
jvanverth@google.comcc782382013-01-28 20:39:48 +0000148 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000149 * Helper to save/restore vertex attribs
150 */
151 class AutoVertexAttribRestore {
152 public:
153 AutoVertexAttribRestore(GrDrawState* drawState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000154 SkASSERT(NULL != drawState);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000155 fDrawState = drawState;
bsalomon2ed5ef82014-07-07 08:44:05 -0700156 fVAPtr = drawState->fVAPtr;
157 fVACount = drawState->fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000158 fDrawState->setDefaultVertexAttribs();
159 }
160
161 ~AutoVertexAttribRestore(){
commit-bot@chromium.orgfe070ba2013-10-16 14:43:12 +0000162 fDrawState->setVertexAttribs(fVAPtr, fVACount);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000163 }
164
165 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000166 GrDrawState* fDrawState;
167 const GrVertexAttrib* fVAPtr;
168 int fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000169 };
170
171 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000172 * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
173 * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
174 * nicer looking.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000175 */
176
177 /**
178 * Gets a pointer to a GrPoint of a vertex's position or texture
179 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000180 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000181 * @param vertexIndex the index of the vertex in the array
182 * @param vertexSize the size of each vertex in the array
183 * @param offset the offset in bytes of the vertex component.
184 * Defaults to zero (corresponding to vertex position)
185 * @return pointer to the vertex component as a GrPoint
186 */
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000187 static SkPoint* GetVertexPoint(void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000188 int vertexIndex,
189 int vertexSize,
190 int offset = 0) {
191 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000192 return GrTCast<SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000193 vertexIndex * vertexSize);
194 }
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000195 static const SkPoint* GetVertexPoint(const void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000196 int vertexIndex,
197 int vertexSize,
198 int offset = 0) {
199 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000200 return GrTCast<const SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000201 vertexIndex * vertexSize);
202 }
203
204 /**
205 * Gets a pointer to a GrColor inside a vertex within a vertex array.
206 * @param vertices the vetex array
207 * @param vertexIndex the index of the vertex in the array
208 * @param vertexSize the size of each vertex in the array
209 * @param offset the offset in bytes of the vertex color
210 * @return pointer to the vertex component as a GrColor
211 */
212 static GrColor* GetVertexColor(void* vertices,
213 int vertexIndex,
214 int vertexSize,
215 int offset) {
216 intptr_t start = GrTCast<intptr_t>(vertices);
217 return GrTCast<GrColor*>(start + offset +
218 vertexIndex * vertexSize);
219 }
220 static const GrColor* GetVertexColor(const void* vertices,
221 int vertexIndex,
222 int vertexSize,
223 int offset) {
224 const intptr_t start = GrTCast<intptr_t>(vertices);
225 return GrTCast<const GrColor*>(start + offset +
226 vertexIndex * vertexSize);
227 }
228
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000229 /// @}
230
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000231 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000232 * Determines whether src alpha is guaranteed to be one for all src pixels
233 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000234 bool srcAlphaWillBeOne() const;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000235
236 /**
237 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
238 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000239 bool hasSolidCoverage() const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000240
241 /// @}
242
243 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000244 /// @name Color
245 ////
246
247 /**
248 * Sets color for next draw to a premultiplied-alpha color.
249 *
250 * @param color the color to set.
251 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700252 void setColor(GrColor color) { fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000253
bsalomon2ed5ef82014-07-07 08:44:05 -0700254 GrColor getColor() const { return fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000255
256 /**
257 * Sets the color to be used for the next draw to be
258 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
259 *
260 * @param alpha The alpha value to set as the color.
261 */
262 void setAlpha(uint8_t a) {
263 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
264 }
265
266 /**
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000267 * Constructor sets the color to be 'color' which is undone by the destructor.
268 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000269 class AutoColorRestore : public ::SkNoncopyable {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000270 public:
sugoi@google.com66a58ac2013-03-05 20:40:52 +0000271 AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000272
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000273 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000274 fDrawState = NULL;
275 this->set(drawState, color);
276 }
277
278 void reset() {
279 if (NULL != fDrawState) {
280 fDrawState->setColor(fOldColor);
281 fDrawState = NULL;
282 }
283 }
284
285 void set(GrDrawState* drawState, GrColor color) {
286 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000287 fDrawState = drawState;
288 fOldColor = fDrawState->getColor();
289 fDrawState->setColor(color);
290 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000291
292 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000293 private:
294 GrDrawState* fDrawState;
295 GrColor fOldColor;
296 };
297
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000298 /// @}
299
300 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000301 /// @name Coverage
302 ////
303
304 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000305 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000306 * initial value (after construction or reset()) is 0xff. The constant
307 * coverage is ignored when per-vertex coverage is provided.
308 */
309 void setCoverage(uint8_t coverage) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700310 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000311 }
312
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000313 uint8_t getCoverage() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700314 return GrColorUnpackR(fCoverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000315 }
316
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000317 GrColor getCoverageColor() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700318 return fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000319 }
320
321 /// @}
322
323 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000324 /// @name Effect Stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000325 /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
326 /// shader. Its inputs are the output from the previous stage as well as some variables
327 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
328 /// the fragment position, local coordinates).
329 ///
330 /// The stages are divided into two sets, color-computing and coverage-computing. The final
331 /// color stage produces the final pixel color. The coverage-computing stages function exactly
332 /// as the color-computing but the output of the final coverage stage is treated as a fractional
333 /// pixel coverage rather than as input to the src/dst color blend step.
334 ///
335 /// The input color to the first color-stage is either the constant color or interpolated
336 /// per-vertex colors. The input to the first coverage stage is either a constant coverage
337 /// (usually full-coverage) or interpolated per-vertex coverage.
338 ///
339 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
340 /// the color / coverage distinction.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000341 ////
342
bsalomon97b9ab72014-07-08 06:52:35 -0700343 const GrEffect* addColorEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000344 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000345 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000346 return effect;
347 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000348
bsalomon97b9ab72014-07-08 06:52:35 -0700349 const GrEffect* addCoverageEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000350 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000351 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
bsalomon@google.comadc65362013-01-28 14:26:09 +0000352 return effect;
353 }
354
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000355 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000356 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000357 */
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000358 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700359 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000360 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000361
362 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700363 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000364 }
365
366 void addColorTextureEffect(GrTexture* texture,
367 const SkMatrix& matrix,
368 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700369 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000370 }
371
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000372 void addCoverageTextureEffect(GrTexture* texture,
373 const SkMatrix& matrix,
374 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700375 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000376 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000377
robertphillips@google.com972265d2012-06-13 18:49:30 +0000378 /**
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000379 * When this object is destroyed it will remove any effects from the draw state that were added
380 * after its constructor.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000381 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000382 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000383 public:
bsalomon@google.com2fad5a82013-06-13 19:47:23 +0000384 AutoRestoreEffects() : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000385
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000386 AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {
387 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000388 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000389
390 ~AutoRestoreEffects() { this->set(NULL); }
391
392 void set(GrDrawState* ds) {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000393 if (NULL != fDrawState) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000394 int n = fDrawState->fColorStages.count() - fColorEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000395 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000396 fDrawState->fColorStages.pop_back_n(n);
397 n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000398 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000399 fDrawState->fCoverageStages.pop_back_n(n);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000400 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000401 }
402 fDrawState = ds;
403 if (NULL != ds) {
404 fColorEffectCnt = ds->fColorStages.count();
405 fCoverageEffectCnt = ds->fCoverageStages.count();
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000406 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
robertphillips@google.com972265d2012-06-13 18:49:30 +0000407 }
408 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000409
bsalomon8af05232014-06-03 06:34:58 -0700410 bool isSet() const { return NULL != fDrawState; }
411
robertphillips@google.com972265d2012-06-13 18:49:30 +0000412 private:
413 GrDrawState* fDrawState;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000414 int fColorEffectCnt;
415 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000416 };
417
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000418 int numColorStages() const { return fColorStages.count(); }
419 int numCoverageStages() const { return fCoverageStages.count(); }
420 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000421
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000422 const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
423 const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000424
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000425 /**
426 * Checks whether any of the effects will read the dst pixel color.
427 */
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000428 bool willEffectReadDstColor() const;
reed@google.com67e7cde2013-03-20 17:47:16 +0000429
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000430 /// @}
431
432 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000433 /// @name Blending
434 ////
435
436 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000437 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000438 *
439 * The blend function will be:
440 * D' = sat(S*srcCoef + D*dstCoef)
441 *
442 * where D is the existing destination color, S is the incoming source
443 * color, and D' is the new destination color that will be written. sat()
444 * is the saturation function.
445 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000446 * @param srcCoef coefficient applied to the src color.
447 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000448 */
449 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700450 fSrcBlend = srcCoeff;
451 fDstBlend = dstCoeff;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000452 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000453 if (GrBlendCoeffRefsDst(dstCoeff)) {
454 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000455 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000456 if (GrBlendCoeffRefsSrc(srcCoeff)) {
457 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000458 }
459 #endif
460 }
461
bsalomon2ed5ef82014-07-07 08:44:05 -0700462 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
463 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000464
465 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
466 GrBlendCoeff* dstBlendCoeff) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700467 *srcBlendCoeff = fSrcBlend;
468 *dstBlendCoeff = fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000469 }
470
471 /**
472 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000473 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000474 * kConstC_GrBlendCoeff
475 * kIConstC_GrBlendCoeff
476 * kConstA_GrBlendCoeff
477 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000478 *
479 * @param constant the constant to set
480 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700481 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482
483 /**
484 * Retrieves the last value set by setBlendConstant()
485 * @return the blending constant value
486 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700487 GrColor getBlendConstant() const { return fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488
bsalomon@google.com2b446732013-02-12 16:47:41 +0000489 /**
490 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
491 * coverage before the blend will give the correct final destination color. In general it
492 * will not as coverage is applied after blending.
493 */
494 bool canTweakAlphaForCoverage() const;
495
496 /**
497 * Optimizations for blending / coverage to that can be applied based on the current state.
498 */
499 enum BlendOptFlags {
500 /**
501 * No optimization
502 */
503 kNone_BlendOpt = 0,
504 /**
505 * Don't draw at all
506 */
507 kSkipDraw_BlendOptFlag = 0x1,
508 /**
509 * Emit the src color, disable HW blending (replace dst with src)
510 */
511 kDisableBlend_BlendOptFlag = 0x2,
512 /**
513 * The coverage value does not have to be computed separately from alpha, the the output
514 * color can be the modulation of the two.
515 */
516 kCoverageAsAlpha_BlendOptFlag = 0x4,
517 /**
518 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
519 * "don't cares".
520 */
521 kEmitCoverage_BlendOptFlag = 0x8,
522 /**
523 * Emit transparent black instead of the src color, no need to compute coverage.
524 */
525 kEmitTransBlack_BlendOptFlag = 0x10,
526 };
527 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
528
529 /**
530 * Determines what optimizations can be applied based on the blend. The coefficients may have
531 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
532 * params that receive the tweaked coefficients. Normally the function looks at the current
533 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
534 * determine the blend optimizations that would be used if there was partial pixel coverage.
535 *
536 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
537 * playback) must call this function and respect the flags that replace the output color.
538 */
539 BlendOptFlags getBlendOpts(bool forceCoverage = false,
540 GrBlendCoeff* srcCoeff = NULL,
541 GrBlendCoeff* dstCoeff = NULL) const;
542
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543 /// @}
544
545 ///////////////////////////////////////////////////////////////////////////
546 /// @name View Matrix
547 ////
548
549 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000550 * Sets the view matrix to identity and updates any installed effects to compensate for the
551 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000552 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000553 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000554
555 /**
556 * Retrieves the current view matrix
557 * @return the current view matrix.
558 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700559 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000560
561 /**
562 * Retrieves the inverse of the current view matrix.
563 *
564 * If the current view matrix is invertible, return true, and if matrix
565 * is non-null, copy the inverse into it. If the current view matrix is
566 * non-invertible, return false and ignore the matrix parameter.
567 *
568 * @param matrix if not null, will receive a copy of the current inverse.
569 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000570 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000571 // TODO: determine whether we really need to leave matrix unmodified
572 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000573 SkMatrix inverse;
bsalomon2ed5ef82014-07-07 08:44:05 -0700574 if (fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000575 if (matrix) {
576 *matrix = inverse;
577 }
578 return true;
579 }
580 return false;
581 }
582
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000583 ////////////////////////////////////////////////////////////////////////////
584
585 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000586 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000587 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000588 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000589 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000590 public:
591 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000592
bsalomon@google.comc7818882013-03-20 19:19:53 +0000593 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000594 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000595 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000597
598 ~AutoViewMatrixRestore() { this->restore(); }
599
bsalomon@google.coma8347462012-10-08 18:59:39 +0000600 /**
601 * Can be called prior to destructor to restore the original matrix.
602 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000603 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000604
bsalomon@google.comc7818882013-03-20 19:19:53 +0000605 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000606
bsalomon@google.com137f1342013-05-29 21:27:53 +0000607 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
608 is not invertible. */
609 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000610
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000611 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000612 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
613
614 GrDrawState* fDrawState;
615 SkMatrix fViewMatrix;
616 int fNumColorStages;
617 SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000618 };
619
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000620 /// @}
621
622 ///////////////////////////////////////////////////////////////////////////
623 /// @name Render Target
624 ////
625
626 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000627 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000628 *
629 * @param target The render target to set.
630 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000631 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000632 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000633 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000634
635 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000636 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000637 *
638 * @return The currently set render target.
639 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000640 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
641 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000642
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000643 class AutoRenderTargetRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000644 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000645 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
647 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000648 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000649 this->set(ds, newTarget);
650 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000651 ~AutoRenderTargetRestore() { this->restore(); }
652
653 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 if (NULL != fDrawState) {
655 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000656 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000657 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000658 SkSafeSetNull(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000659 }
660
661 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
662 this->restore();
663
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000664 if (NULL != ds) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000665 SkASSERT(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000666 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000667 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000668 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000669 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000671 }
672 private:
673 GrDrawState* fDrawState;
674 GrRenderTarget* fSavedTarget;
675 };
676
677 /// @}
678
679 ///////////////////////////////////////////////////////////////////////////
680 /// @name Stencil
681 ////
682
683 /**
684 * Sets the stencil settings to use for the next draw.
685 * Changing the clip has the side-effect of possibly zeroing
686 * out the client settable stencil bits. So multipass algorithms
687 * using stencil should not change the clip between passes.
688 * @param settings the stencil settings to use.
689 */
690 void setStencil(const GrStencilSettings& settings) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700691 fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000692 }
693
694 /**
695 * Shortcut to disable stencil testing and ops.
696 */
697 void disableStencil() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700698 fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000699 }
700
bsalomon2ed5ef82014-07-07 08:44:05 -0700701 const GrStencilSettings& getStencil() const { return fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000702
bsalomon2ed5ef82014-07-07 08:44:05 -0700703 GrStencilSettings* stencil() { return &fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000704
705 /// @}
706
707 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000708 /// @name State Flags
709 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000710
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000711 /**
712 * Flags that affect rendering. Controlled using enable/disableState(). All
713 * default to disabled.
714 */
715 enum StateBits {
716 /**
717 * Perform dithering. TODO: Re-evaluate whether we need this bit
718 */
719 kDither_StateBit = 0x01,
720 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000721 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
722 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
723 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000724 */
725 kHWAntialias_StateBit = 0x02,
726 /**
727 * Draws will respect the clip, otherwise the clip is ignored.
728 */
729 kClip_StateBit = 0x04,
730 /**
731 * Disables writing to the color buffer. Useful when performing stencil
732 * operations.
733 */
734 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000735
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000736 /**
737 * Usually coverage is applied after color blending. The color is blended using the coeffs
738 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
739 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
740 * this case there is no distinction between coverage and color and the caller needs direct
741 * control over the blend coeffs. When set, there will be a single blend step controlled by
742 * setBlendFunc() which will use coverage*color as the src color.
743 */
744 kCoverageDrawing_StateBit = 0x10,
745
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 // Users of the class may add additional bits to the vector
747 kDummyStateBit,
748 kLastPublicStateBit = kDummyStateBit-1,
749 };
750
751 void resetStateFlags() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700752 fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000753 }
754
755 /**
756 * Enable render state settings.
757 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000758 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000759 */
760 void enableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700761 fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762 }
763
764 /**
765 * Disable render state settings.
766 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000767 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000768 */
769 void disableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700770 fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000771 }
772
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000773 /**
774 * Enable or disable stateBits based on a boolean.
775 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000776 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000777 * @param enable if true enable stateBits, otherwise disable
778 */
779 void setState(uint32_t stateBits, bool enable) {
780 if (enable) {
781 this->enableState(stateBits);
782 } else {
783 this->disableState(stateBits);
784 }
785 }
786
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000787 bool isDitherState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700788 return 0 != (fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000789 }
790
791 bool isHWAntialiasState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700792 return 0 != (fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000793 }
794
795 bool isClipState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700796 return 0 != (fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000797 }
798
799 bool isColorWriteDisabled() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700800 return 0 != (fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000801 }
802
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000803 bool isCoverageDrawing() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700804 return 0 != (fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000805 }
806
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000807 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700808 return 0 != (stateBit & fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000809 }
810
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000811 /// @}
812
813 ///////////////////////////////////////////////////////////////////////////
814 /// @name Face Culling
815 ////
816
817 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000818 kInvalid_DrawFace = -1,
819
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000820 kBoth_DrawFace,
821 kCCW_DrawFace,
822 kCW_DrawFace,
823 };
824
825 /**
826 * Controls whether clockwise, counterclockwise, or both faces are drawn.
827 * @param face the face(s) to draw.
828 */
829 void setDrawFace(DrawFace face) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000830 SkASSERT(kInvalid_DrawFace != face);
bsalomon2ed5ef82014-07-07 08:44:05 -0700831 fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000832 }
833
834 /**
835 * Gets whether the target is drawing clockwise, counterclockwise,
836 * or both faces.
837 * @return the current draw face(s).
838 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700839 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000840
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 /// @}
842
843 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000844
bsalomon2ed5ef82014-07-07 08:44:05 -0700845 bool operator ==(const GrDrawState& that) const {
846 if (fRenderTarget.get() != that.fRenderTarget.get() ||
847 fColorStages.count() != that.fColorStages.count() ||
848 fCoverageStages.count() != that.fCoverageStages.count() ||
849 fColor != that.fColor ||
850 !fViewMatrix.cheapEqualTo(that.fViewMatrix) ||
851 fSrcBlend != that.fSrcBlend ||
852 fDstBlend != that.fDstBlend ||
853 fBlendConstant != that.fBlendConstant ||
854 fFlagBits != that.fFlagBits ||
855 fVACount != that.fVACount ||
856 memcmp(fVAPtr, that.fVAPtr, fVACount * sizeof(GrVertexAttrib)) ||
857 fStencilSettings != that.fStencilSettings ||
858 fCoverage != that.fCoverage ||
859 fDrawFace != that.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000860 return false;
861 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000862 for (int i = 0; i < fColorStages.count(); i++) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700863 if (fColorStages[i] != that.fColorStages[i]) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000864 return false;
865 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000866 }
867 for (int i = 0; i < fCoverageStages.count(); i++) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700868 if (fCoverageStages[i] != that.fCoverageStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000869 return false;
870 }
871 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700872 SkASSERT(0 == memcmp(fFixedFunctionVertexAttribIndices,
873 that.fFixedFunctionVertexAttribIndices,
874 sizeof(fFixedFunctionVertexAttribIndices)));
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000875 return true;
876 }
877 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
878
bsalomon2ed5ef82014-07-07 08:44:05 -0700879 GrDrawState& operator= (const GrDrawState& that) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000880 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2ed5ef82014-07-07 08:44:05 -0700881 this->setRenderTarget(that.fRenderTarget.get());
882 fColor = that.fColor;
883 fViewMatrix = that.fViewMatrix;
884 fSrcBlend = that.fSrcBlend;
885 fDstBlend = that.fDstBlend;
886 fBlendConstant = that.fBlendConstant;
887 fFlagBits = that.fFlagBits;
888 fVACount = that.fVACount;
889 fVAPtr = that.fVAPtr;
890 fStencilSettings = that.fStencilSettings;
891 fCoverage = that.fCoverage;
892 fDrawFace = that.fDrawFace;
893 fColorStages = that.fColorStages;
894 fCoverageStages = that.fCoverageStages;
895
896 memcpy(fFixedFunctionVertexAttribIndices,
897 that.fFixedFunctionVertexAttribIndices,
898 sizeof(fFixedFunctionVertexAttribIndices));
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000899 return *this;
900 }
901
902private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000903
bsalomon@google.com137f1342013-05-29 21:27:53 +0000904 void onReset(const SkMatrix* initialViewMatrix) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000905 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000906 fColorStages.reset();
907 fCoverageStages.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000908
909 fRenderTarget.reset(NULL);
910
911 this->setDefaultVertexAttribs();
912
bsalomon2ed5ef82014-07-07 08:44:05 -0700913 fColor = 0xffffffff;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000914 if (NULL == initialViewMatrix) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700915 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000916 } else {
bsalomon2ed5ef82014-07-07 08:44:05 -0700917 fViewMatrix = *initialViewMatrix;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000918 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700919 fSrcBlend = kOne_GrBlendCoeff;
920 fDstBlend = kZero_GrBlendCoeff;
921 fBlendConstant = 0x0;
922 fFlagBits = 0x0;
923 fStencilSettings.setDisabled();
924 fCoverage = 0xffffffff;
925 fDrawFace = kBoth_DrawFace;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000926 }
927
jvanverth@google.com054ae992013-04-01 20:06:51 +0000928
bsalomon2ed5ef82014-07-07 08:44:05 -0700929 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000930 SkAutoTUnref<GrRenderTarget> fRenderTarget;
bsalomon2ed5ef82014-07-07 08:44:05 -0700931 GrColor fColor;
932 SkMatrix fViewMatrix;
933 GrBlendCoeff fSrcBlend;
934 GrBlendCoeff fDstBlend;
935 GrColor fBlendConstant;
936 uint32_t fFlagBits;
937 const GrVertexAttrib* fVAPtr;
938 int fVACount;
939 GrStencilSettings fStencilSettings;
940 GrColor fCoverage;
941 DrawFace fDrawFace;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000942
943 typedef SkSTArray<4, GrEffectStage> EffectStageArray;
944 EffectStageArray fColorStages;
945 EffectStageArray fCoverageStages;
946
bsalomon2ed5ef82014-07-07 08:44:05 -0700947 // This is simply a different representation of info in fVertexAttribs and thus does
948 // not need to be compared in op==.
949 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
950
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000951 // Some of the auto restore objects assume that no effects are removed during their lifetime.
952 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000953 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000954
robertphillips@google.com42903302013-04-20 12:26:07 +0000955 /**
956 * Sets vertex attributes for next draw.
957 *
958 * @param attribs the array of vertex attributes to set.
959 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
960 */
961 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
962
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000963 typedef SkRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000964};
965
bsalomon@google.com2b446732013-02-12 16:47:41 +0000966GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
967
tomhudson@google.com93813632011-10-27 20:21:16 +0000968#endif