blob: 0a0b0da33d725702db7fbfae6a843a84d642da9d [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
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000026class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000027public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000028 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000029
tomhudson@google.com93813632011-10-27 20:21:16 +000030 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000031 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
32 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
33 * output from the previous enabled stage and a position. The position is either derived from
34 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
35 * GrVertexLayout used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000036 *
bsalomon@google.com13221342012-10-26 13:41:59 +000037 * The stages are divided into two sets, color-computing and coverage-computing. The final color
38 * stage produces the final pixel color. The coverage-computing stages function exactly as the
39 * color-computing but the output of the final coverage stage is treated as a fractional pixel
40 * coverage rather than as input to the src/dst color blend step.
41 *
42 * The input color to the first enabled color-stage is either the constant color or interpolated
43 * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
44 * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
45 * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
46 * GrEffect).
47 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000048 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
49 * the color / coverage distinction.
50 *
bsalomon@google.com13221342012-10-26 13:41:59 +000051 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
52 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
53 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000054 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000055 */
56 enum {
twiz@google.com58071162012-07-18 21:41:50 +000057 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000058 kMaxTexCoords = kNumStages
59 };
60
bsalomon@google.comca432082013-01-23 19:53:46 +000061 GrDrawState() {
reed@google.com75847192013-01-28 20:53:22 +000062#if GR_DEBUG
63 VertexLayoutUnitTest();
64#endif
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000065 this->reset();
66 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000067
bsalomon@google.comca432082013-01-23 19:53:46 +000068 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000069 *this = state;
70 }
71
robertphillips@google.com9ec07532012-06-22 12:01:30 +000072 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000073 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000074 }
75
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000076 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000078 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000079 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000081
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000082 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000083
bsalomon@google.comca432082013-01-23 19:53:46 +000084 fRenderTarget.reset(NULL);
85
86 fCommon.fColor = 0xffffffff;
87 fCommon.fViewMatrix.reset();
88 fCommon.fSrcBlend = kOne_GrBlendCoeff;
89 fCommon.fDstBlend = kZero_GrBlendCoeff;
90 fCommon.fBlendConstant = 0x0;
91 fCommon.fFlagBits = 0x0;
92 fCommon.fVertexEdgeType = kHairLine_EdgeType;
93 fCommon.fStencilSettings.setDisabled();
94 fCommon.fFirstCoverageStage = kNumStages;
95 fCommon.fCoverage = 0xffffffff;
96 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
97 fCommon.fColorFilterColor = 0x0;
98 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000099 }
100
101 /**
102 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000103 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000104 * GrPaint equivalents are not modified. GrPaint has fewer stages than
105 * GrDrawState. The extra GrDrawState stages are disabled.
106 */
107 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000108
109 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000110 /// @name Vertex Format
111 ////
112
113 /**
114 * The format of vertices is represented as a bitfield of flags.
115 * Flags that indicate the layout of vertex data. Vertices always contain
116 * positions and may also contain up to GrDrawState::kMaxTexCoords sets
117 * of 2D texture coordinates, per-vertex colors, and per-vertex coverage.
118 * Each stage can
119 * use any of the texture coordinates as its input texture coordinates or it
120 * may use the positions as texture coordinates.
121 *
122 * If no texture coordinates are specified for a stage then the stage is
123 * disabled.
124 *
125 * Only one type of texture coord can be specified per stage. For
126 * example StageTexCoordVertexLayoutBit(0, 2) and
127 * StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
128 *
129 * The order in memory is always (position, texture coord 0, ..., color,
130 * coverage) with any unused fields omitted. Note that this means that if
131 * only texture coordinates 1 is referenced then there is no texture
132 * coordinates 0 and the order would be (position, texture coordinate 1
133 * [, color][, coverage]).
134 */
135
136 /**
137 * Generates a bit indicating that a texture stage uses texture coordinates
138 *
139 * @param stageIdx the stage that will use texture coordinates.
140 * @param texCoordIdx the index of the texture coordinates to use
141 *
142 * @return the bit to add to a GrVertexLayout bitfield.
143 */
144 static int StageTexCoordVertexLayoutBit(int stageIdx, int texCoordIdx) {
145 GrAssert(stageIdx < kNumStages);
146 GrAssert(texCoordIdx < kMaxTexCoords);
147 return 1 << (stageIdx + (texCoordIdx * kNumStages));
148 }
149
150 static bool StageUsesTexCoords(GrVertexLayout layout, int stageIdx);
skia.committer@gmail.comcdcb2ce2013-01-29 07:05:52 +0000151
jvanverth@google.comcc782382013-01-28 20:39:48 +0000152private:
153 // non-stage bits start at this index.
154 static const int STAGE_BIT_CNT = kNumStages * kMaxTexCoords;
155public:
156
157 /**
158 * Additional Bits that can be specified in GrVertexLayout.
159 */
160 enum VertexLayoutBits {
161 /* vertices have colors (GrColor) */
162 kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0),
163 /* vertices have coverage (GrColor)
164 */
165 kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
166 /* Use text vertices. (Pos and tex coords may be a different type for
167 * text [GrGpuTextVertex vs GrPoint].)
168 */
169 kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2),
170
171 /* Each vertex specificies an edge. Distance to the edge is used to
172 * compute a coverage. See GrDrawState::setVertexEdgeType().
173 */
174 kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 3),
175 // for below assert
176 kDummyVertexLayoutBit,
177 kHighVertexLayoutBit = kDummyVertexLayoutBit - 1
178 };
179 // make sure we haven't exceeded the number of bits in GrVertexLayout.
180 GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
181
182 ////////////////////////////////////////////////////////////////////////////
183 // Helpers for picking apart vertex layouts
184
185 /**
186 * Helper function to compute the size of a vertex from a vertex layout
187 * @return size of a single vertex.
188 */
189 static size_t VertexSize(GrVertexLayout vertexLayout);
190
191 /**
192 * Helper function for determining the index of texture coordinates that
193 * is input for a texture stage. Note that a stage may instead use positions
194 * as texture coordinates, in which case the result of the function is
195 * indistinguishable from the case when the stage is disabled.
196 *
197 * @param stageIdx the stage to query
198 * @param vertexLayout layout to query
199 *
200 * @return the texture coordinate index or -1 if the stage doesn't use
201 * separate (non-position) texture coordinates.
202 */
203 static int VertexTexCoordsForStage(int stageIdx, GrVertexLayout vertexLayout);
204
205 /**
206 * Helper function to compute the offset of texture coordinates in a vertex
207 * @return offset of texture coordinates in vertex layout or -1 if the
208 * layout has no texture coordinates. Will be 0 if positions are
209 * used as texture coordinates for the stage.
210 */
211 static int VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout);
212
213 /**
214 * Helper function to compute the offset of the color in a vertex
215 * @return offset of color in vertex layout or -1 if the
216 * layout has no color.
217 */
218 static int VertexColorOffset(GrVertexLayout vertexLayout);
219
220 /**
221 * Helper function to compute the offset of the coverage in a vertex
222 * @return offset of coverage in vertex layout or -1 if the
223 * layout has no coverage.
224 */
225 static int VertexCoverageOffset(GrVertexLayout vertexLayout);
226
227 /**
228 * Helper function to compute the offset of the edge pts in a vertex
229 * @return offset of edge in vertex layout or -1 if the
230 * layout has no edge.
231 */
232 static int VertexEdgeOffset(GrVertexLayout vertexLayout);
233
234 /**
235 * Helper function to determine if vertex layout contains explicit texture
236 * coordinates of some index.
237 *
238 * @param coordIndex the tex coord index to query
239 * @param vertexLayout layout to query
240 *
241 * @return true if vertex specifies texture coordinates for the index,
242 * false otherwise.
243 */
244 static bool VertexUsesTexCoordIdx(int coordIndex,
245 GrVertexLayout vertexLayout);
246
247 /**
248 * Helper function to compute the size of each vertex and the offsets of
249 * texture coordinates and color. Determines tex coord offsets by tex coord
250 * index rather than by stage. (Each stage can be mapped to any t.c. index
251 * by StageTexCoordVertexLayoutBit.)
252 *
253 * @param vertexLayout the layout to query
254 * @param texCoordOffsetsByIdx after return it is the offset of each
255 * tex coord index in the vertex or -1 if
256 * index isn't used. (optional)
257 * @param colorOffset after return it is the offset of the
258 * color field in each vertex, or -1 if
259 * there aren't per-vertex colors. (optional)
260 * @param coverageOffset after return it is the offset of the
261 * coverage field in each vertex, or -1 if
262 * there aren't per-vertex coeverages.
263 * (optional)
264 * @param edgeOffset after return it is the offset of the
265 * edge eq field in each vertex, or -1 if
266 * there aren't per-vertex edge equations.
267 * (optional)
268 * @return size of a single vertex
269 */
270 static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
271 int texCoordOffsetsByIdx[kMaxTexCoords],
272 int *colorOffset,
273 int *coverageOffset,
274 int* edgeOffset);
275
276 /**
277 * Helper function to compute the size of each vertex and the offsets of
278 * texture coordinates and color. Determines tex coord offsets by stage
279 * rather than by index. (Each stage can be mapped to any t.c. index
280 * by StageTexCoordVertexLayoutBit.) If a stage uses positions for
281 * tex coords then that stage's offset will be 0 (positions are always at 0).
282 *
283 * @param vertexLayout the layout to query
284 * @param texCoordOffsetsByStage after return it is the offset of each
285 * tex coord index in the vertex or -1 if
286 * index isn't used. (optional)
287 * @param colorOffset after return it is the offset of the
288 * color field in each vertex, or -1 if
289 * there aren't per-vertex colors.
290 * (optional)
291 * @param coverageOffset after return it is the offset of the
292 * coverage field in each vertex, or -1 if
293 * there aren't per-vertex coeverages.
294 * (optional)
295 * @param edgeOffset after return it is the offset of the
296 * edge eq field in each vertex, or -1 if
297 * there aren't per-vertex edge equations.
298 * (optional)
299 * @return size of a single vertex
300 */
301 static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
302 int texCoordOffsetsByStage[kNumStages],
303 int* colorOffset,
304 int* coverageOffset,
305 int* edgeOffset);
306
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000307 /**
308 * Determines whether src alpha is guaranteed to be one for all src pixels
309 */
310 bool srcAlphaWillBeOne(GrVertexLayout) const;
311
312 /**
313 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
314 */
315 bool hasSolidCoverage(GrVertexLayout) const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000316
317 /**
318 * Accessing positions, texture coords, or colors, of a vertex within an
319 * array is a hassle involving casts and simple math. These helpers exist
320 * to keep GrDrawTarget clients' code a bit nicer looking.
321 */
322
323 /**
324 * Gets a pointer to a GrPoint of a vertex's position or texture
325 * coordinate.
326 * @param vertices the vetex array
327 * @param vertexIndex the index of the vertex in the array
328 * @param vertexSize the size of each vertex in the array
329 * @param offset the offset in bytes of the vertex component.
330 * Defaults to zero (corresponding to vertex position)
331 * @return pointer to the vertex component as a GrPoint
332 */
333 static GrPoint* GetVertexPoint(void* vertices,
334 int vertexIndex,
335 int vertexSize,
336 int offset = 0) {
337 intptr_t start = GrTCast<intptr_t>(vertices);
338 return GrTCast<GrPoint*>(start + offset +
339 vertexIndex * vertexSize);
340 }
341 static const GrPoint* GetVertexPoint(const void* vertices,
342 int vertexIndex,
343 int vertexSize,
344 int offset = 0) {
345 intptr_t start = GrTCast<intptr_t>(vertices);
346 return GrTCast<const GrPoint*>(start + offset +
347 vertexIndex * vertexSize);
348 }
349
350 /**
351 * Gets a pointer to a GrColor inside a vertex within a vertex array.
352 * @param vertices the vetex array
353 * @param vertexIndex the index of the vertex in the array
354 * @param vertexSize the size of each vertex in the array
355 * @param offset the offset in bytes of the vertex color
356 * @return pointer to the vertex component as a GrColor
357 */
358 static GrColor* GetVertexColor(void* vertices,
359 int vertexIndex,
360 int vertexSize,
361 int offset) {
362 intptr_t start = GrTCast<intptr_t>(vertices);
363 return GrTCast<GrColor*>(start + offset +
364 vertexIndex * vertexSize);
365 }
366 static const GrColor* GetVertexColor(const void* vertices,
367 int vertexIndex,
368 int vertexSize,
369 int offset) {
370 const intptr_t start = GrTCast<intptr_t>(vertices);
371 return GrTCast<const GrColor*>(start + offset +
372 vertexIndex * vertexSize);
373 }
374
375 static void VertexLayoutUnitTest();
376
377 /// @}
378
379 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000380 /// @name Color
381 ////
382
383 /**
384 * Sets color for next draw to a premultiplied-alpha color.
385 *
386 * @param color the color to set.
387 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000388 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000389
bsalomon@google.comca432082013-01-23 19:53:46 +0000390 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000391
392 /**
393 * Sets the color to be used for the next draw to be
394 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
395 *
396 * @param alpha The alpha value to set as the color.
397 */
398 void setAlpha(uint8_t a) {
399 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
400 }
401
402 /**
403 * Add a color filter that can be represented by a color and a mode. Applied
404 * after color-computing texture stages.
405 */
406 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000407 fCommon.fColorFilterColor = c;
408 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000409 }
410
bsalomon@google.comca432082013-01-23 19:53:46 +0000411 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
412 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000413
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000414 /**
415 * Constructor sets the color to be 'color' which is undone by the destructor.
416 */
417 class AutoColorRestore : public ::GrNoncopyable {
418 public:
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000419 AutoColorRestore() : fDrawState(NULL) {}
420
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000421 AutoColorRestore(GrDrawState* drawState, GrColor color) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000422 fDrawState = NULL;
423 this->set(drawState, color);
424 }
425
426 void reset() {
427 if (NULL != fDrawState) {
428 fDrawState->setColor(fOldColor);
429 fDrawState = NULL;
430 }
431 }
432
433 void set(GrDrawState* drawState, GrColor color) {
434 this->reset();
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000435 fDrawState = drawState;
436 fOldColor = fDrawState->getColor();
437 fDrawState->setColor(color);
438 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000439
440 ~AutoColorRestore() { this->reset(); }
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000441 private:
442 GrDrawState* fDrawState;
443 GrColor fOldColor;
444 };
445
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000446 /// @}
447
448 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000449 /// @name Coverage
450 ////
451
452 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000453 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000454 * initial value (after construction or reset()) is 0xff. The constant
455 * coverage is ignored when per-vertex coverage is provided.
456 */
457 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000458 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000459 }
460
461 /**
462 * Version of above that specifies 4 channel per-vertex color. The value
463 * should be premultiplied.
464 */
465 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000466 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000467 }
468
469 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000470 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000471 }
472
473 /// @}
474
475 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000476 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 ////
478
bsalomon@google.comadc65362013-01-28 14:26:09 +0000479 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
480 fStages[stageIdx].setEffect(effect);
481 return effect;
482 }
483
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000484 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000485 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000486 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000487 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000488 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000489 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000490 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000491 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000492 void createTextureEffect(int stageIdx,
493 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000494 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000495 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000496 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000497 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000498 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000499 }
500
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000501 bool stagesDisabled() {
502 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000503 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000504 return false;
505 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000506 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000507 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000508 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000509
bsalomon@google.comadc65362013-01-28 14:26:09 +0000510 void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000511
robertphillips@google.com972265d2012-06-13 18:49:30 +0000512 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000513 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000514 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000515 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000516 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000517 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000518 }
519 }
520
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000521 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000522 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000523 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
524 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000525 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000526 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000527 }
528 }
529 private:
530 GrDrawState* fDrawState;
531 };
532
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000533 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000534 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000535 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000536 const GrEffectStage& getStage(int stageIdx) const {
537 GrAssert((unsigned)stageIdx < kNumStages);
538 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000539 }
540
541 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000542 * Called when the source coord system is changing. preConcat gives the transformation from the
543 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000545 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000546 this->preConcatStageMatrices(~0U, preConcat);
547 }
548 /**
549 * Version of above that applies the update matrix selectively to stages via a mask.
550 */
551 void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000552 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000553 if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000554 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000555 }
556 }
557 }
558
bsalomon@google.come3d32162012-07-20 13:37:06 +0000559 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000560 * Called when the source coord system is changing. preConcatInverse is the inverse of the
561 * transformation from the old coord system to the new coord system. Returns false if the matrix
562 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000563 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000564 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
565 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000566 bool computed = false;
567 for (int i = 0; i < kNumStages; ++i) {
568 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000569 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000570 return false;
571 } else {
572 computed = true;
573 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000574 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000575 }
576 }
577 return true;
578 }
579
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580 /// @}
581
582 ///////////////////////////////////////////////////////////////////////////
583 /// @name Coverage / Color Stages
584 ////
585
586 /**
587 * A common pattern is to compute a color with the initial stages and then
588 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000589 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
590 * computed based on the pre-coverage-modulated color. The division of
591 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 * this method. Initially this is kNumStages (all stages
593 * are color-computing).
594 */
595 void setFirstCoverageStage(int firstCoverageStage) {
596 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000597 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000598 }
599
600 /**
601 * Gets the index of the first coverage-computing stage.
602 */
603 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000604 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000605 }
606
607 ///@}
608
609 ///////////////////////////////////////////////////////////////////////////
610 /// @name Blending
611 ////
612
613 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000614 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000615 *
616 * The blend function will be:
617 * D' = sat(S*srcCoef + D*dstCoef)
618 *
619 * where D is the existing destination color, S is the incoming source
620 * color, and D' is the new destination color that will be written. sat()
621 * is the saturation function.
622 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000623 * @param srcCoef coefficient applied to the src color.
624 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000625 */
626 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000627 fCommon.fSrcBlend = srcCoeff;
628 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000629 #if GR_DEBUG
630 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000631 case kDC_GrBlendCoeff:
632 case kIDC_GrBlendCoeff:
633 case kDA_GrBlendCoeff:
634 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000635 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
636 "coverage stages.\n");
637 break;
638 default:
639 break;
640 }
641 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000642 case kSC_GrBlendCoeff:
643 case kISC_GrBlendCoeff:
644 case kSA_GrBlendCoeff:
645 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
647 "coverage stages.\n");
648 break;
649 default:
650 break;
651 }
652 #endif
653 }
654
bsalomon@google.comca432082013-01-23 19:53:46 +0000655 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
656 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000657
658 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
659 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000660 *srcBlendCoeff = fCommon.fSrcBlend;
661 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000662 }
663
664 /**
665 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000666 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000667 * kConstC_GrBlendCoeff
668 * kIConstC_GrBlendCoeff
669 * kConstA_GrBlendCoeff
670 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000671 *
672 * @param constant the constant to set
673 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000674 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675
676 /**
677 * Retrieves the last value set by setBlendConstant()
678 * @return the blending constant value
679 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000680 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000681
682 /// @}
683
684 ///////////////////////////////////////////////////////////////////////////
685 /// @name View Matrix
686 ////
687
688 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000689 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000690 *
691 * In the post-view-matrix space the rectangle [0,w]x[0,h]
692 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000693 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000694 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000695 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696
697 /**
698 * Gets a writable pointer to the view matrix.
699 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000700 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701
702 /**
703 * Multiplies the current view matrix by a matrix
704 *
705 * After this call V' = V*m where V is the old view matrix,
706 * m is the parameter to this function, and V' is the new view matrix.
707 * (We consider positions to be column vectors so position vector p is
708 * transformed by matrix X as p' = X*p.)
709 *
710 * @param m the matrix used to modify the view matrix.
711 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000712 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000713
714 /**
715 * Multiplies the current view matrix by a matrix
716 *
717 * After this call V' = m*V where V is the old view matrix,
718 * m is the parameter to this function, and V' is the new view matrix.
719 * (We consider positions to be column vectors so position vector p is
720 * transformed by matrix X as p' = X*p.)
721 *
722 * @param m the matrix used to modify the view matrix.
723 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000724 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000725
726 /**
727 * Retrieves the current view matrix
728 * @return the current view matrix.
729 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000730 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000731
732 /**
733 * Retrieves the inverse of the current view matrix.
734 *
735 * If the current view matrix is invertible, return true, and if matrix
736 * is non-null, copy the inverse into it. If the current view matrix is
737 * non-invertible, return false and ignore the matrix parameter.
738 *
739 * @param matrix if not null, will receive a copy of the current inverse.
740 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000741 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000742 // TODO: determine whether we really need to leave matrix unmodified
743 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000744 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000745 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 if (matrix) {
747 *matrix = inverse;
748 }
749 return true;
750 }
751 return false;
752 }
753
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000754 ////////////////////////////////////////////////////////////////////////////
755
756 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000757 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000758 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000759 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000760 class AutoViewMatrixRestore : public ::GrNoncopyable {
761 public:
762 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000763
764 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000765 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000766 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000767 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000768 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000769 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000770
771 ~AutoViewMatrixRestore() { this->restore(); }
772
bsalomon@google.coma8347462012-10-08 18:59:39 +0000773 /**
774 * Can be called prior to destructor to restore the original matrix.
775 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000776 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000777
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000778 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000779 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000780 uint32_t explicitCoordStageMask = 0);
781
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000782 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000783
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000784 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000785 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000786 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000787 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000788 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000789 };
790
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000791 ////////////////////////////////////////////////////////////////////////////
792
793 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000794 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
795 * destructor undoes the changes, restoring the view matrix that was set before the
796 * constructor. It is similar to passing the inverse of the current view matrix to
797 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000798 */
799 class AutoDeviceCoordDraw : ::GrNoncopyable {
800 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000801 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000802 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000803 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
804 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
805 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000806 */
807 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000808 uint32_t explicitCoordStageMask = 0) {
809 fDrawState = NULL;
810 this->set(drawState, explicitCoordStageMask);
811 }
812
bsalomon@google.coma8347462012-10-08 18:59:39 +0000813 ~AutoDeviceCoordDraw() { this->restore(); }
814
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000815 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
816
bsalomon@google.coma8347462012-10-08 18:59:39 +0000817 /**
818 * Returns true if this object was successfully initialized on to a GrDrawState. It may
819 * return false because a non-default constructor or set() were never called or because
820 * the view matrix was not invertible.
821 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000822 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000823
bsalomon@google.coma8347462012-10-08 18:59:39 +0000824 /**
825 * Returns the matrix that was set previously set on the drawState. This is only valid
826 * if succeeded returns true.
827 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000828 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000829 GrAssert(this->succeeded());
830 return fViewMatrix;
831 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000832
bsalomon@google.coma8347462012-10-08 18:59:39 +0000833 /**
834 * Can be called prior to destructor to restore the original matrix.
835 */
836 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000837
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000838 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000839 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000840 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000841 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000842 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000843 };
844
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 /// @}
846
847 ///////////////////////////////////////////////////////////////////////////
848 /// @name Render Target
849 ////
850
851 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000852 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000853 *
854 * @param target The render target to set.
855 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000856 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000857 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000858 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000859
860 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000861 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000862 *
863 * @return The currently set render target.
864 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000865 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
866 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000867
868 class AutoRenderTargetRestore : public ::GrNoncopyable {
869 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000870 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000871 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
872 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000873 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000874 this->set(ds, newTarget);
875 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000876 ~AutoRenderTargetRestore() { this->restore(); }
877
878 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000879 if (NULL != fDrawState) {
880 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000881 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000882 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000883 GrSafeSetNull(fSavedTarget);
884 }
885
886 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
887 this->restore();
888
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000889 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000890 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000891 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000892 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000893 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000894 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000895 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000896 }
897 private:
898 GrDrawState* fDrawState;
899 GrRenderTarget* fSavedTarget;
900 };
901
902 /// @}
903
904 ///////////////////////////////////////////////////////////////////////////
905 /// @name Stencil
906 ////
907
908 /**
909 * Sets the stencil settings to use for the next draw.
910 * Changing the clip has the side-effect of possibly zeroing
911 * out the client settable stencil bits. So multipass algorithms
912 * using stencil should not change the clip between passes.
913 * @param settings the stencil settings to use.
914 */
915 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000916 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000917 }
918
919 /**
920 * Shortcut to disable stencil testing and ops.
921 */
922 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000923 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000924 }
925
bsalomon@google.comca432082013-01-23 19:53:46 +0000926 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000927
bsalomon@google.comca432082013-01-23 19:53:46 +0000928 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000929
930 /// @}
931
932 ///////////////////////////////////////////////////////////////////////////
933 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000934 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000935 // edges are specified as per-vertex data, vertices that are shared by
936 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000937 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000938 ////
939
940 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000941 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000942 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000943 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000944 *
945 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
946 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000947 */
948 enum VertexEdgeType {
949 /* 1-pixel wide line
950 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
951 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000952 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000953 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000954 being inside, positive outside. Edge specified in window space
955 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000956 kQuad_EdgeType,
957 /* Same as above but for hairline quadratics. Uses unsigned distance.
958 Coverage is min(0, 1-distance). */
959 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000960 /* Circle specified as center_x, center_y, outer_radius, inner_radius
961 all in window space (y-down). */
962 kCircle_EdgeType,
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000963 /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
964 all in window space (y-down). */
965 kEllipse_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000966
967 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000968 };
969
970 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000971 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000972 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
973 * are not specified the value of this setting has no effect.
974 */
975 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000976 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.comca432082013-01-23 19:53:46 +0000977 fCommon.fVertexEdgeType = type;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000978 }
979
bsalomon@google.comca432082013-01-23 19:53:46 +0000980 VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000981
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000982 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000983
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000984 ///////////////////////////////////////////////////////////////////////////
985 /// @name State Flags
986 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000987
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000988 /**
989 * Flags that affect rendering. Controlled using enable/disableState(). All
990 * default to disabled.
991 */
992 enum StateBits {
993 /**
994 * Perform dithering. TODO: Re-evaluate whether we need this bit
995 */
996 kDither_StateBit = 0x01,
997 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000998 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
999 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
1000 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001001 */
1002 kHWAntialias_StateBit = 0x02,
1003 /**
1004 * Draws will respect the clip, otherwise the clip is ignored.
1005 */
1006 kClip_StateBit = 0x04,
1007 /**
1008 * Disables writing to the color buffer. Useful when performing stencil
1009 * operations.
1010 */
1011 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +00001012
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001013 /**
1014 * Usually coverage is applied after color blending. The color is blended using the coeffs
1015 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
1016 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
1017 * this case there is no distinction between coverage and color and the caller needs direct
1018 * control over the blend coeffs. When set, there will be a single blend step controlled by
1019 * setBlendFunc() which will use coverage*color as the src color.
1020 */
1021 kCoverageDrawing_StateBit = 0x10,
1022
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001023 // Users of the class may add additional bits to the vector
1024 kDummyStateBit,
1025 kLastPublicStateBit = kDummyStateBit-1,
1026 };
1027
1028 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +00001029 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001030 }
1031
1032 /**
1033 * Enable render state settings.
1034 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001035 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001036 */
1037 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001038 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001039 }
1040
1041 /**
1042 * Disable render state settings.
1043 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001044 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001045 */
1046 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001047 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001048 }
1049
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001050 /**
1051 * Enable or disable stateBits based on a boolean.
1052 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001053 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001054 * @param enable if true enable stateBits, otherwise disable
1055 */
1056 void setState(uint32_t stateBits, bool enable) {
1057 if (enable) {
1058 this->enableState(stateBits);
1059 } else {
1060 this->disableState(stateBits);
1061 }
1062 }
1063
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001064 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001065 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001066 }
1067
1068 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001069 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001070 }
1071
1072 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001073 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001074 }
1075
1076 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001077 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001078 }
1079
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001080 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001081 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001082 }
1083
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001084 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001085 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001086 }
1087
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001088 /// @}
1089
1090 ///////////////////////////////////////////////////////////////////////////
1091 /// @name Face Culling
1092 ////
1093
1094 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001095 kInvalid_DrawFace = -1,
1096
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001097 kBoth_DrawFace,
1098 kCCW_DrawFace,
1099 kCW_DrawFace,
1100 };
1101
1102 /**
1103 * Controls whether clockwise, counterclockwise, or both faces are drawn.
1104 * @param face the face(s) to draw.
1105 */
1106 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001107 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +00001108 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001109 }
1110
1111 /**
1112 * Gets whether the target is drawing clockwise, counterclockwise,
1113 * or both faces.
1114 * @return the current draw face(s).
1115 */
bsalomon@google.comca432082013-01-23 19:53:46 +00001116 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +00001117
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001118 /// @}
1119
1120 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001121
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001122 bool isStageEnabled(int s) const {
1123 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001124 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001125 }
1126
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001127 // Most stages are usually not used, so conditionals here
1128 // reduce the expected number of bytes touched by 50%.
1129 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001130 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001131 return false;
1132 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001133
1134 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001135 bool enabled = this->isStageEnabled(i);
1136 if (enabled != s.isStageEnabled(i)) {
1137 return false;
1138 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001139 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001140 return false;
1141 }
1142 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001143 return true;
1144 }
1145 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1146
bsalomon@google.comca432082013-01-23 19:53:46 +00001147 GrDrawState& operator= (const GrDrawState& s) {
1148 this->setRenderTarget(s.fRenderTarget.get());
1149 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001150 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001151 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001152 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001153 }
1154 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001155 return *this;
1156 }
1157
1158private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001159
bsalomon@google.comca432082013-01-23 19:53:46 +00001160 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1161 struct CommonState {
1162 // These fields are roughly sorted by decreasing likelihood of being different in op==
1163 GrColor fColor;
1164 SkMatrix fViewMatrix;
1165 GrBlendCoeff fSrcBlend;
1166 GrBlendCoeff fDstBlend;
1167 GrColor fBlendConstant;
1168 uint32_t fFlagBits;
1169 VertexEdgeType fVertexEdgeType;
1170 GrStencilSettings fStencilSettings;
1171 int fFirstCoverageStage;
1172 GrColor fCoverage;
1173 SkXfermode::Mode fColorFilterMode;
1174 GrColor fColorFilterColor;
1175 DrawFace fDrawFace;
1176 bool operator== (const CommonState& other) const {
1177 return fColor == other.fColor &&
1178 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1179 fSrcBlend == other.fSrcBlend &&
1180 fDstBlend == other.fDstBlend &&
1181 fBlendConstant == other.fBlendConstant &&
1182 fFlagBits == other.fFlagBits &&
1183 fVertexEdgeType == other.fVertexEdgeType &&
1184 fStencilSettings == other.fStencilSettings &&
1185 fFirstCoverageStage == other.fFirstCoverageStage &&
1186 fCoverage == other.fCoverage &&
1187 fColorFilterMode == other.fColorFilterMode &&
1188 fColorFilterColor == other.fColorFilterColor &&
1189 fDrawFace == other.fDrawFace;
1190 }
1191 bool operator!= (const CommonState& other) const { return !(*this == other); }
1192 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001193
bsalomon@google.comca432082013-01-23 19:53:46 +00001194 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1195 DeferredState must directly reference GrEffects, however. */
1196 struct SavedEffectStage {
1197 SavedEffectStage() : fEffect(NULL) {}
1198 const GrEffect* fEffect;
1199 GrEffectStage::SavedCoordChange fCoordChange;
1200 };
1201
1202public:
1203 /**
1204 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1205 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1206 * dispose mechanism returns them to the cache. This allows recycling resources through the
1207 * the cache while they are in a deferred draw queue.
1208 */
1209 class DeferredState {
1210 public:
1211 DeferredState() : fRenderTarget(NULL) {
1212 GR_DEBUGCODE(fInitialized = false;)
1213 }
1214 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1215 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1216
1217 void saveFrom(const GrDrawState& drawState) {
1218 fCommon = drawState.fCommon;
1219 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1220 fRenderTarget = drawState.fRenderTarget.get();
1221 SkSafeRef(fRenderTarget);
1222 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1223 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1224 // and recycle them to the cache (if no one else is holding a ref to the resources).
1225 for (int i = 0; i < kNumStages; ++i) {
1226 fStages[i].saveFrom(drawState.fStages[i]);
1227 }
1228 GR_DEBUGCODE(fInitialized = true;)
1229 }
1230
1231 void restoreTo(GrDrawState* drawState) {
1232 GrAssert(fInitialized);
1233 drawState->fCommon = fCommon;
1234 drawState->setRenderTarget(fRenderTarget);
1235 for (int i = 0; i < kNumStages; ++i) {
1236 fStages[i].restoreTo(&drawState->fStages[i]);
1237 }
1238 }
1239
1240 bool isEqual(const GrDrawState& state) const {
1241 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1242 return false;
1243 }
1244 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001245 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001246 return false;
1247 }
1248 }
1249 return true;
1250 }
1251
1252 private:
1253 GrRenderTarget* fRenderTarget;
1254 CommonState fCommon;
1255 GrEffectStage::DeferredStage fStages[kNumStages];
1256
1257 GR_DEBUGCODE(bool fInitialized;)
1258 };
1259
1260private:
1261 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1262 CommonState fCommon;
1263 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001264
reed@google.comfa35e3d2012-06-26 20:16:17 +00001265 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001266};
1267
1268#endif