blob: 6cefd9776134773a0b2136aadf2e8f03fe7bbb4e [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
robertphillips@google.com42903302013-04-20 12:26:07 +0000106 const GrVertexAttrib* getVertexAttribs() const { return fCommon.fVAPtr; }
107 int getVertexAttribCount() const { return fCommon.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 {
124 return fCommon.fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
125 }
126 int localCoordAttributeIndex() const {
127 return fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
128 }
129 int colorVertexAttributeIndex() const {
130 return fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
131 }
132 int coverageVertexAttributeIndex() const {
133 return fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
134 }
135
136 bool hasLocalCoordAttribute() const {
137 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
138 }
139 bool hasColorVertexAttribute() const {
140 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
141 }
142 bool hasCoverageVertexAttribute() const {
143 return -1 != fCommon.fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
144 }
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;
robertphillips@google.com42903302013-04-20 12:26:07 +0000156 fVAPtr = drawState->fCommon.fVAPtr;
157 fVACount = drawState->fCommon.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 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000252 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000253
bsalomon@google.comca432082013-01-23 19:53:46 +0000254 GrColor getColor() const { return fCommon.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) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000310 fCommon.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 {
314 return GrColorUnpackR(fCommon.fCoverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000315 }
316
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000317 GrColor getCoverageColor() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000318 return fCommon.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
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000343 const GrEffectRef* addColorEffect(const GrEffectRef* 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
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000349 const GrEffectRef* addCoverageEffect(const GrEffectRef* 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) {
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000359 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000360 this->addColorEffect(effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000361 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000362
363 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
364 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
365 this->addCoverageEffect(effect)->unref();
366 }
367
368 void addColorTextureEffect(GrTexture* texture,
369 const SkMatrix& matrix,
370 const GrTextureParams& params) {
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000371 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000372 this->addColorEffect(effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000373 }
374
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000375 void addCoverageTextureEffect(GrTexture* texture,
376 const SkMatrix& matrix,
377 const GrTextureParams& params) {
378 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
379 this->addCoverageEffect(effect)->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000380 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000381
robertphillips@google.com972265d2012-06-13 18:49:30 +0000382 /**
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000383 * When this object is destroyed it will remove any effects from the draw state that were added
384 * after its constructor.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000385 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000386 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000387 public:
bsalomon@google.com2fad5a82013-06-13 19:47:23 +0000388 AutoRestoreEffects() : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000389
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000390 AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {
391 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000392 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000393
394 ~AutoRestoreEffects() { this->set(NULL); }
395
396 void set(GrDrawState* ds) {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000397 if (NULL != fDrawState) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000398 int n = fDrawState->fColorStages.count() - fColorEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000399 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000400 fDrawState->fColorStages.pop_back_n(n);
401 n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000402 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000403 fDrawState->fCoverageStages.pop_back_n(n);
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000404 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000405 }
406 fDrawState = ds;
407 if (NULL != ds) {
408 fColorEffectCnt = ds->fColorStages.count();
409 fCoverageEffectCnt = ds->fCoverageStages.count();
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000410 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
robertphillips@google.com972265d2012-06-13 18:49:30 +0000411 }
412 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000413
bsalomon8af05232014-06-03 06:34:58 -0700414 bool isSet() const { return NULL != fDrawState; }
415
robertphillips@google.com972265d2012-06-13 18:49:30 +0000416 private:
417 GrDrawState* fDrawState;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000418 int fColorEffectCnt;
419 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000420 };
421
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000422 int numColorStages() const { return fColorStages.count(); }
423 int numCoverageStages() const { return fCoverageStages.count(); }
424 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000425
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000426 const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
427 const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000428
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000429 /**
430 * Checks whether any of the effects will read the dst pixel color.
431 */
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000432 bool willEffectReadDstColor() const;
reed@google.com67e7cde2013-03-20 17:47:16 +0000433
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000434 /// @}
435
436 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000437 /// @name Blending
438 ////
439
440 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000441 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000442 *
443 * The blend function will be:
444 * D' = sat(S*srcCoef + D*dstCoef)
445 *
446 * where D is the existing destination color, S is the incoming source
447 * color, and D' is the new destination color that will be written. sat()
448 * is the saturation function.
449 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000450 * @param srcCoef coefficient applied to the src color.
451 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000452 */
453 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000454 fCommon.fSrcBlend = srcCoeff;
455 fCommon.fDstBlend = dstCoeff;
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000456 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000457 if (GrBlendCoeffRefsDst(dstCoeff)) {
458 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000459 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000460 if (GrBlendCoeffRefsSrc(srcCoeff)) {
461 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000462 }
463 #endif
464 }
465
bsalomon@google.comca432082013-01-23 19:53:46 +0000466 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
467 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000468
469 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
470 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000471 *srcBlendCoeff = fCommon.fSrcBlend;
472 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000473 }
474
475 /**
476 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000477 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000478 * kConstC_GrBlendCoeff
479 * kIConstC_GrBlendCoeff
480 * kConstA_GrBlendCoeff
481 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482 *
483 * @param constant the constant to set
484 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000485 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000486
487 /**
488 * Retrieves the last value set by setBlendConstant()
489 * @return the blending constant value
490 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000491 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000492
bsalomon@google.com2b446732013-02-12 16:47:41 +0000493 /**
494 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
495 * coverage before the blend will give the correct final destination color. In general it
496 * will not as coverage is applied after blending.
497 */
498 bool canTweakAlphaForCoverage() const;
499
500 /**
501 * Optimizations for blending / coverage to that can be applied based on the current state.
502 */
503 enum BlendOptFlags {
504 /**
505 * No optimization
506 */
507 kNone_BlendOpt = 0,
508 /**
509 * Don't draw at all
510 */
511 kSkipDraw_BlendOptFlag = 0x1,
512 /**
513 * Emit the src color, disable HW blending (replace dst with src)
514 */
515 kDisableBlend_BlendOptFlag = 0x2,
516 /**
517 * The coverage value does not have to be computed separately from alpha, the the output
518 * color can be the modulation of the two.
519 */
520 kCoverageAsAlpha_BlendOptFlag = 0x4,
521 /**
522 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
523 * "don't cares".
524 */
525 kEmitCoverage_BlendOptFlag = 0x8,
526 /**
527 * Emit transparent black instead of the src color, no need to compute coverage.
528 */
529 kEmitTransBlack_BlendOptFlag = 0x10,
530 };
531 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
532
533 /**
534 * Determines what optimizations can be applied based on the blend. The coefficients may have
535 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
536 * params that receive the tweaked coefficients. Normally the function looks at the current
537 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
538 * determine the blend optimizations that would be used if there was partial pixel coverage.
539 *
540 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
541 * playback) must call this function and respect the flags that replace the output color.
542 */
543 BlendOptFlags getBlendOpts(bool forceCoverage = false,
544 GrBlendCoeff* srcCoeff = NULL,
545 GrBlendCoeff* dstCoeff = NULL) const;
546
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000547 /// @}
548
549 ///////////////////////////////////////////////////////////////////////////
550 /// @name View Matrix
551 ////
552
553 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000554 * Sets the view matrix to identity and updates any installed effects to compensate for the
555 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000556 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000557 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000558
559 /**
560 * Retrieves the current view matrix
561 * @return the current view matrix.
562 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000563 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000564
565 /**
566 * Retrieves the inverse of the current view matrix.
567 *
568 * If the current view matrix is invertible, return true, and if matrix
569 * is non-null, copy the inverse into it. If the current view matrix is
570 * non-invertible, return false and ignore the matrix parameter.
571 *
572 * @param matrix if not null, will receive a copy of the current inverse.
573 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000574 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000575 // TODO: determine whether we really need to leave matrix unmodified
576 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000577 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000578 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000579 if (matrix) {
580 *matrix = inverse;
581 }
582 return true;
583 }
584 return false;
585 }
586
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000587 ////////////////////////////////////////////////////////////////////////////
588
589 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000590 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000591 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000592 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000593 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000594 public:
595 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000596
bsalomon@google.comc7818882013-03-20 19:19:53 +0000597 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000598 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000599 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000601
602 ~AutoViewMatrixRestore() { this->restore(); }
603
bsalomon@google.coma8347462012-10-08 18:59:39 +0000604 /**
605 * Can be called prior to destructor to restore the original matrix.
606 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000607 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000608
bsalomon@google.comc7818882013-03-20 19:19:53 +0000609 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000610
bsalomon@google.com137f1342013-05-29 21:27:53 +0000611 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
612 is not invertible. */
613 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000614
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000615 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000616 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
617
618 GrDrawState* fDrawState;
619 SkMatrix fViewMatrix;
620 int fNumColorStages;
621 SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000622 };
623
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000624 /// @}
625
626 ///////////////////////////////////////////////////////////////////////////
627 /// @name Render Target
628 ////
629
630 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000631 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632 *
633 * @param target The render target to set.
634 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000635 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000636 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000637 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638
639 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000640 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641 *
642 * @return The currently set render target.
643 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000644 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
645 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000647 class AutoRenderTargetRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000648 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000649 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000650 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
651 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000652 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000653 this->set(ds, newTarget);
654 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000655 ~AutoRenderTargetRestore() { this->restore(); }
656
657 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000658 if (NULL != fDrawState) {
659 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000660 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000661 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000662 SkSafeSetNull(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000663 }
664
665 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
666 this->restore();
667
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000668 if (NULL != ds) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000669 SkASSERT(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000671 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000672 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000673 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000674 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675 }
676 private:
677 GrDrawState* fDrawState;
678 GrRenderTarget* fSavedTarget;
679 };
680
681 /// @}
682
683 ///////////////////////////////////////////////////////////////////////////
684 /// @name Stencil
685 ////
686
687 /**
688 * Sets the stencil settings to use for the next draw.
689 * Changing the clip has the side-effect of possibly zeroing
690 * out the client settable stencil bits. So multipass algorithms
691 * using stencil should not change the clip between passes.
692 * @param settings the stencil settings to use.
693 */
694 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000695 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696 }
697
698 /**
699 * Shortcut to disable stencil testing and ops.
700 */
701 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000702 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000703 }
704
bsalomon@google.comca432082013-01-23 19:53:46 +0000705 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706
bsalomon@google.comca432082013-01-23 19:53:46 +0000707 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000708
709 /// @}
710
711 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000712 /// @name State Flags
713 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000714
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000715 /**
716 * Flags that affect rendering. Controlled using enable/disableState(). All
717 * default to disabled.
718 */
719 enum StateBits {
720 /**
721 * Perform dithering. TODO: Re-evaluate whether we need this bit
722 */
723 kDither_StateBit = 0x01,
724 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000725 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
726 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
727 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000728 */
729 kHWAntialias_StateBit = 0x02,
730 /**
731 * Draws will respect the clip, otherwise the clip is ignored.
732 */
733 kClip_StateBit = 0x04,
734 /**
735 * Disables writing to the color buffer. Useful when performing stencil
736 * operations.
737 */
738 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000739
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000740 /**
741 * Usually coverage is applied after color blending. The color is blended using the coeffs
742 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
743 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
744 * this case there is no distinction between coverage and color and the caller needs direct
745 * control over the blend coeffs. When set, there will be a single blend step controlled by
746 * setBlendFunc() which will use coverage*color as the src color.
747 */
748 kCoverageDrawing_StateBit = 0x10,
749
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000750 // Users of the class may add additional bits to the vector
751 kDummyStateBit,
752 kLastPublicStateBit = kDummyStateBit-1,
753 };
754
755 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000756 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000757 }
758
759 /**
760 * Enable render state settings.
761 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000762 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000763 */
764 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000765 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000766 }
767
768 /**
769 * Disable render state settings.
770 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000771 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000772 */
773 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000774 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000775 }
776
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000777 /**
778 * Enable or disable stateBits based on a boolean.
779 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000780 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000781 * @param enable if true enable stateBits, otherwise disable
782 */
783 void setState(uint32_t stateBits, bool enable) {
784 if (enable) {
785 this->enableState(stateBits);
786 } else {
787 this->disableState(stateBits);
788 }
789 }
790
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000792 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000793 }
794
795 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000796 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000797 }
798
799 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000800 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000801 }
802
803 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000804 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000805 }
806
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000807 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000808 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000809 }
810
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000811 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000812 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000813 }
814
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000815 /// @}
816
817 ///////////////////////////////////////////////////////////////////////////
818 /// @name Face Culling
819 ////
820
821 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000822 kInvalid_DrawFace = -1,
823
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000824 kBoth_DrawFace,
825 kCCW_DrawFace,
826 kCW_DrawFace,
827 };
828
829 /**
830 * Controls whether clockwise, counterclockwise, or both faces are drawn.
831 * @param face the face(s) to draw.
832 */
833 void setDrawFace(DrawFace face) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000834 SkASSERT(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +0000835 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000836 }
837
838 /**
839 * Gets whether the target is drawing clockwise, counterclockwise,
840 * or both faces.
841 * @return the current draw face(s).
842 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000843 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000844
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 /// @}
846
847 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000848
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000849 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000850 if (fRenderTarget.get() != s.fRenderTarget.get() ||
851 fColorStages.count() != s.fColorStages.count() ||
852 fCoverageStages.count() != s.fCoverageStages.count() ||
853 fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000854 return false;
855 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000856 for (int i = 0; i < fColorStages.count(); i++) {
857 if (fColorStages[i] != s.fColorStages[i]) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000858 return false;
859 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000860 }
861 for (int i = 0; i < fCoverageStages.count(); i++) {
862 if (fCoverageStages[i] != s.fCoverageStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000863 return false;
864 }
865 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000866 return true;
867 }
868 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
869
bsalomon@google.comca432082013-01-23 19:53:46 +0000870 GrDrawState& operator= (const GrDrawState& s) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000871 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comca432082013-01-23 19:53:46 +0000872 this->setRenderTarget(s.fRenderTarget.get());
873 fCommon = s.fCommon;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000874 fColorStages = s.fColorStages;
875 fCoverageStages = s.fCoverageStages;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000876 return *this;
877 }
878
879private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000880
bsalomon@google.com137f1342013-05-29 21:27:53 +0000881 void onReset(const SkMatrix* initialViewMatrix) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000882 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000883 fColorStages.reset();
884 fCoverageStages.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000885
886 fRenderTarget.reset(NULL);
887
888 this->setDefaultVertexAttribs();
889
890 fCommon.fColor = 0xffffffff;
891 if (NULL == initialViewMatrix) {
892 fCommon.fViewMatrix.reset();
893 } else {
894 fCommon.fViewMatrix = *initialViewMatrix;
895 }
896 fCommon.fSrcBlend = kOne_GrBlendCoeff;
897 fCommon.fDstBlend = kZero_GrBlendCoeff;
898 fCommon.fBlendConstant = 0x0;
899 fCommon.fFlagBits = 0x0;
900 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000901 fCommon.fCoverage = 0xffffffff;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000902 fCommon.fDrawFace = kBoth_DrawFace;
903 }
904
bsalomon@google.comca432082013-01-23 19:53:46 +0000905 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
906 struct CommonState {
907 // These fields are roughly sorted by decreasing likelihood of being different in op==
robertphillips@google.com42903302013-04-20 12:26:07 +0000908 GrColor fColor;
909 SkMatrix fViewMatrix;
910 GrBlendCoeff fSrcBlend;
911 GrBlendCoeff fDstBlend;
912 GrColor fBlendConstant;
913 uint32_t fFlagBits;
914 const GrVertexAttrib* fVAPtr;
915 int fVACount;
916 GrStencilSettings fStencilSettings;
robertphillips@google.com42903302013-04-20 12:26:07 +0000917 GrColor fCoverage;
robertphillips@google.com42903302013-04-20 12:26:07 +0000918 DrawFace fDrawFace;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000919
920 // This is simply a different representation of info in fVertexAttribs and thus does
921 // not need to be compared in op==.
922 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
923
bsalomon@google.comca432082013-01-23 19:53:46 +0000924 bool operator== (const CommonState& other) const {
jvanverth@google.com054ae992013-04-01 20:06:51 +0000925 bool result = fColor == other.fColor &&
926 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
927 fSrcBlend == other.fSrcBlend &&
928 fDstBlend == other.fDstBlend &&
929 fBlendConstant == other.fBlendConstant &&
930 fFlagBits == other.fFlagBits &&
robertphillips@google.com42903302013-04-20 12:26:07 +0000931 fVACount == other.fVACount &&
932 !memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000933 fStencilSettings == other.fStencilSettings &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000934 fCoverage == other.fCoverage &&
jvanverth@google.com054ae992013-04-01 20:06:51 +0000935 fDrawFace == other.fDrawFace;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000936 SkASSERT(!result || 0 == memcmp(fFixedFunctionVertexAttribIndices,
jvanverth@google.com054ae992013-04-01 20:06:51 +0000937 other.fFixedFunctionVertexAttribIndices,
938 sizeof(fFixedFunctionVertexAttribIndices)));
939 return result;
bsalomon@google.comca432082013-01-23 19:53:46 +0000940 }
941 bool operator!= (const CommonState& other) const { return !(*this == other); }
942 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000943
bsalomon@google.comca432082013-01-23 19:53:46 +0000944 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
945 DeferredState must directly reference GrEffects, however. */
946 struct SavedEffectStage {
947 SavedEffectStage() : fEffect(NULL) {}
948 const GrEffect* fEffect;
949 GrEffectStage::SavedCoordChange fCoordChange;
950 };
951
952public:
953 /**
954 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
955 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
956 * dispose mechanism returns them to the cache. This allows recycling resources through the
957 * the cache while they are in a deferred draw queue.
958 */
959 class DeferredState {
960 public:
961 DeferredState() : fRenderTarget(NULL) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000962 SkDEBUGCODE(fInitialized = false;)
bsalomon@google.comca432082013-01-23 19:53:46 +0000963 }
964 // TODO: Remove this when DeferredState no longer holds a ref to the RT
965 ~DeferredState() { SkSafeUnref(fRenderTarget); }
966
967 void saveFrom(const GrDrawState& drawState) {
968 fCommon = drawState.fCommon;
969 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
970 fRenderTarget = drawState.fRenderTarget.get();
971 SkSafeRef(fRenderTarget);
972 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
973 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
974 // and recycle them to the cache (if no one else is holding a ref to the resources).
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000975 fStages.reset(drawState.fColorStages.count() + drawState.fCoverageStages.count());
976 fColorStageCnt = drawState.fColorStages.count();
977 for (int i = 0; i < fColorStageCnt; ++i) {
978 fStages[i].saveFrom(drawState.fColorStages[i]);
979 }
980 for (int i = 0; i < drawState.fCoverageStages.count(); ++i) {
981 fStages[i + fColorStageCnt].saveFrom(drawState.fCoverageStages[i]);
bsalomon@google.comca432082013-01-23 19:53:46 +0000982 }
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000983 SkDEBUGCODE(fInitialized = true;)
bsalomon@google.comca432082013-01-23 19:53:46 +0000984 }
985
986 void restoreTo(GrDrawState* drawState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000987 SkASSERT(fInitialized);
bsalomon@google.comca432082013-01-23 19:53:46 +0000988 drawState->fCommon = fCommon;
989 drawState->setRenderTarget(fRenderTarget);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000990 // reinflate color/cov stage arrays.
commit-bot@chromium.org2d3b4922013-07-15 13:54:06 +0000991 drawState->fColorStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000992 for (int i = 0; i < fColorStageCnt; ++i) {
commit-bot@chromium.org2d3b4922013-07-15 13:54:06 +0000993 SkNEW_APPEND_TO_TARRAY(&drawState->fColorStages, GrEffectStage, (fStages[i]));
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000994 }
995 int coverageStageCnt = fStages.count() - fColorStageCnt;
commit-bot@chromium.org2d3b4922013-07-15 13:54:06 +0000996 drawState->fCoverageStages.reset();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000997 for (int i = 0; i < coverageStageCnt; ++i) {
commit-bot@chromium.org2d3b4922013-07-15 13:54:06 +0000998 SkNEW_APPEND_TO_TARRAY(&drawState->fCoverageStages,
999 GrEffectStage, (fStages[i + fColorStageCnt]));
bsalomon@google.comca432082013-01-23 19:53:46 +00001000 }
1001 }
1002
1003 bool isEqual(const GrDrawState& state) const {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001004 int numCoverageStages = fStages.count() - fColorStageCnt;
1005 if (fRenderTarget != state.fRenderTarget.get() ||
1006 fColorStageCnt != state.fColorStages.count() ||
1007 numCoverageStages != state.fCoverageStages.count() ||
1008 fCommon != state.fCommon) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001009 return false;
1010 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001011 bool explicitLocalCoords = state.hasLocalCoordAttribute();
1012 for (int i = 0; i < fColorStageCnt; ++i) {
1013 if (!fStages[i].isEqual(state.fColorStages[i], explicitLocalCoords)) {
1014 return false;
1015 }
1016 }
1017 for (int i = 0; i < numCoverageStages; ++i) {
1018 int s = fColorStageCnt + i;
1019 if (!fStages[s].isEqual(state.fCoverageStages[i], explicitLocalCoords)) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001020 return false;
1021 }
1022 }
1023 return true;
1024 }
1025
1026 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001027 typedef SkAutoSTArray<8, GrEffectStage::DeferredStage> DeferredStageArray;
1028
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001029 GrRenderTarget* fRenderTarget;
1030 CommonState fCommon;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001031 int fColorStageCnt;
1032 DeferredStageArray fStages;
bsalomon@google.comca432082013-01-23 19:53:46 +00001033
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +00001034 SkDEBUGCODE(bool fInitialized;)
bsalomon@google.comca432082013-01-23 19:53:46 +00001035 };
1036
1037private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001038
bsalomon@google.comeb6879f2013-06-13 19:34:18 +00001039 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1040 CommonState fCommon;
1041
1042 typedef SkSTArray<4, GrEffectStage> EffectStageArray;
1043 EffectStageArray fColorStages;
1044 EffectStageArray fCoverageStages;
1045
1046 // Some of the auto restore objects assume that no effects are removed during their lifetime.
1047 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +00001048 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001049
robertphillips@google.com42903302013-04-20 12:26:07 +00001050 /**
1051 * Sets vertex attributes for next draw.
1052 *
1053 * @param attribs the array of vertex attributes to set.
1054 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
1055 */
1056 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
1057
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +00001058 typedef SkRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001059};
1060
bsalomon@google.com2b446732013-02-12 16:47:41 +00001061GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1062
tomhudson@google.com93813632011-10-27 20:21:16 +00001063#endif