blob: a4db89d643d95acb4d77cc02eecf06c0dfda93d9 [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 }
egdaniel9514d242014-07-18 06:15:43 -070062 this->invalidateBlendOptFlags();
bsalomon@google.com137f1342013-05-29 21:27:53 +000063 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000064 }
65
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000066 virtual ~GrDrawState() { SkASSERT(0 == fBlockEffectRemovalCnt); }
bsalomon@google.com137f1342013-05-29 21:27:53 +000067
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000068 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +000069 * Resets to the default state. GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000070 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000071 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000072
bsalomon@google.com137f1342013-05-29 21:27:53 +000073 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000074
75 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000076 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
77 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000078 * equivalents are set to default values. Clipping will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000079 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000080 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000081
82 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +000083 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +000084 ////
85
jvanverth@google.com9b855c72013-03-01 18:21:22 +000086 enum {
jvanverth@google.com054ae992013-04-01 20:06:51 +000087 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000088 };
89
jvanverth@google.com9b855c72013-03-01 18:21:22 +000090 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +000091 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
92 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
93 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000094 *
jvanverth@google.com054ae992013-04-01 20:06:51 +000095 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
96 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000097 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000098
jvanverth@google.com9b855c72013-03-01 18:21:22 +000099 /**
robertphillips@google.com42903302013-04-20 12:26:07 +0000100 * Sets vertex attributes for next draw. The object driving the templatization
101 * should be a global GrVertexAttrib array that is never changed.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000102 */
robertphillips@google.com42903302013-04-20 12:26:07 +0000103 template <const GrVertexAttrib A[]> void setVertexAttribs(int count) {
104 this->setVertexAttribs(A, count);
105 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000106
bsalomon2ed5ef82014-07-07 08:44:05 -0700107 const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
108 int getVertexAttribCount() const { return fVACount; }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000109
110 size_t getVertexSize() const;
111
112 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000113 * Sets default vertex attributes for next draw. The default is a single attribute:
114 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000115 */
116 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000117
jvanverth@google.com054ae992013-04-01 20:06:51 +0000118 /**
119 * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
120 * binding does not appear in the current attribs. These bindings should appear only once in
121 * the attrib array.
122 */
123
124 int positionAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700125 return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000126 }
127 int localCoordAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700128 return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000129 }
130 int colorVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700131 return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000132 }
133 int coverageVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700134 return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000135 }
136
137 bool hasLocalCoordAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700138 return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000139 }
140 bool hasColorVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700141 return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000142 }
143 bool hasCoverageVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700144 return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000145 }
146
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000147 bool validateVertexAttribs() const;
148
jvanverth@google.comcc782382013-01-28 20:39:48 +0000149 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000150 * Helper to save/restore vertex attribs
151 */
152 class AutoVertexAttribRestore {
153 public:
154 AutoVertexAttribRestore(GrDrawState* drawState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000155 SkASSERT(NULL != drawState);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000156 fDrawState = drawState;
bsalomon2ed5ef82014-07-07 08:44:05 -0700157 fVAPtr = drawState->fVAPtr;
158 fVACount = drawState->fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000159 fDrawState->setDefaultVertexAttribs();
160 }
161
162 ~AutoVertexAttribRestore(){
commit-bot@chromium.orgfe070ba2013-10-16 14:43:12 +0000163 fDrawState->setVertexAttribs(fVAPtr, fVACount);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000164 }
165
166 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000167 GrDrawState* fDrawState;
168 const GrVertexAttrib* fVAPtr;
169 int fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000170 };
171
172 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000173 * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
174 * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
175 * nicer looking.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000176 */
177
178 /**
179 * Gets a pointer to a GrPoint of a vertex's position or texture
180 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000181 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000182 * @param vertexIndex the index of the vertex in the array
183 * @param vertexSize the size of each vertex in the array
184 * @param offset the offset in bytes of the vertex component.
185 * Defaults to zero (corresponding to vertex position)
186 * @return pointer to the vertex component as a GrPoint
187 */
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000188 static SkPoint* GetVertexPoint(void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000189 int vertexIndex,
190 int vertexSize,
191 int offset = 0) {
192 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000193 return GrTCast<SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000194 vertexIndex * vertexSize);
195 }
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000196 static const SkPoint* GetVertexPoint(const void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000197 int vertexIndex,
198 int vertexSize,
199 int offset = 0) {
200 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000201 return GrTCast<const SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000202 vertexIndex * vertexSize);
203 }
204
205 /**
206 * Gets a pointer to a GrColor inside a vertex within a vertex array.
207 * @param vertices the vetex array
208 * @param vertexIndex the index of the vertex in the array
209 * @param vertexSize the size of each vertex in the array
210 * @param offset the offset in bytes of the vertex color
211 * @return pointer to the vertex component as a GrColor
212 */
213 static GrColor* GetVertexColor(void* vertices,
214 int vertexIndex,
215 int vertexSize,
216 int offset) {
217 intptr_t start = GrTCast<intptr_t>(vertices);
218 return GrTCast<GrColor*>(start + offset +
219 vertexIndex * vertexSize);
220 }
221 static const GrColor* GetVertexColor(const void* vertices,
222 int vertexIndex,
223 int vertexSize,
224 int offset) {
225 const intptr_t start = GrTCast<intptr_t>(vertices);
226 return GrTCast<const GrColor*>(start + offset +
227 vertexIndex * vertexSize);
228 }
229
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000230 /// @}
231
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000232 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000233 * Determines whether src alpha is guaranteed to be one for all src pixels
234 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000235 bool srcAlphaWillBeOne() const;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000236
237 /**
238 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
239 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000240 bool hasSolidCoverage() const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000241
242 /// @}
243
244 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000245 /// @name Color
246 ////
247
248 /**
249 * Sets color for next draw to a premultiplied-alpha color.
250 *
251 * @param color the color to set.
252 */
egdaniel9514d242014-07-18 06:15:43 -0700253 void setColor(GrColor color) {
254 fColor = color;
255 this->invalidateBlendOptFlags();
256 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000257
bsalomon2ed5ef82014-07-07 08:44:05 -0700258 GrColor getColor() const { return fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000259
260 /**
261 * Sets the color to be used for the next draw to be
262 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
263 *
264 * @param alpha The alpha value to set as the color.
265 */
266 void setAlpha(uint8_t a) {
267 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
268 }
269
270 /**
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000271 * Constructor sets the color to be 'color' which is undone by the destructor.
272 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000273 class AutoColorRestore : public ::SkNoncopyable {
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000274 public:
sugoi@google.com66a58ac2013-03-05 20:40:52 +0000275 AutoColorRestore() : fDrawState(NULL), fOldColor(0) {}
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000276
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000277 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000278 fDrawState = NULL;
279 this->set(drawState, color);
280 }
281
282 void reset() {
283 if (NULL != fDrawState) {
284 fDrawState->setColor(fOldColor);
285 fDrawState = NULL;
286 }
287 }
288
289 void set(GrDrawState* drawState, GrColor color) {
290 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000291 fDrawState = drawState;
292 fOldColor = fDrawState->getColor();
293 fDrawState->setColor(color);
294 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000295
296 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000297 private:
298 GrDrawState* fDrawState;
299 GrColor fOldColor;
300 };
301
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000302 /// @}
303
304 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000305 /// @name Coverage
306 ////
307
308 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000309 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000310 * initial value (after construction or reset()) is 0xff. The constant
311 * coverage is ignored when per-vertex coverage is provided.
312 */
313 void setCoverage(uint8_t coverage) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700314 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
egdaniel9514d242014-07-18 06:15:43 -0700315 this->invalidateBlendOptFlags();
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000316 }
317
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000318 uint8_t getCoverage() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700319 return GrColorUnpackR(fCoverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000320 }
321
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000322 GrColor getCoverageColor() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700323 return fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000324 }
325
326 /// @}
327
328 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000329 /// @name Effect Stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000330 /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
331 /// shader. Its inputs are the output from the previous stage as well as some variables
332 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
333 /// the fragment position, local coordinates).
334 ///
335 /// The stages are divided into two sets, color-computing and coverage-computing. The final
336 /// color stage produces the final pixel color. The coverage-computing stages function exactly
337 /// as the color-computing but the output of the final coverage stage is treated as a fractional
338 /// pixel coverage rather than as input to the src/dst color blend step.
339 ///
340 /// The input color to the first color-stage is either the constant color or interpolated
341 /// per-vertex colors. The input to the first coverage stage is either a constant coverage
342 /// (usually full-coverage) or interpolated per-vertex coverage.
343 ///
344 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
345 /// the color / coverage distinction.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000346 ////
347
bsalomon97b9ab72014-07-08 06:52:35 -0700348 const GrEffect* addColorEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000349 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000350 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
egdaniel9514d242014-07-18 06:15:43 -0700351 this->invalidateBlendOptFlags();
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000352 return effect;
353 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000354
bsalomon97b9ab72014-07-08 06:52:35 -0700355 const GrEffect* addCoverageEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000356 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000357 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
egdaniel9514d242014-07-18 06:15:43 -0700358 this->invalidateBlendOptFlags();
bsalomon@google.comadc65362013-01-28 14:26:09 +0000359 return effect;
360 }
361
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000362 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000363 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000364 */
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000365 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700366 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000367 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000368
369 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700370 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000371 }
372
373 void addColorTextureEffect(GrTexture* texture,
374 const SkMatrix& matrix,
375 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700376 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000377 }
378
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000379 void addCoverageTextureEffect(GrTexture* texture,
380 const SkMatrix& matrix,
381 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700382 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000383 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000384
robertphillips@google.com972265d2012-06-13 18:49:30 +0000385 /**
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000386 * When this object is destroyed it will remove any effects from the draw state that were added
387 * after its constructor.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000388 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000389 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000390 public:
bsalomon@google.com2fad5a82013-06-13 19:47:23 +0000391 AutoRestoreEffects() : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000392
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000393 AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {
394 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000395 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000396
397 ~AutoRestoreEffects() { this->set(NULL); }
398
399 void set(GrDrawState* ds) {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000400 if (NULL != fDrawState) {
egdaniel9514d242014-07-18 06:15:43 -0700401 int m = fDrawState->fColorStages.count() - fColorEffectCnt;
402 SkASSERT(m >= 0);
403 fDrawState->fColorStages.pop_back_n(m);
404
405 int n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000406 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000407 fDrawState->fCoverageStages.pop_back_n(n);
egdaniel9514d242014-07-18 06:15:43 -0700408 if (m + n > 0) {
409 fDrawState->invalidateBlendOptFlags();
410 }
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000411 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000412 }
413 fDrawState = ds;
414 if (NULL != ds) {
415 fColorEffectCnt = ds->fColorStages.count();
416 fCoverageEffectCnt = ds->fCoverageStages.count();
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000417 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
robertphillips@google.com972265d2012-06-13 18:49:30 +0000418 }
419 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000420
bsalomon8af05232014-06-03 06:34:58 -0700421 bool isSet() const { return NULL != fDrawState; }
422
robertphillips@google.com972265d2012-06-13 18:49:30 +0000423 private:
424 GrDrawState* fDrawState;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000425 int fColorEffectCnt;
426 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000427 };
428
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000429 int numColorStages() const { return fColorStages.count(); }
430 int numCoverageStages() const { return fCoverageStages.count(); }
431 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000432
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000433 const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
434 const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000435
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000436 /**
437 * Checks whether any of the effects will read the dst pixel color.
438 */
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000439 bool willEffectReadDstColor() const;
reed@google.com67e7cde2013-03-20 17:47:16 +0000440
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000441 /// @}
442
443 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000444 /// @name Blending
445 ////
446
447 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000448 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000449 *
450 * The blend function will be:
451 * D' = sat(S*srcCoef + D*dstCoef)
452 *
453 * where D is the existing destination color, S is the incoming source
454 * color, and D' is the new destination color that will be written. sat()
455 * is the saturation function.
456 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000457 * @param srcCoef coefficient applied to the src color.
458 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000459 */
460 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700461 fSrcBlend = srcCoeff;
462 fDstBlend = dstCoeff;
egdaniel9514d242014-07-18 06:15:43 -0700463 this->invalidateBlendOptFlags();
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000464 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000465 if (GrBlendCoeffRefsDst(dstCoeff)) {
466 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000467 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000468 if (GrBlendCoeffRefsSrc(srcCoeff)) {
469 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000470 }
471 #endif
472 }
473
bsalomon2ed5ef82014-07-07 08:44:05 -0700474 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
475 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000476
477 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
478 GrBlendCoeff* dstBlendCoeff) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700479 *srcBlendCoeff = fSrcBlend;
480 *dstBlendCoeff = fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 }
482
483 /**
484 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000485 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000486 * kConstC_GrBlendCoeff
487 * kIConstC_GrBlendCoeff
488 * kConstA_GrBlendCoeff
489 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000490 *
491 * @param constant the constant to set
492 */
egdaniel9514d242014-07-18 06:15:43 -0700493 void setBlendConstant(GrColor constant) {
494 fBlendConstant = constant;
495 this->invalidateBlendOptFlags();
496 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000497
498 /**
499 * Retrieves the last value set by setBlendConstant()
500 * @return the blending constant value
501 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700502 GrColor getBlendConstant() const { return fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000503
bsalomon@google.com2b446732013-02-12 16:47:41 +0000504 /**
505 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
506 * coverage before the blend will give the correct final destination color. In general it
507 * will not as coverage is applied after blending.
508 */
509 bool canTweakAlphaForCoverage() const;
510
511 /**
512 * Optimizations for blending / coverage to that can be applied based on the current state.
513 */
514 enum BlendOptFlags {
515 /**
516 * No optimization
517 */
518 kNone_BlendOpt = 0,
519 /**
520 * Don't draw at all
521 */
522 kSkipDraw_BlendOptFlag = 0x1,
523 /**
bsalomon@google.com2b446732013-02-12 16:47:41 +0000524 * The coverage value does not have to be computed separately from alpha, the the output
525 * color can be the modulation of the two.
526 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700527 kCoverageAsAlpha_BlendOptFlag = 0x2,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000528 /**
529 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
530 * "don't cares".
531 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700532 kEmitCoverage_BlendOptFlag = 0x4,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000533 /**
534 * Emit transparent black instead of the src color, no need to compute coverage.
535 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700536 kEmitTransBlack_BlendOptFlag = 0x8,
egdaniel9514d242014-07-18 06:15:43 -0700537 /**
538 * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by
539 * the get BlendOpts function.
540 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700541 kInvalid_BlendOptFlag = 1 << 31,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000542 };
543 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
544
egdaniel9514d242014-07-18 06:15:43 -0700545 void invalidateBlendOptFlags() {
546 fBlendOptFlags = kInvalid_BlendOptFlag;
547 }
548
bsalomon@google.com2b446732013-02-12 16:47:41 +0000549 /**
egdaniel02cafcc2014-07-21 11:37:28 -0700550 * We don't use suplied vertex color attributes if our blend mode is EmitCoverage or
551 * EmitTransBlack
552 */
553 bool canIgnoreColorAttribute() const;
554
555 /**
bsalomon@google.com2b446732013-02-12 16:47:41 +0000556 * Determines what optimizations can be applied based on the blend. The coefficients may have
557 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
558 * params that receive the tweaked coefficients. Normally the function looks at the current
559 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
560 * determine the blend optimizations that would be used if there was partial pixel coverage.
561 *
562 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
563 * playback) must call this function and respect the flags that replace the output color.
egdaniel9514d242014-07-18 06:15:43 -0700564 *
565 * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
566 * simply returned the cached flags and coefficients. Otherwise it will calculate the values.
bsalomon@google.com2b446732013-02-12 16:47:41 +0000567 */
568 BlendOptFlags getBlendOpts(bool forceCoverage = false,
569 GrBlendCoeff* srcCoeff = NULL,
570 GrBlendCoeff* dstCoeff = NULL) const;
571
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000572 /// @}
573
574 ///////////////////////////////////////////////////////////////////////////
575 /// @name View Matrix
576 ////
577
578 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000579 * Sets the view matrix to identity and updates any installed effects to compensate for the
580 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000581 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000582 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000583
584 /**
585 * Retrieves the current view matrix
586 * @return the current view matrix.
587 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700588 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000589
590 /**
591 * Retrieves the inverse of the current view matrix.
592 *
593 * If the current view matrix is invertible, return true, and if matrix
594 * is non-null, copy the inverse into it. If the current view matrix is
595 * non-invertible, return false and ignore the matrix parameter.
596 *
597 * @param matrix if not null, will receive a copy of the current inverse.
598 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000599 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 // TODO: determine whether we really need to leave matrix unmodified
601 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000602 SkMatrix inverse;
bsalomon2ed5ef82014-07-07 08:44:05 -0700603 if (fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000604 if (matrix) {
605 *matrix = inverse;
606 }
607 return true;
608 }
609 return false;
610 }
611
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000612 ////////////////////////////////////////////////////////////////////////////
613
614 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000615 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000616 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000617 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000618 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000619 public:
620 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000621
bsalomon@google.comc7818882013-03-20 19:19:53 +0000622 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000623 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000624 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000625 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000626
627 ~AutoViewMatrixRestore() { this->restore(); }
628
bsalomon@google.coma8347462012-10-08 18:59:39 +0000629 /**
630 * Can be called prior to destructor to restore the original matrix.
631 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000632 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000633
bsalomon@google.comc7818882013-03-20 19:19:53 +0000634 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000635
bsalomon@google.com137f1342013-05-29 21:27:53 +0000636 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
637 is not invertible. */
638 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000639
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000640 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000641 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
642
643 GrDrawState* fDrawState;
644 SkMatrix fViewMatrix;
645 int fNumColorStages;
646 SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000647 };
648
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000649 /// @}
650
651 ///////////////////////////////////////////////////////////////////////////
652 /// @name Render Target
653 ////
654
655 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000656 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000657 *
658 * @param target The render target to set.
659 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000660 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000661 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000662 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000663
664 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000665 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000666 *
667 * @return The currently set render target.
668 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000669 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
670 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000671
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000672 class AutoRenderTargetRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000673 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000674 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
676 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000677 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000678 this->set(ds, newTarget);
679 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000680 ~AutoRenderTargetRestore() { this->restore(); }
681
682 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000683 if (NULL != fDrawState) {
684 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000685 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000686 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000687 SkSafeSetNull(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000688 }
689
690 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
691 this->restore();
692
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000693 if (NULL != ds) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000694 SkASSERT(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000695 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000696 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000697 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000698 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000699 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000700 }
701 private:
702 GrDrawState* fDrawState;
703 GrRenderTarget* fSavedTarget;
704 };
705
706 /// @}
707
708 ///////////////////////////////////////////////////////////////////////////
709 /// @name Stencil
710 ////
711
712 /**
713 * Sets the stencil settings to use for the next draw.
714 * Changing the clip has the side-effect of possibly zeroing
715 * out the client settable stencil bits. So multipass algorithms
716 * using stencil should not change the clip between passes.
717 * @param settings the stencil settings to use.
718 */
719 void setStencil(const GrStencilSettings& settings) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700720 fStencilSettings = settings;
egdaniel9514d242014-07-18 06:15:43 -0700721 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 }
723
724 /**
725 * Shortcut to disable stencil testing and ops.
726 */
727 void disableStencil() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700728 fStencilSettings.setDisabled();
egdaniel9514d242014-07-18 06:15:43 -0700729 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000730 }
731
bsalomon2ed5ef82014-07-07 08:44:05 -0700732 const GrStencilSettings& getStencil() const { return fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000733
bsalomon2ed5ef82014-07-07 08:44:05 -0700734 GrStencilSettings* stencil() { return &fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735
736 /// @}
737
738 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000739 /// @name State Flags
740 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000741
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000742 /**
743 * Flags that affect rendering. Controlled using enable/disableState(). All
744 * default to disabled.
745 */
746 enum StateBits {
747 /**
748 * Perform dithering. TODO: Re-evaluate whether we need this bit
749 */
750 kDither_StateBit = 0x01,
751 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000752 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
753 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
754 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755 */
756 kHWAntialias_StateBit = 0x02,
757 /**
758 * Draws will respect the clip, otherwise the clip is ignored.
759 */
760 kClip_StateBit = 0x04,
761 /**
762 * Disables writing to the color buffer. Useful when performing stencil
763 * operations.
764 */
765 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000766
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000767 /**
768 * Usually coverage is applied after color blending. The color is blended using the coeffs
769 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
770 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
771 * this case there is no distinction between coverage and color and the caller needs direct
772 * control over the blend coeffs. When set, there will be a single blend step controlled by
773 * setBlendFunc() which will use coverage*color as the src color.
774 */
775 kCoverageDrawing_StateBit = 0x10,
776
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000777 // Users of the class may add additional bits to the vector
778 kDummyStateBit,
779 kLastPublicStateBit = kDummyStateBit-1,
780 };
781
782 void resetStateFlags() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700783 fFlagBits = 0;
egdaniel9514d242014-07-18 06:15:43 -0700784 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000785 }
786
787 /**
788 * Enable render state settings.
789 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000790 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791 */
792 void enableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700793 fFlagBits |= stateBits;
egdaniel9514d242014-07-18 06:15:43 -0700794 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000795 }
796
797 /**
798 * Disable render state settings.
799 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000800 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000801 */
802 void disableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700803 fFlagBits &= ~(stateBits);
egdaniel9514d242014-07-18 06:15:43 -0700804 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000805 }
806
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000807 /**
808 * Enable or disable stateBits based on a boolean.
809 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000810 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000811 * @param enable if true enable stateBits, otherwise disable
812 */
813 void setState(uint32_t stateBits, bool enable) {
814 if (enable) {
815 this->enableState(stateBits);
816 } else {
817 this->disableState(stateBits);
818 }
819 }
820
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 bool isDitherState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700822 return 0 != (fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000823 }
824
825 bool isHWAntialiasState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700826 return 0 != (fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000827 }
828
829 bool isClipState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700830 return 0 != (fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000831 }
832
833 bool isColorWriteDisabled() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700834 return 0 != (fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000835 }
836
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000837 bool isCoverageDrawing() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700838 return 0 != (fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000839 }
840
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700842 return 0 != (stateBit & fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000843 }
844
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 /// @}
846
847 ///////////////////////////////////////////////////////////////////////////
848 /// @name Face Culling
849 ////
850
851 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000852 kInvalid_DrawFace = -1,
853
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000854 kBoth_DrawFace,
855 kCCW_DrawFace,
856 kCW_DrawFace,
857 };
858
859 /**
860 * Controls whether clockwise, counterclockwise, or both faces are drawn.
861 * @param face the face(s) to draw.
862 */
863 void setDrawFace(DrawFace face) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000864 SkASSERT(kInvalid_DrawFace != face);
bsalomon2ed5ef82014-07-07 08:44:05 -0700865 fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000866 }
867
868 /**
869 * Gets whether the target is drawing clockwise, counterclockwise,
870 * or both faces.
871 * @return the current draw face(s).
872 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700873 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000874
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000875 /// @}
876
877 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000878
bsalomon838f62d2014-08-05 07:15:57 -0700879 /** Return type for CombineIfPossible. */
880 enum CombinedState {
881 /** The GrDrawStates cannot be combined. */
882 kIncompatible_CombinedState,
883 /** Either draw state can be used in place of the other. */
884 kAOrB_CombinedState,
885 /** Use the first draw state. */
886 kA_CombinedState,
887 /** Use the second draw state. */
888 kB_CombinedState,
889 };
890
891 /** This function determines whether the GrDrawStates used for two draws can be combined into
892 a single GrDrawState. This is used to avoid storing redundant GrDrawStates and to determine
893 if draws can be batched. The return value indicates whether combining is possible and, if
894 so, which of the two inputs should be used. */
895 static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b) {
896 if (a.fRenderTarget.get() != b.fRenderTarget.get() ||
897 a.fColorStages.count() != b.fColorStages.count() ||
898 a.fCoverageStages.count() != b.fCoverageStages.count() ||
899 a.fColor != b.fColor ||
900 !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) ||
901 a.fSrcBlend != b.fSrcBlend ||
902 a.fDstBlend != b.fDstBlend ||
903 a.fBlendConstant != b.fBlendConstant ||
904 a.fFlagBits != b.fFlagBits ||
905 a.fVACount != b.fVACount ||
906 memcmp(a.fVAPtr, b.fVAPtr, a.fVACount * sizeof(GrVertexAttrib)) ||
907 a.fStencilSettings != b.fStencilSettings ||
908 a.fCoverage != b.fCoverage ||
909 a.fDrawFace != b.fDrawFace) {
910 return kIncompatible_CombinedState;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000911 }
bsalomon06736762014-08-04 10:56:39 -0700912
bsalomon838f62d2014-08-05 07:15:57 -0700913 bool explicitLocalCoords = a.hasLocalCoordAttribute();
914 for (int i = 0; i < a.fColorStages.count(); i++) {
915 if (!GrEffectStage::AreCompatible(a.fColorStages[i], b.fColorStages[i],
bsalomon06736762014-08-04 10:56:39 -0700916 explicitLocalCoords)) {
bsalomon838f62d2014-08-05 07:15:57 -0700917 return kIncompatible_CombinedState;
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000918 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000919 }
bsalomon838f62d2014-08-05 07:15:57 -0700920 for (int i = 0; i < a.fCoverageStages.count(); i++) {
921 if (!GrEffectStage::AreCompatible(a.fCoverageStages[i], b.fCoverageStages[i],
bsalomon06736762014-08-04 10:56:39 -0700922 explicitLocalCoords)) {
bsalomon838f62d2014-08-05 07:15:57 -0700923 return kIncompatible_CombinedState;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000924 }
925 }
bsalomon838f62d2014-08-05 07:15:57 -0700926 SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices,
927 b.fFixedFunctionVertexAttribIndices,
928 sizeof(a.fFixedFunctionVertexAttribIndices)));
929 return kAOrB_CombinedState;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000930 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000931
bsalomon2ed5ef82014-07-07 08:44:05 -0700932 GrDrawState& operator= (const GrDrawState& that) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000933 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2ed5ef82014-07-07 08:44:05 -0700934 this->setRenderTarget(that.fRenderTarget.get());
935 fColor = that.fColor;
936 fViewMatrix = that.fViewMatrix;
937 fSrcBlend = that.fSrcBlend;
938 fDstBlend = that.fDstBlend;
939 fBlendConstant = that.fBlendConstant;
940 fFlagBits = that.fFlagBits;
941 fVACount = that.fVACount;
942 fVAPtr = that.fVAPtr;
943 fStencilSettings = that.fStencilSettings;
944 fCoverage = that.fCoverage;
945 fDrawFace = that.fDrawFace;
946 fColorStages = that.fColorStages;
947 fCoverageStages = that.fCoverageStages;
egdaniel9514d242014-07-18 06:15:43 -0700948 fOptSrcBlend = that.fOptSrcBlend;
949 fOptDstBlend = that.fOptDstBlend;
950 fBlendOptFlags = that.fBlendOptFlags;
bsalomon2ed5ef82014-07-07 08:44:05 -0700951
952 memcpy(fFixedFunctionVertexAttribIndices,
953 that.fFixedFunctionVertexAttribIndices,
954 sizeof(fFixedFunctionVertexAttribIndices));
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000955 return *this;
956 }
957
958private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000959
bsalomon@google.com137f1342013-05-29 21:27:53 +0000960 void onReset(const SkMatrix* initialViewMatrix) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000961 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000962 fColorStages.reset();
963 fCoverageStages.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000964
965 fRenderTarget.reset(NULL);
966
967 this->setDefaultVertexAttribs();
968
bsalomon2ed5ef82014-07-07 08:44:05 -0700969 fColor = 0xffffffff;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000970 if (NULL == initialViewMatrix) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700971 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000972 } else {
bsalomon2ed5ef82014-07-07 08:44:05 -0700973 fViewMatrix = *initialViewMatrix;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000974 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700975 fSrcBlend = kOne_GrBlendCoeff;
976 fDstBlend = kZero_GrBlendCoeff;
977 fBlendConstant = 0x0;
978 fFlagBits = 0x0;
979 fStencilSettings.setDisabled();
980 fCoverage = 0xffffffff;
981 fDrawFace = kBoth_DrawFace;
egdaniel9514d242014-07-18 06:15:43 -0700982
983 this->invalidateBlendOptFlags();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000984 }
985
egdaniel9514d242014-07-18 06:15:43 -0700986 BlendOptFlags calcBlendOpts(bool forceCoverage = false,
987 GrBlendCoeff* srcCoeff = NULL,
988 GrBlendCoeff* dstCoeff = NULL) const;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000989
bsalomon2ed5ef82014-07-07 08:44:05 -0700990 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000991 SkAutoTUnref<GrRenderTarget> fRenderTarget;
bsalomon2ed5ef82014-07-07 08:44:05 -0700992 GrColor fColor;
993 SkMatrix fViewMatrix;
994 GrBlendCoeff fSrcBlend;
995 GrBlendCoeff fDstBlend;
996 GrColor fBlendConstant;
997 uint32_t fFlagBits;
998 const GrVertexAttrib* fVAPtr;
999 int fVACount;
1000 GrStencilSettings fStencilSettings;
1001 GrColor fCoverage;
1002 DrawFace fDrawFace;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001003
1004 typedef SkSTArray<4, GrEffectStage> EffectStageArray;
1005 EffectStageArray fColorStages;
1006 EffectStageArray fCoverageStages;
egdaniel9514d242014-07-18 06:15:43 -07001007
1008 mutable GrBlendCoeff fOptSrcBlend;
1009 mutable GrBlendCoeff fOptDstBlend;
1010 mutable BlendOptFlags fBlendOptFlags;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001011
bsalomon2ed5ef82014-07-07 08:44:05 -07001012 // This is simply a different representation of info in fVertexAttribs and thus does
1013 // not need to be compared in op==.
1014 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
1015
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001016 // Some of the auto restore objects assume that no effects are removed during their lifetime.
1017 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +00001018 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001019
robertphillips@google.com42903302013-04-20 12:26:07 +00001020 /**
1021 * Sets vertex attributes for next draw.
1022 *
1023 * @param attribs the array of vertex attributes to set.
1024 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
1025 */
1026 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
1027
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +00001028 typedef SkRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001029};
1030
bsalomon@google.com2b446732013-02-12 16:47:41 +00001031GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1032
tomhudson@google.com93813632011-10-27 20:21:16 +00001033#endif