blob: 53c575d3afb395e7d5995a6b40c47f825d948a03 [file] [log] [blame]
tomhudson@google.com93813632011-10-27 20:21:16 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000011#include "GrBackendEffectFactory.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000012#include "GrColor.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000013#include "GrEffectStage.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000014#include "GrRefCnt.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000015#include "GrRenderTarget.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000016#include "GrStencil.h"
17#include "GrTemplates.h"
18#include "GrTexture.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000019#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000020
jvanverth@google.comcc782382013-01-28 20:39:48 +000021#include "SkMatrix.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000022#include "SkXfermode.h"
23
bsalomon@google.comaf84e742012-10-05 13:23:24 +000024class GrPaint;
tomhudson@google.com93813632011-10-27 20:21:16 +000025
jvanverth@google.com9b855c72013-03-01 18:21:22 +000026/**
27 * Types used to describe format of vertices in arrays
28 */
29enum GrVertexAttribType {
30 kFloat_GrVertexAttribType = 0,
31 kVec2f_GrVertexAttribType,
32 kVec3f_GrVertexAttribType,
33 kVec4f_GrVertexAttribType,
34 kVec4ub_GrVertexAttribType, // vector of 4 unsigned bytes, e.g. colors
35
36 kLast_GrVertexAttribType = kVec4ub_GrVertexAttribType
37};
38static const int kGrVertexAttribTypeCount = kLast_GrVertexAttribType + 1;
39
40struct GrVertexAttrib {
41 GrVertexAttrib() {}
42 GrVertexAttrib(GrVertexAttribType type, size_t offset) :
43 fType(type), fOffset(offset) {}
44 bool operator==(const GrVertexAttrib& other) const {
45 return fType == other.fType && fOffset == other.fOffset;
46 };
47 bool operator!=(const GrVertexAttrib& other) const { return !(*this == other); }
48
49 GrVertexAttribType fType;
50 size_t fOffset;
51};
52
53template <int N>
54class GrVertexAttribArray : public SkSTArray<N, GrVertexAttrib, true> {};
55
56/**
57 * Type used to describe how attributes bind to program usage
58 */
59typedef int GrAttribBindings;
60
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000061class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000062public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000063 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000064
tomhudson@google.com93813632011-10-27 20:21:16 +000065 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000066 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
67 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
68 * output from the previous enabled stage and a position. The position is either derived from
69 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
jvanverth@google.com9b855c72013-03-01 18:21:22 +000070 * GrAttribBindings used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000071 *
bsalomon@google.com13221342012-10-26 13:41:59 +000072 * The stages are divided into two sets, color-computing and coverage-computing. The final color
73 * stage produces the final pixel color. The coverage-computing stages function exactly as the
74 * color-computing but the output of the final coverage stage is treated as a fractional pixel
75 * coverage rather than as input to the src/dst color blend step.
76 *
77 * The input color to the first enabled color-stage is either the constant color or interpolated
jvanverth@google.com9b855c72013-03-01 18:21:22 +000078 * per-vertex colors, depending upon GrAttribBindings. The input to the first coverage stage is
bsalomon@google.com13221342012-10-26 13:41:59 +000079 * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
80 * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
81 * GrEffect).
82 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000083 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
84 * the color / coverage distinction.
85 *
bsalomon@google.com13221342012-10-26 13:41:59 +000086 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
87 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
88 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000089 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000090 */
91 enum {
twiz@google.com58071162012-07-18 21:41:50 +000092 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000093 };
94
bsalomon@google.comca432082013-01-23 19:53:46 +000095 GrDrawState() {
reed@google.com75847192013-01-28 20:53:22 +000096#if GR_DEBUG
jvanverth@google.com9b855c72013-03-01 18:21:22 +000097 VertexAttributesUnitTest();
reed@google.com75847192013-01-28 20:53:22 +000098#endif
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000099 this->reset();
100 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +0000101
bsalomon@google.comca432082013-01-23 19:53:46 +0000102 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +0000103 *this = state;
104 }
105
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000106 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000107 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000108 }
109
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000110 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000111 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +0000112 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000113 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000114 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000115
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000116 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000117
bsalomon@google.comca432082013-01-23 19:53:46 +0000118 fRenderTarget.reset(NULL);
119
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000120 this->setDefaultVertexAttribs();
121
bsalomon@google.comca432082013-01-23 19:53:46 +0000122 fCommon.fColor = 0xffffffff;
123 fCommon.fViewMatrix.reset();
124 fCommon.fSrcBlend = kOne_GrBlendCoeff;
125 fCommon.fDstBlend = kZero_GrBlendCoeff;
126 fCommon.fBlendConstant = 0x0;
127 fCommon.fFlagBits = 0x0;
128 fCommon.fVertexEdgeType = kHairLine_EdgeType;
129 fCommon.fStencilSettings.setDisabled();
130 fCommon.fFirstCoverageStage = kNumStages;
131 fCommon.fCoverage = 0xffffffff;
132 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
133 fCommon.fColorFilterColor = 0x0;
134 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000135 }
136
137 /**
138 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000139 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000140 * GrPaint equivalents are not modified. GrPaint has fewer stages than
141 * GrDrawState. The extra GrDrawState stages are disabled.
142 */
143 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000144
145 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000146 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000147 ////
148
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000149 enum {
150 kVertexAttribCnt = 6,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000151 };
152
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000153 /**
154 * The format of vertices is represented as an array of vertex attribute
155 * pair, with each pair representing the type of the attribute and the
156 * offset in the vertex structure (see GrVertexAttrib, above).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000157 *
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000158 * This will only set up the vertex geometry. To bind the attributes in
159 * the shaders, attribute indices and attribute bindings need to be set
160 * as well.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000161 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000162
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000163 /**
164 * Sets vertex attributes for next draw.
165 *
166 * @param attribs the array of vertex attributes to set.
167 * @param count the number of attributes being set.
168 * limited to a count of kVertexAttribCnt.
169 */
170 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000171
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000172 const GrVertexAttrib* getVertexAttribs() const { return fVertexAttribs.begin(); }
173 int getVertexAttribCount() const { return fVertexAttribs.count(); }
174
175 size_t getVertexSize() const;
176
177 /**
178 * Sets default vertex attributes for next draw.
179 *
180 * This will also set default vertex attribute indices and bindings
181 */
182 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000183
jvanverth@google.comcc782382013-01-28 20:39:48 +0000184 ////////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000185 // Helpers for picking apart vertex attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +0000186
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000187 // helper array to let us check the expected so we know what bound attrib indices
188 // we care about
189 static const size_t kVertexAttribSizes[kGrVertexAttribTypeCount];
jvanverth@google.comcc782382013-01-28 20:39:48 +0000190
191 /**
192 * Accessing positions, texture coords, or colors, of a vertex within an
193 * array is a hassle involving casts and simple math. These helpers exist
194 * to keep GrDrawTarget clients' code a bit nicer looking.
195 */
196
197 /**
198 * Gets a pointer to a GrPoint of a vertex's position or texture
199 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000200 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000201 * @param vertexIndex the index of the vertex in the array
202 * @param vertexSize the size of each vertex in the array
203 * @param offset the offset in bytes of the vertex component.
204 * Defaults to zero (corresponding to vertex position)
205 * @return pointer to the vertex component as a GrPoint
206 */
207 static GrPoint* GetVertexPoint(void* vertices,
208 int vertexIndex,
209 int vertexSize,
210 int offset = 0) {
211 intptr_t start = GrTCast<intptr_t>(vertices);
212 return GrTCast<GrPoint*>(start + offset +
213 vertexIndex * vertexSize);
214 }
215 static const GrPoint* GetVertexPoint(const void* vertices,
216 int vertexIndex,
217 int vertexSize,
218 int offset = 0) {
219 intptr_t start = GrTCast<intptr_t>(vertices);
220 return GrTCast<const GrPoint*>(start + offset +
221 vertexIndex * vertexSize);
222 }
223
224 /**
225 * Gets a pointer to a GrColor inside a vertex within a vertex array.
226 * @param vertices the vetex array
227 * @param vertexIndex the index of the vertex in the array
228 * @param vertexSize the size of each vertex in the array
229 * @param offset the offset in bytes of the vertex color
230 * @return pointer to the vertex component as a GrColor
231 */
232 static GrColor* GetVertexColor(void* vertices,
233 int vertexIndex,
234 int vertexSize,
235 int offset) {
236 intptr_t start = GrTCast<intptr_t>(vertices);
237 return GrTCast<GrColor*>(start + offset +
238 vertexIndex * vertexSize);
239 }
240 static const GrColor* GetVertexColor(const void* vertices,
241 int vertexIndex,
242 int vertexSize,
243 int offset) {
244 const intptr_t start = GrTCast<intptr_t>(vertices);
245 return GrTCast<const GrColor*>(start + offset +
246 vertexIndex * vertexSize);
247 }
248
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000249 /// @}
250
251 ///////////////////////////////////////////////////////////////////////////
252 /// @name Attribute Bindings
253 ////
254
255 /**
256 * The vertex data used by the current program is represented as a bitfield
257 * of flags. Programs always use positions and may also use texture
258 * coordinates, per-vertex colors, per-vertex coverage and edge data. Each
259 * stage can use the explicit texture coordinates as its input texture
260 * coordinates or it may use the positions as texture coordinates.
261 */
262
263 /**
264 * Generates a bit indicating that a texture stage uses texture coordinates
265 *
266 * @param stageIdx the stage that will use texture coordinates.
267 *
268 * @return the bit to add to a GrAttribBindings bitfield.
269 */
270 static int ExplicitTexCoordAttribBindingsBit(int stageIdx) {
271 GrAssert(stageIdx < kNumStages);
272 return (1 << stageIdx);
273 }
274
275 static bool StageBindsExplicitTexCoords(GrAttribBindings bindings, int stageIdx);
276
277 /**
278 * Additional Bits that can be specified in GrAttribBindings.
279 */
280 enum AttribBindingsBits {
281 /* program uses colors (GrColor) */
282 kColor_AttribBindingsBit = 1 << (kNumStages + 0),
283 /* program uses coverage (GrColor)
284 */
285 kCoverage_AttribBindingsBit = 1 << (kNumStages + 1),
286 /* program uses edge data. Distance to the edge is used to
287 * compute a coverage. See GrDrawState::setVertexEdgeType().
288 */
289 kEdge_AttribBindingsBit = 1 << (kNumStages + 2),
290 // for below assert
291 kDummyAttribBindingsBit,
292 kHighAttribBindingsBit = kDummyAttribBindingsBit - 1
293 };
294 // make sure we haven't exceeded the number of bits in GrAttribBindings.
295 GR_STATIC_ASSERT(kHighAttribBindingsBit < ((uint64_t)1 << 8*sizeof(GrAttribBindings)));
296
297 enum AttribBindings {
298 kDefault_AttribBindings = 0
299 };
300
301 /**
302 * Sets attribute bindings for next draw.
303 *
304 * @param bindings the attribute bindings to set.
305 */
306 void setAttribBindings(GrAttribBindings bindings) { fCommon.fAttribBindings = bindings; }
307
308 GrAttribBindings getAttribBindings() const { return fCommon.fAttribBindings; }
309
310 ////////////////////////////////////////////////////////////////////////////
311 // Helpers for picking apart attribute bindings
312
313 /**
314 * Helper function to determine if program uses explicit texture
315 * coordinates.
316 *
317 * @param bindings attribute bindings to query
318 *
319 * @return true if program uses texture coordinates,
320 * false otherwise.
321 */
322 static bool AttributesBindExplicitTexCoords(GrAttribBindings bindings);
323
324 /**
325 * Determines whether src alpha is guaranteed to be one for all src pixels
326 */
327 bool srcAlphaWillBeOne(GrAttribBindings) const;
328
329 /**
330 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
331 */
332 bool hasSolidCoverage(GrAttribBindings) const;
333
334 static void VertexAttributesUnitTest();
335
336 /// @}
337
338 ///////////////////////////////////////////////////////////////////////////
339 /// @name Vertex Attribute Indices
340 ////
341
342 /**
343 * Vertex attribute indices map the data set in the vertex attribute array
344 * to the bindings specified in the attribute bindings. Each binding type
345 * has an associated index in the attribute array. This index is used to
346 * look up the vertex attribute data from the array, and potentially as the
347 * attribute index if we're binding attributes in GL.
348 *
349 * Indices which do not have active attribute bindings will be ignored.
350 */
351
352 enum AttribIndex {
353 kPosition_AttribIndex = 0,
354 kColor_AttribIndex,
355 kCoverage_AttribIndex,
356 kEdge_AttribIndex,
357 kTexCoord_AttribIndex,
358
359 kLast_AttribIndex = kTexCoord_AttribIndex
360 };
361 static const int kAttribIndexCount = kLast_AttribIndex + 1;
362
363 // these are used when vertex color and coverage isn't set
364 enum {
365 kColorOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt,
366 kCoverageOverrideAttribIndexValue = GrDrawState::kVertexAttribCnt+1,
367 };
368
369 ////////////////////////////////////////////////////////////////////////////
370 // Helpers to set attribute indices. These should match the index in the
371 // current attribute index array.
372
373 /**
374 * Sets index for next draw. This is used to look up the offset
375 * from the current vertex attribute array and to bind the attributes.
376 *
377 * @param index the attribute index we're setting
378 * @param value the value of the index
379 */
380 void setAttribIndex(AttribIndex index, int value) { fAttribIndices[index] = value; }
381
382 int getAttribIndex(AttribIndex index) const { return fAttribIndices[index]; }
jvanverth@google.comcc782382013-01-28 20:39:48 +0000383
384 /// @}
385
386 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000387 /// @name Color
388 ////
389
390 /**
391 * Sets color for next draw to a premultiplied-alpha color.
392 *
393 * @param color the color to set.
394 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000395 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000396
bsalomon@google.comca432082013-01-23 19:53:46 +0000397 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000398
399 /**
400 * Sets the color to be used for the next draw to be
401 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
402 *
403 * @param alpha The alpha value to set as the color.
404 */
405 void setAlpha(uint8_t a) {
406 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
407 }
408
409 /**
410 * Add a color filter that can be represented by a color and a mode. Applied
411 * after color-computing texture stages.
412 */
413 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000414 fCommon.fColorFilterColor = c;
415 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000416 }
417
bsalomon@google.comca432082013-01-23 19:53:46 +0000418 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
419 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000420
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000421 /**
422 * Constructor sets the color to be 'color' which is undone by the destructor.
423 */
424 class AutoColorRestore : public ::GrNoncopyable {
425 public:
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000426 AutoColorRestore() : fDrawState(NULL) {}
427
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000428 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000429 fDrawState = NULL;
430 this->set(drawState, color);
431 }
432
433 void reset() {
434 if (NULL != fDrawState) {
435 fDrawState->setColor(fOldColor);
436 fDrawState = NULL;
437 }
438 }
439
440 void set(GrDrawState* drawState, GrColor color) {
441 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000442 fDrawState = drawState;
443 fOldColor = fDrawState->getColor();
444 fDrawState->setColor(color);
445 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000446
447 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000448 private:
449 GrDrawState* fDrawState;
450 GrColor fOldColor;
451 };
452
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000453 /// @}
454
455 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000456 /// @name Coverage
457 ////
458
459 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000460 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000461 * initial value (after construction or reset()) is 0xff. The constant
462 * coverage is ignored when per-vertex coverage is provided.
463 */
464 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000465 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000466 }
467
468 /**
469 * Version of above that specifies 4 channel per-vertex color. The value
470 * should be premultiplied.
471 */
472 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000473 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000474 }
475
476 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000477 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000478 }
479
480 /// @}
481
482 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000483 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000484 ////
485
bsalomon@google.comadc65362013-01-28 14:26:09 +0000486 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
487 fStages[stageIdx].setEffect(effect);
488 return effect;
489 }
490
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000491 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000492 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000493 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000494 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000495 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000496 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000497 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000498 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000499 void createTextureEffect(int stageIdx,
500 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000501 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000502 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000503 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000504 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000505 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000506 }
507
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000508 bool stagesDisabled() {
509 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000510 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000511 return false;
512 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000513 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000514 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000515 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000516
bsalomon@google.comadc65362013-01-28 14:26:09 +0000517 void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000518
robertphillips@google.com972265d2012-06-13 18:49:30 +0000519 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000520 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000521 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000522 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000523 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000524 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000525 }
526 }
527
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000528 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000529 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000530 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
531 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000532 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000533 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000534 }
535 }
536 private:
537 GrDrawState* fDrawState;
538 };
539
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000541 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000542 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000543 const GrEffectStage& getStage(int stageIdx) const {
544 GrAssert((unsigned)stageIdx < kNumStages);
545 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000546 }
547
548 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000549 * Called when the source coord system is changing. preConcat gives the transformation from the
550 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000551 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000552 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000553 this->preConcatStageMatrices(~0U, preConcat);
554 }
555 /**
556 * Version of above that applies the update matrix selectively to stages via a mask.
557 */
558 void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000559 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000560 if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000561 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000562 }
563 }
564 }
565
bsalomon@google.come3d32162012-07-20 13:37:06 +0000566 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000567 * Called when the source coord system is changing. preConcatInverse is the inverse of the
568 * transformation from the old coord system to the new coord system. Returns false if the matrix
569 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000570 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000571 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
572 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000573 bool computed = false;
574 for (int i = 0; i < kNumStages; ++i) {
575 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000576 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000577 return false;
578 } else {
579 computed = true;
580 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000581 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000582 }
583 }
584 return true;
585 }
586
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000587 /// @}
588
589 ///////////////////////////////////////////////////////////////////////////
590 /// @name Coverage / Color Stages
591 ////
592
593 /**
594 * A common pattern is to compute a color with the initial stages and then
595 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000596 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
597 * computed based on the pre-coverage-modulated color. The division of
598 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000599 * this method. Initially this is kNumStages (all stages
600 * are color-computing).
601 */
602 void setFirstCoverageStage(int firstCoverageStage) {
603 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000604 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000605 }
606
607 /**
608 * Gets the index of the first coverage-computing stage.
609 */
610 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000611 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612 }
613
614 ///@}
615
616 ///////////////////////////////////////////////////////////////////////////
617 /// @name Blending
618 ////
619
620 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000621 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000622 *
623 * The blend function will be:
624 * D' = sat(S*srcCoef + D*dstCoef)
625 *
626 * where D is the existing destination color, S is the incoming source
627 * color, and D' is the new destination color that will be written. sat()
628 * is the saturation function.
629 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000630 * @param srcCoef coefficient applied to the src color.
631 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000632 */
633 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000634 fCommon.fSrcBlend = srcCoeff;
635 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000636 #if GR_DEBUG
637 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000638 case kDC_GrBlendCoeff:
639 case kIDC_GrBlendCoeff:
640 case kDA_GrBlendCoeff:
641 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000642 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
643 "coverage stages.\n");
644 break;
645 default:
646 break;
647 }
648 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000649 case kSC_GrBlendCoeff:
650 case kISC_GrBlendCoeff:
651 case kSA_GrBlendCoeff:
652 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000653 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
654 "coverage stages.\n");
655 break;
656 default:
657 break;
658 }
659 #endif
660 }
661
bsalomon@google.comca432082013-01-23 19:53:46 +0000662 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
663 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000664
665 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
666 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000667 *srcBlendCoeff = fCommon.fSrcBlend;
668 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000669 }
670
671 /**
672 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000673 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000674 * kConstC_GrBlendCoeff
675 * kIConstC_GrBlendCoeff
676 * kConstA_GrBlendCoeff
677 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000678 *
679 * @param constant the constant to set
680 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000681 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000682
683 /**
684 * Retrieves the last value set by setBlendConstant()
685 * @return the blending constant value
686 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000687 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000688
bsalomon@google.com2b446732013-02-12 16:47:41 +0000689 /**
690 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
691 * coverage before the blend will give the correct final destination color. In general it
692 * will not as coverage is applied after blending.
693 */
694 bool canTweakAlphaForCoverage() const;
695
696 /**
697 * Optimizations for blending / coverage to that can be applied based on the current state.
698 */
699 enum BlendOptFlags {
700 /**
701 * No optimization
702 */
703 kNone_BlendOpt = 0,
704 /**
705 * Don't draw at all
706 */
707 kSkipDraw_BlendOptFlag = 0x1,
708 /**
709 * Emit the src color, disable HW blending (replace dst with src)
710 */
711 kDisableBlend_BlendOptFlag = 0x2,
712 /**
713 * The coverage value does not have to be computed separately from alpha, the the output
714 * color can be the modulation of the two.
715 */
716 kCoverageAsAlpha_BlendOptFlag = 0x4,
717 /**
718 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
719 * "don't cares".
720 */
721 kEmitCoverage_BlendOptFlag = 0x8,
722 /**
723 * Emit transparent black instead of the src color, no need to compute coverage.
724 */
725 kEmitTransBlack_BlendOptFlag = 0x10,
726 };
727 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
728
729 /**
730 * Determines what optimizations can be applied based on the blend. The coefficients may have
731 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
732 * params that receive the tweaked coefficients. Normally the function looks at the current
733 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
734 * determine the blend optimizations that would be used if there was partial pixel coverage.
735 *
736 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
737 * playback) must call this function and respect the flags that replace the output color.
738 */
739 BlendOptFlags getBlendOpts(bool forceCoverage = false,
740 GrBlendCoeff* srcCoeff = NULL,
741 GrBlendCoeff* dstCoeff = NULL) const;
742
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000743 /// @}
744
745 ///////////////////////////////////////////////////////////////////////////
746 /// @name View Matrix
747 ////
748
749 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000750 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000751 *
752 * In the post-view-matrix space the rectangle [0,w]x[0,h]
753 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000754 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000755 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000756 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000757
758 /**
759 * Gets a writable pointer to the view matrix.
760 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000761 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762
763 /**
764 * Multiplies the current view matrix by a matrix
765 *
766 * After this call V' = V*m where V is the old view matrix,
767 * m is the parameter to this function, and V' is the new view matrix.
768 * (We consider positions to be column vectors so position vector p is
769 * transformed by matrix X as p' = X*p.)
770 *
771 * @param m the matrix used to modify the view matrix.
772 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000773 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000774
775 /**
776 * Multiplies the current view matrix by a matrix
777 *
778 * After this call V' = m*V where V is the old view matrix,
779 * m is the parameter to this function, and V' is the new view matrix.
780 * (We consider positions to be column vectors so position vector p is
781 * transformed by matrix X as p' = X*p.)
782 *
783 * @param m the matrix used to modify the view matrix.
784 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000785 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000786
787 /**
788 * Retrieves the current view matrix
789 * @return the current view matrix.
790 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000791 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000792
793 /**
794 * Retrieves the inverse of the current view matrix.
795 *
796 * If the current view matrix is invertible, return true, and if matrix
797 * is non-null, copy the inverse into it. If the current view matrix is
798 * non-invertible, return false and ignore the matrix parameter.
799 *
800 * @param matrix if not null, will receive a copy of the current inverse.
801 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000802 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000803 // TODO: determine whether we really need to leave matrix unmodified
804 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000805 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000806 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000807 if (matrix) {
808 *matrix = inverse;
809 }
810 return true;
811 }
812 return false;
813 }
814
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000815 ////////////////////////////////////////////////////////////////////////////
816
817 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000818 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000819 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000820 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 class AutoViewMatrixRestore : public ::GrNoncopyable {
822 public:
823 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000824
825 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000826 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000827 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000828 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000829 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000830 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000831
832 ~AutoViewMatrixRestore() { this->restore(); }
833
bsalomon@google.coma8347462012-10-08 18:59:39 +0000834 /**
835 * Can be called prior to destructor to restore the original matrix.
836 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000837 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000838
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000839 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000840 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000841 uint32_t explicitCoordStageMask = 0);
842
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000843 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000844
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000846 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000847 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000848 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000849 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000850 };
851
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000852 ////////////////////////////////////////////////////////////////////////////
853
854 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000855 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
856 * destructor undoes the changes, restoring the view matrix that was set before the
857 * constructor. It is similar to passing the inverse of the current view matrix to
858 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000859 */
860 class AutoDeviceCoordDraw : ::GrNoncopyable {
861 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000862 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000863 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000864 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
865 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
866 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000867 */
868 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000869 uint32_t explicitCoordStageMask = 0) {
870 fDrawState = NULL;
871 this->set(drawState, explicitCoordStageMask);
872 }
873
bsalomon@google.coma8347462012-10-08 18:59:39 +0000874 ~AutoDeviceCoordDraw() { this->restore(); }
875
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000876 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
877
bsalomon@google.coma8347462012-10-08 18:59:39 +0000878 /**
879 * Returns true if this object was successfully initialized on to a GrDrawState. It may
880 * return false because a non-default constructor or set() were never called or because
881 * the view matrix was not invertible.
882 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000883 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000884
bsalomon@google.coma8347462012-10-08 18:59:39 +0000885 /**
886 * Returns the matrix that was set previously set on the drawState. This is only valid
887 * if succeeded returns true.
888 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000889 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000890 GrAssert(this->succeeded());
891 return fViewMatrix;
892 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000893
bsalomon@google.coma8347462012-10-08 18:59:39 +0000894 /**
895 * Can be called prior to destructor to restore the original matrix.
896 */
897 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000898
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000899 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000900 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000901 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000902 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000903 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000904 };
905
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000906 /// @}
907
908 ///////////////////////////////////////////////////////////////////////////
909 /// @name Render Target
910 ////
911
912 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000913 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000914 *
915 * @param target The render target to set.
916 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000917 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000918 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000919 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000920
921 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000922 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000923 *
924 * @return The currently set render target.
925 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000926 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
927 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928
929 class AutoRenderTargetRestore : public ::GrNoncopyable {
930 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000931 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000932 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
933 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000934 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000935 this->set(ds, newTarget);
936 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000937 ~AutoRenderTargetRestore() { this->restore(); }
938
939 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000940 if (NULL != fDrawState) {
941 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000942 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000943 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000944 GrSafeSetNull(fSavedTarget);
945 }
946
947 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
948 this->restore();
949
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000950 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000951 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000952 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000953 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000954 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000955 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000956 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000957 }
958 private:
959 GrDrawState* fDrawState;
960 GrRenderTarget* fSavedTarget;
961 };
962
963 /// @}
964
965 ///////////////////////////////////////////////////////////////////////////
966 /// @name Stencil
967 ////
968
969 /**
970 * Sets the stencil settings to use for the next draw.
971 * Changing the clip has the side-effect of possibly zeroing
972 * out the client settable stencil bits. So multipass algorithms
973 * using stencil should not change the clip between passes.
974 * @param settings the stencil settings to use.
975 */
976 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000977 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000978 }
979
980 /**
981 * Shortcut to disable stencil testing and ops.
982 */
983 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000984 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000985 }
986
bsalomon@google.comca432082013-01-23 19:53:46 +0000987 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000988
bsalomon@google.comca432082013-01-23 19:53:46 +0000989 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000990
991 /// @}
992
993 ///////////////////////////////////////////////////////////////////////////
994 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000995 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000996 // edges are specified as per-vertex data, vertices that are shared by
997 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000998 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000999 ////
1000
1001 /**
tomhudson@google.com93813632011-10-27 20:21:16 +00001002 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +00001003 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +00001004 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +00001005 *
1006 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
1007 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +00001008 */
1009 enum VertexEdgeType {
1010 /* 1-pixel wide line
1011 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
1012 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001013 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001014 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +00001015 being inside, positive outside. Edge specified in window space
1016 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001017 kQuad_EdgeType,
1018 /* Same as above but for hairline quadratics. Uses unsigned distance.
1019 Coverage is min(0, 1-distance). */
1020 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +00001021 /* Circle specified as center_x, center_y, outer_radius, inner_radius
1022 all in window space (y-down). */
1023 kCircle_EdgeType,
jvanverth@google.com46d3d392013-01-22 13:34:01 +00001024 /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
1025 all in window space (y-down). */
1026 kEllipse_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001027
1028 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +00001029 };
1030
1031 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +00001032 * Determines the interpretation per-vertex edge data when the
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001033 * kEdge_AttribBindingsBit is set (see GrDrawTarget). When per-vertex edges
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001034 * are not specified the value of this setting has no effect.
1035 */
1036 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +00001037 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.comca432082013-01-23 19:53:46 +00001038 fCommon.fVertexEdgeType = type;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001039 }
1040
bsalomon@google.comca432082013-01-23 19:53:46 +00001041 VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001042
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001043 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +00001044
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001045 ///////////////////////////////////////////////////////////////////////////
1046 /// @name State Flags
1047 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001048
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001049 /**
1050 * Flags that affect rendering. Controlled using enable/disableState(). All
1051 * default to disabled.
1052 */
1053 enum StateBits {
1054 /**
1055 * Perform dithering. TODO: Re-evaluate whether we need this bit
1056 */
1057 kDither_StateBit = 0x01,
1058 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001059 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
1060 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
1061 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001062 */
1063 kHWAntialias_StateBit = 0x02,
1064 /**
1065 * Draws will respect the clip, otherwise the clip is ignored.
1066 */
1067 kClip_StateBit = 0x04,
1068 /**
1069 * Disables writing to the color buffer. Useful when performing stencil
1070 * operations.
1071 */
1072 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +00001073
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001074 /**
1075 * Usually coverage is applied after color blending. The color is blended using the coeffs
1076 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
1077 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
1078 * this case there is no distinction between coverage and color and the caller needs direct
1079 * control over the blend coeffs. When set, there will be a single blend step controlled by
1080 * setBlendFunc() which will use coverage*color as the src color.
1081 */
1082 kCoverageDrawing_StateBit = 0x10,
1083
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001084 // Users of the class may add additional bits to the vector
1085 kDummyStateBit,
1086 kLastPublicStateBit = kDummyStateBit-1,
1087 };
1088
1089 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +00001090 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001091 }
1092
1093 /**
1094 * Enable render state settings.
1095 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001096 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001097 */
1098 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001099 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001100 }
1101
1102 /**
1103 * Disable render state settings.
1104 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001105 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001106 */
1107 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001108 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001109 }
1110
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001111 /**
1112 * Enable or disable stateBits based on a boolean.
1113 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001114 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001115 * @param enable if true enable stateBits, otherwise disable
1116 */
1117 void setState(uint32_t stateBits, bool enable) {
1118 if (enable) {
1119 this->enableState(stateBits);
1120 } else {
1121 this->disableState(stateBits);
1122 }
1123 }
1124
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001125 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001126 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001127 }
1128
1129 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001130 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001131 }
1132
1133 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001134 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001135 }
1136
1137 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001138 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001139 }
1140
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001141 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001142 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001143 }
1144
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001145 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001146 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001147 }
1148
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001149 /// @}
1150
1151 ///////////////////////////////////////////////////////////////////////////
1152 /// @name Face Culling
1153 ////
1154
1155 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001156 kInvalid_DrawFace = -1,
1157
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001158 kBoth_DrawFace,
1159 kCCW_DrawFace,
1160 kCW_DrawFace,
1161 };
1162
1163 /**
1164 * Controls whether clockwise, counterclockwise, or both faces are drawn.
1165 * @param face the face(s) to draw.
1166 */
1167 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001168 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +00001169 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001170 }
1171
1172 /**
1173 * Gets whether the target is drawing clockwise, counterclockwise,
1174 * or both faces.
1175 * @return the current draw face(s).
1176 */
bsalomon@google.comca432082013-01-23 19:53:46 +00001177 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +00001178
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001179 /// @}
1180
1181 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001182
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001183 bool isStageEnabled(int s) const {
1184 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001185 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001186 }
1187
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001188 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001189 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001190 return false;
1191 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001192 if (fVertexAttribs.count() != s.fVertexAttribs.count()) {
1193 return false;
1194 }
1195 for (int i = 0; i < fVertexAttribs.count(); ++i) {
1196 if (fVertexAttribs[i] != s.fVertexAttribs[i]) {
1197 return false;
1198 }
1199 }
1200 for (int i = 0; i < kAttribIndexCount; ++i) {
1201 if ((i == kPosition_AttribIndex ||
1202 s.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
1203 fAttribIndices[i] != s.fAttribIndices[i]) {
1204 return false;
1205 }
1206 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001207 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001208 bool enabled = this->isStageEnabled(i);
1209 if (enabled != s.isStageEnabled(i)) {
1210 return false;
1211 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001212 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001213 return false;
1214 }
1215 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001216 return true;
1217 }
1218 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1219
bsalomon@google.comca432082013-01-23 19:53:46 +00001220 GrDrawState& operator= (const GrDrawState& s) {
1221 this->setRenderTarget(s.fRenderTarget.get());
1222 fCommon = s.fCommon;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001223 fVertexAttribs = s.fVertexAttribs;
1224 for (int i = 0; i < kAttribIndexCount; i++) {
1225 fAttribIndices[i] = s.fAttribIndices[i];
1226 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001227 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001228 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001229 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001230 }
1231 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001232 return *this;
1233 }
1234
1235private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001236
bsalomon@google.comca432082013-01-23 19:53:46 +00001237 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1238 struct CommonState {
1239 // These fields are roughly sorted by decreasing likelihood of being different in op==
1240 GrColor fColor;
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001241 GrAttribBindings fAttribBindings;
bsalomon@google.comca432082013-01-23 19:53:46 +00001242 SkMatrix fViewMatrix;
1243 GrBlendCoeff fSrcBlend;
1244 GrBlendCoeff fDstBlend;
1245 GrColor fBlendConstant;
1246 uint32_t fFlagBits;
1247 VertexEdgeType fVertexEdgeType;
1248 GrStencilSettings fStencilSettings;
1249 int fFirstCoverageStage;
1250 GrColor fCoverage;
1251 SkXfermode::Mode fColorFilterMode;
1252 GrColor fColorFilterColor;
1253 DrawFace fDrawFace;
1254 bool operator== (const CommonState& other) const {
1255 return fColor == other.fColor &&
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001256 fAttribBindings == other.fAttribBindings &&
bsalomon@google.comca432082013-01-23 19:53:46 +00001257 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1258 fSrcBlend == other.fSrcBlend &&
1259 fDstBlend == other.fDstBlend &&
1260 fBlendConstant == other.fBlendConstant &&
1261 fFlagBits == other.fFlagBits &&
1262 fVertexEdgeType == other.fVertexEdgeType &&
1263 fStencilSettings == other.fStencilSettings &&
1264 fFirstCoverageStage == other.fFirstCoverageStage &&
1265 fCoverage == other.fCoverage &&
1266 fColorFilterMode == other.fColorFilterMode &&
1267 fColorFilterColor == other.fColorFilterColor &&
1268 fDrawFace == other.fDrawFace;
1269 }
1270 bool operator!= (const CommonState& other) const { return !(*this == other); }
1271 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001272
bsalomon@google.comca432082013-01-23 19:53:46 +00001273 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1274 DeferredState must directly reference GrEffects, however. */
1275 struct SavedEffectStage {
1276 SavedEffectStage() : fEffect(NULL) {}
1277 const GrEffect* fEffect;
1278 GrEffectStage::SavedCoordChange fCoordChange;
1279 };
1280
1281public:
1282 /**
1283 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1284 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1285 * dispose mechanism returns them to the cache. This allows recycling resources through the
1286 * the cache while they are in a deferred draw queue.
1287 */
1288 class DeferredState {
1289 public:
1290 DeferredState() : fRenderTarget(NULL) {
1291 GR_DEBUGCODE(fInitialized = false;)
1292 }
1293 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1294 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1295
1296 void saveFrom(const GrDrawState& drawState) {
1297 fCommon = drawState.fCommon;
1298 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1299 fRenderTarget = drawState.fRenderTarget.get();
1300 SkSafeRef(fRenderTarget);
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001301 fVertexAttribs = drawState.fVertexAttribs;
1302 for (int i = 0; i < kAttribIndexCount; i++) {
1303 fAttribIndices[i] = drawState.fAttribIndices[i];
1304 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001305 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1306 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1307 // and recycle them to the cache (if no one else is holding a ref to the resources).
1308 for (int i = 0; i < kNumStages; ++i) {
1309 fStages[i].saveFrom(drawState.fStages[i]);
1310 }
1311 GR_DEBUGCODE(fInitialized = true;)
1312 }
1313
1314 void restoreTo(GrDrawState* drawState) {
1315 GrAssert(fInitialized);
1316 drawState->fCommon = fCommon;
1317 drawState->setRenderTarget(fRenderTarget);
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001318 drawState->fVertexAttribs = fVertexAttribs;
1319 for (int i = 0; i < kAttribIndexCount; i++) {
1320 drawState->fAttribIndices[i] = fAttribIndices[i];
1321 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001322 for (int i = 0; i < kNumStages; ++i) {
1323 fStages[i].restoreTo(&drawState->fStages[i]);
1324 }
1325 }
1326
1327 bool isEqual(const GrDrawState& state) const {
1328 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1329 return false;
1330 }
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001331 for (int i = 0; i < kAttribIndexCount; ++i) {
1332 if ((i == kPosition_AttribIndex ||
1333 state.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
1334 fAttribIndices[i] != state.fAttribIndices[i]) {
1335 return false;
1336 }
1337 }
1338 if (fVertexAttribs.count() != state.fVertexAttribs.count()) {
1339 return false;
1340 }
1341 for (int i = 0; i < fVertexAttribs.count(); ++i)
1342 if (fVertexAttribs[i] != state.fVertexAttribs[i]) {
1343 return false;
1344 }
bsalomon@google.comca432082013-01-23 19:53:46 +00001345 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001346 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001347 return false;
1348 }
1349 }
1350 return true;
1351 }
1352
1353 private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001354 GrRenderTarget* fRenderTarget;
1355 CommonState fCommon;
1356 int fAttribIndices[kAttribIndexCount];
1357 GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
1358 GrEffectStage::DeferredStage fStages[kNumStages];
bsalomon@google.comca432082013-01-23 19:53:46 +00001359
1360 GR_DEBUGCODE(bool fInitialized;)
1361 };
1362
1363private:
jvanverth@google.com9b855c72013-03-01 18:21:22 +00001364 // helper array to let us check the current bindings so we know what bound attrib indices
1365 // we care about
1366 static const GrAttribBindings kAttribIndexMasks[kAttribIndexCount];
1367
1368 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1369 CommonState fCommon;
1370 int fAttribIndices[kAttribIndexCount];
1371 GrVertexAttribArray<kVertexAttribCnt> fVertexAttribs;
1372 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001373
reed@google.comfa35e3d2012-06-26 20:16:17 +00001374 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001375};
1376
bsalomon@google.com2b446732013-02-12 16:47:41 +00001377GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1378
tomhudson@google.com93813632011-10-27 20:21:16 +00001379#endif