blob: a3a41b334dd97c2dd31dcb1c270912b50c64d1dd [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);
151
152private:
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
307 // determine if src alpha is guaranteed to be one for all src pixels
308 bool srcAlphaWillBeOne(GrVertexLayout vertexLayout) const;
309
310 /**
311 * Accessing positions, texture coords, or colors, of a vertex within an
312 * array is a hassle involving casts and simple math. These helpers exist
313 * to keep GrDrawTarget clients' code a bit nicer looking.
314 */
315
316 /**
317 * Gets a pointer to a GrPoint of a vertex's position or texture
318 * coordinate.
319 * @param vertices the vetex array
320 * @param vertexIndex the index of the vertex in the array
321 * @param vertexSize the size of each vertex in the array
322 * @param offset the offset in bytes of the vertex component.
323 * Defaults to zero (corresponding to vertex position)
324 * @return pointer to the vertex component as a GrPoint
325 */
326 static GrPoint* GetVertexPoint(void* vertices,
327 int vertexIndex,
328 int vertexSize,
329 int offset = 0) {
330 intptr_t start = GrTCast<intptr_t>(vertices);
331 return GrTCast<GrPoint*>(start + offset +
332 vertexIndex * vertexSize);
333 }
334 static const GrPoint* GetVertexPoint(const void* vertices,
335 int vertexIndex,
336 int vertexSize,
337 int offset = 0) {
338 intptr_t start = GrTCast<intptr_t>(vertices);
339 return GrTCast<const GrPoint*>(start + offset +
340 vertexIndex * vertexSize);
341 }
342
343 /**
344 * Gets a pointer to a GrColor inside a vertex within a vertex array.
345 * @param vertices the vetex array
346 * @param vertexIndex the index of the vertex in the array
347 * @param vertexSize the size of each vertex in the array
348 * @param offset the offset in bytes of the vertex color
349 * @return pointer to the vertex component as a GrColor
350 */
351 static GrColor* GetVertexColor(void* vertices,
352 int vertexIndex,
353 int vertexSize,
354 int offset) {
355 intptr_t start = GrTCast<intptr_t>(vertices);
356 return GrTCast<GrColor*>(start + offset +
357 vertexIndex * vertexSize);
358 }
359 static const GrColor* GetVertexColor(const void* vertices,
360 int vertexIndex,
361 int vertexSize,
362 int offset) {
363 const intptr_t start = GrTCast<intptr_t>(vertices);
364 return GrTCast<const GrColor*>(start + offset +
365 vertexIndex * vertexSize);
366 }
367
368 static void VertexLayoutUnitTest();
369
370 /// @}
371
372 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000373 /// @name Color
374 ////
375
376 /**
377 * Sets color for next draw to a premultiplied-alpha color.
378 *
379 * @param color the color to set.
380 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000381 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000382
bsalomon@google.comca432082013-01-23 19:53:46 +0000383 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000384
385 /**
386 * Sets the color to be used for the next draw to be
387 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
388 *
389 * @param alpha The alpha value to set as the color.
390 */
391 void setAlpha(uint8_t a) {
392 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
393 }
394
395 /**
396 * Add a color filter that can be represented by a color and a mode. Applied
397 * after color-computing texture stages.
398 */
399 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000400 fCommon.fColorFilterColor = c;
401 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000402 }
403
bsalomon@google.comca432082013-01-23 19:53:46 +0000404 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
405 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000406
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000407 /**
408 * Constructor sets the color to be 'color' which is undone by the destructor.
409 */
410 class AutoColorRestore : public ::GrNoncopyable {
411 public:
412 AutoColorRestore(GrDrawState* drawState, GrColor color) {
413 fDrawState = drawState;
414 fOldColor = fDrawState->getColor();
415 fDrawState->setColor(color);
416 }
417 ~AutoColorRestore() {
418 fDrawState->setColor(fOldColor);
419 }
420 private:
421 GrDrawState* fDrawState;
422 GrColor fOldColor;
423 };
424
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000425 /// @}
426
427 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000428 /// @name Coverage
429 ////
430
431 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000432 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000433 * initial value (after construction or reset()) is 0xff. The constant
434 * coverage is ignored when per-vertex coverage is provided.
435 */
436 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000437 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000438 }
439
440 /**
441 * Version of above that specifies 4 channel per-vertex color. The value
442 * should be premultiplied.
443 */
444 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000445 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000446 }
447
448 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000449 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000450 }
451
452 /// @}
453
454 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000455 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000456 ////
457
bsalomon@google.comadc65362013-01-28 14:26:09 +0000458 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
459 fStages[stageIdx].setEffect(effect);
460 return effect;
461 }
462
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000463 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000464 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000465 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000466 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000467 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000468 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000469 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000470 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000471 void createTextureEffect(int stageIdx,
472 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000473 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000474 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000475 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000476 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000477 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000478 }
479
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000480 bool stagesDisabled() {
481 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000482 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000483 return false;
484 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000485 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000486 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000487 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000488
bsalomon@google.comadc65362013-01-28 14:26:09 +0000489 void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000490
robertphillips@google.com972265d2012-06-13 18:49:30 +0000491 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000492 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000493 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000494 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000495 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000496 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000497 }
498 }
499
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000500 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000501 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000502 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
503 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000504 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000505 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000506 }
507 }
508 private:
509 GrDrawState* fDrawState;
510 };
511
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000513 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000514 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000515 const GrEffectStage& getStage(int stageIdx) const {
516 GrAssert((unsigned)stageIdx < kNumStages);
517 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000518 }
519
520 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000521 * Called when the source coord system is changing. preConcat gives the transformation from the
522 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000523 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000524 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000525 this->preConcatStageMatrices(~0U, preConcat);
526 }
527 /**
528 * Version of above that applies the update matrix selectively to stages via a mask.
529 */
530 void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000532 if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000533 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000534 }
535 }
536 }
537
bsalomon@google.come3d32162012-07-20 13:37:06 +0000538 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000539 * Called when the source coord system is changing. preConcatInverse is the inverse of the
540 * transformation from the old coord system to the new coord system. Returns false if the matrix
541 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000542 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000543 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
544 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000545 bool computed = false;
546 for (int i = 0; i < kNumStages; ++i) {
547 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000548 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000549 return false;
550 } else {
551 computed = true;
552 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000553 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000554 }
555 }
556 return true;
557 }
558
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000559 /// @}
560
561 ///////////////////////////////////////////////////////////////////////////
562 /// @name Coverage / Color Stages
563 ////
564
565 /**
566 * A common pattern is to compute a color with the initial stages and then
567 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000568 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
569 * computed based on the pre-coverage-modulated color. The division of
570 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000571 * this method. Initially this is kNumStages (all stages
572 * are color-computing).
573 */
574 void setFirstCoverageStage(int firstCoverageStage) {
575 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000576 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000577 }
578
579 /**
580 * Gets the index of the first coverage-computing stage.
581 */
582 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000583 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000584 }
585
586 ///@}
587
588 ///////////////////////////////////////////////////////////////////////////
589 /// @name Blending
590 ////
591
592 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000593 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000594 *
595 * The blend function will be:
596 * D' = sat(S*srcCoef + D*dstCoef)
597 *
598 * where D is the existing destination color, S is the incoming source
599 * color, and D' is the new destination color that will be written. sat()
600 * is the saturation function.
601 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000602 * @param srcCoef coefficient applied to the src color.
603 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000604 */
605 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000606 fCommon.fSrcBlend = srcCoeff;
607 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 #if GR_DEBUG
609 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000610 case kDC_GrBlendCoeff:
611 case kIDC_GrBlendCoeff:
612 case kDA_GrBlendCoeff:
613 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000614 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
615 "coverage stages.\n");
616 break;
617 default:
618 break;
619 }
620 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000621 case kSC_GrBlendCoeff:
622 case kISC_GrBlendCoeff:
623 case kSA_GrBlendCoeff:
624 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000625 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
626 "coverage stages.\n");
627 break;
628 default:
629 break;
630 }
631 #endif
632 }
633
bsalomon@google.comca432082013-01-23 19:53:46 +0000634 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
635 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000636
637 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
638 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000639 *srcBlendCoeff = fCommon.fSrcBlend;
640 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641 }
642
643 /**
644 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000645 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000646 * kConstC_GrBlendCoeff
647 * kIConstC_GrBlendCoeff
648 * kConstA_GrBlendCoeff
649 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000650 *
651 * @param constant the constant to set
652 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000653 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654
655 /**
656 * Retrieves the last value set by setBlendConstant()
657 * @return the blending constant value
658 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000659 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000660
661 /// @}
662
663 ///////////////////////////////////////////////////////////////////////////
664 /// @name View Matrix
665 ////
666
667 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000668 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000669 *
670 * In the post-view-matrix space the rectangle [0,w]x[0,h]
671 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000672 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000673 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000674 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675
676 /**
677 * Gets a writable pointer to the view matrix.
678 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000679 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000680
681 /**
682 * Multiplies the current view matrix by a matrix
683 *
684 * After this call V' = V*m where V is the old view matrix,
685 * m is the parameter to this function, and V' is the new view matrix.
686 * (We consider positions to be column vectors so position vector p is
687 * transformed by matrix X as p' = X*p.)
688 *
689 * @param m the matrix used to modify the view matrix.
690 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000691 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000692
693 /**
694 * Multiplies the current view matrix by a matrix
695 *
696 * After this call V' = m*V where V is the old view matrix,
697 * m is the parameter to this function, and V' is the new view matrix.
698 * (We consider positions to be column vectors so position vector p is
699 * transformed by matrix X as p' = X*p.)
700 *
701 * @param m the matrix used to modify the view matrix.
702 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000703 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000704
705 /**
706 * Retrieves the current view matrix
707 * @return the current view matrix.
708 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000709 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000710
711 /**
712 * Retrieves the inverse of the current view matrix.
713 *
714 * If the current view matrix is invertible, return true, and if matrix
715 * is non-null, copy the inverse into it. If the current view matrix is
716 * non-invertible, return false and ignore the matrix parameter.
717 *
718 * @param matrix if not null, will receive a copy of the current inverse.
719 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000720 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000721 // TODO: determine whether we really need to leave matrix unmodified
722 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000723 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000724 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000725 if (matrix) {
726 *matrix = inverse;
727 }
728 return true;
729 }
730 return false;
731 }
732
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000733 ////////////////////////////////////////////////////////////////////////////
734
735 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000736 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000737 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000738 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000739 class AutoViewMatrixRestore : public ::GrNoncopyable {
740 public:
741 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000742
743 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000744 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000745 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000747 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000748 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000749
750 ~AutoViewMatrixRestore() { this->restore(); }
751
bsalomon@google.coma8347462012-10-08 18:59:39 +0000752 /**
753 * Can be called prior to destructor to restore the original matrix.
754 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000755 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000756
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000757 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000758 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000759 uint32_t explicitCoordStageMask = 0);
760
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000761 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000762
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000763 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000764 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000765 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000766 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000767 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000768 };
769
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000770 ////////////////////////////////////////////////////////////////////////////
771
772 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000773 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
774 * destructor undoes the changes, restoring the view matrix that was set before the
775 * constructor. It is similar to passing the inverse of the current view matrix to
776 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000777 */
778 class AutoDeviceCoordDraw : ::GrNoncopyable {
779 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000780 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000781 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000782 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
783 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
784 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000785 */
786 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000787 uint32_t explicitCoordStageMask = 0) {
788 fDrawState = NULL;
789 this->set(drawState, explicitCoordStageMask);
790 }
791
bsalomon@google.coma8347462012-10-08 18:59:39 +0000792 ~AutoDeviceCoordDraw() { this->restore(); }
793
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000794 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
795
bsalomon@google.coma8347462012-10-08 18:59:39 +0000796 /**
797 * Returns true if this object was successfully initialized on to a GrDrawState. It may
798 * return false because a non-default constructor or set() were never called or because
799 * the view matrix was not invertible.
800 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000801 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000802
bsalomon@google.coma8347462012-10-08 18:59:39 +0000803 /**
804 * Returns the matrix that was set previously set on the drawState. This is only valid
805 * if succeeded returns true.
806 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000807 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000808 GrAssert(this->succeeded());
809 return fViewMatrix;
810 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000811
bsalomon@google.coma8347462012-10-08 18:59:39 +0000812 /**
813 * Can be called prior to destructor to restore the original matrix.
814 */
815 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000816
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000817 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000818 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000819 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000820 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000821 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000822 };
823
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000824 /// @}
825
826 ///////////////////////////////////////////////////////////////////////////
827 /// @name Render Target
828 ////
829
830 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000831 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000832 *
833 * @param target The render target to set.
834 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000835 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000836 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000837 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000838
839 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000840 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 *
842 * @return The currently set render target.
843 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000844 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
845 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000846
847 class AutoRenderTargetRestore : public ::GrNoncopyable {
848 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000849 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000850 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
851 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000852 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000853 this->set(ds, newTarget);
854 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000855 ~AutoRenderTargetRestore() { this->restore(); }
856
857 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000858 if (NULL != fDrawState) {
859 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000860 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000861 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000862 GrSafeSetNull(fSavedTarget);
863 }
864
865 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
866 this->restore();
867
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000868 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000869 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000871 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000872 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000873 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000874 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000875 }
876 private:
877 GrDrawState* fDrawState;
878 GrRenderTarget* fSavedTarget;
879 };
880
881 /// @}
882
883 ///////////////////////////////////////////////////////////////////////////
884 /// @name Stencil
885 ////
886
887 /**
888 * Sets the stencil settings to use for the next draw.
889 * Changing the clip has the side-effect of possibly zeroing
890 * out the client settable stencil bits. So multipass algorithms
891 * using stencil should not change the clip between passes.
892 * @param settings the stencil settings to use.
893 */
894 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000895 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000896 }
897
898 /**
899 * Shortcut to disable stencil testing and ops.
900 */
901 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000902 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000903 }
904
bsalomon@google.comca432082013-01-23 19:53:46 +0000905 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000906
bsalomon@google.comca432082013-01-23 19:53:46 +0000907 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000908
909 /// @}
910
911 ///////////////////////////////////////////////////////////////////////////
912 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000913 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000914 // edges are specified as per-vertex data, vertices that are shared by
915 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000917 ////
918
919 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000920 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000921 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000922 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000923 *
924 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
925 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000926 */
927 enum VertexEdgeType {
928 /* 1-pixel wide line
929 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
930 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000931 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000932 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000933 being inside, positive outside. Edge specified in window space
934 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000935 kQuad_EdgeType,
936 /* Same as above but for hairline quadratics. Uses unsigned distance.
937 Coverage is min(0, 1-distance). */
938 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000939 /* Circle specified as center_x, center_y, outer_radius, inner_radius
940 all in window space (y-down). */
941 kCircle_EdgeType,
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000942 /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
943 all in window space (y-down). */
944 kEllipse_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000945
946 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000947 };
948
949 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000950 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000951 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
952 * are not specified the value of this setting has no effect.
953 */
954 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000955 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.comca432082013-01-23 19:53:46 +0000956 fCommon.fVertexEdgeType = type;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000957 }
958
bsalomon@google.comca432082013-01-23 19:53:46 +0000959 VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000960
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000961 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000962
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000963 ///////////////////////////////////////////////////////////////////////////
964 /// @name State Flags
965 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000966
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000967 /**
968 * Flags that affect rendering. Controlled using enable/disableState(). All
969 * default to disabled.
970 */
971 enum StateBits {
972 /**
973 * Perform dithering. TODO: Re-evaluate whether we need this bit
974 */
975 kDither_StateBit = 0x01,
976 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000977 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
978 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
979 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000980 */
981 kHWAntialias_StateBit = 0x02,
982 /**
983 * Draws will respect the clip, otherwise the clip is ignored.
984 */
985 kClip_StateBit = 0x04,
986 /**
987 * Disables writing to the color buffer. Useful when performing stencil
988 * operations.
989 */
990 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000991
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000992 /**
993 * Usually coverage is applied after color blending. The color is blended using the coeffs
994 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
995 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
996 * this case there is no distinction between coverage and color and the caller needs direct
997 * control over the blend coeffs. When set, there will be a single blend step controlled by
998 * setBlendFunc() which will use coverage*color as the src color.
999 */
1000 kCoverageDrawing_StateBit = 0x10,
1001
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001002 // Users of the class may add additional bits to the vector
1003 kDummyStateBit,
1004 kLastPublicStateBit = kDummyStateBit-1,
1005 };
1006
1007 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +00001008 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001009 }
1010
1011 /**
1012 * Enable render state settings.
1013 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001014 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001015 */
1016 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001017 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001018 }
1019
1020 /**
1021 * Disable render state settings.
1022 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001023 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001024 */
1025 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001026 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001027 }
1028
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001029 /**
1030 * Enable or disable stateBits based on a boolean.
1031 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001032 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001033 * @param enable if true enable stateBits, otherwise disable
1034 */
1035 void setState(uint32_t stateBits, bool enable) {
1036 if (enable) {
1037 this->enableState(stateBits);
1038 } else {
1039 this->disableState(stateBits);
1040 }
1041 }
1042
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001043 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001044 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001045 }
1046
1047 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001048 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001049 }
1050
1051 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001052 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001053 }
1054
1055 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001056 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001057 }
1058
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001059 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001060 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001061 }
1062
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001063 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001064 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001065 }
1066
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001067 /// @}
1068
1069 ///////////////////////////////////////////////////////////////////////////
1070 /// @name Face Culling
1071 ////
1072
1073 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001074 kInvalid_DrawFace = -1,
1075
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001076 kBoth_DrawFace,
1077 kCCW_DrawFace,
1078 kCW_DrawFace,
1079 };
1080
1081 /**
1082 * Controls whether clockwise, counterclockwise, or both faces are drawn.
1083 * @param face the face(s) to draw.
1084 */
1085 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001086 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +00001087 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001088 }
1089
1090 /**
1091 * Gets whether the target is drawing clockwise, counterclockwise,
1092 * or both faces.
1093 * @return the current draw face(s).
1094 */
bsalomon@google.comca432082013-01-23 19:53:46 +00001095 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +00001096
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001097 /// @}
1098
1099 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001100
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001101 bool isStageEnabled(int s) const {
1102 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001103 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001104 }
1105
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001106 // Most stages are usually not used, so conditionals here
1107 // reduce the expected number of bytes touched by 50%.
1108 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001109 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001110 return false;
1111 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001112
1113 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001114 bool enabled = this->isStageEnabled(i);
1115 if (enabled != s.isStageEnabled(i)) {
1116 return false;
1117 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001118 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001119 return false;
1120 }
1121 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001122 return true;
1123 }
1124 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1125
bsalomon@google.comca432082013-01-23 19:53:46 +00001126 GrDrawState& operator= (const GrDrawState& s) {
1127 this->setRenderTarget(s.fRenderTarget.get());
1128 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001129 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001130 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001131 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001132 }
1133 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001134 return *this;
1135 }
1136
1137private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001138
bsalomon@google.comca432082013-01-23 19:53:46 +00001139 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1140 struct CommonState {
1141 // These fields are roughly sorted by decreasing likelihood of being different in op==
1142 GrColor fColor;
1143 SkMatrix fViewMatrix;
1144 GrBlendCoeff fSrcBlend;
1145 GrBlendCoeff fDstBlend;
1146 GrColor fBlendConstant;
1147 uint32_t fFlagBits;
1148 VertexEdgeType fVertexEdgeType;
1149 GrStencilSettings fStencilSettings;
1150 int fFirstCoverageStage;
1151 GrColor fCoverage;
1152 SkXfermode::Mode fColorFilterMode;
1153 GrColor fColorFilterColor;
1154 DrawFace fDrawFace;
1155 bool operator== (const CommonState& other) const {
1156 return fColor == other.fColor &&
1157 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1158 fSrcBlend == other.fSrcBlend &&
1159 fDstBlend == other.fDstBlend &&
1160 fBlendConstant == other.fBlendConstant &&
1161 fFlagBits == other.fFlagBits &&
1162 fVertexEdgeType == other.fVertexEdgeType &&
1163 fStencilSettings == other.fStencilSettings &&
1164 fFirstCoverageStage == other.fFirstCoverageStage &&
1165 fCoverage == other.fCoverage &&
1166 fColorFilterMode == other.fColorFilterMode &&
1167 fColorFilterColor == other.fColorFilterColor &&
1168 fDrawFace == other.fDrawFace;
1169 }
1170 bool operator!= (const CommonState& other) const { return !(*this == other); }
1171 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001172
bsalomon@google.comca432082013-01-23 19:53:46 +00001173 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1174 DeferredState must directly reference GrEffects, however. */
1175 struct SavedEffectStage {
1176 SavedEffectStage() : fEffect(NULL) {}
1177 const GrEffect* fEffect;
1178 GrEffectStage::SavedCoordChange fCoordChange;
1179 };
1180
1181public:
1182 /**
1183 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1184 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1185 * dispose mechanism returns them to the cache. This allows recycling resources through the
1186 * the cache while they are in a deferred draw queue.
1187 */
1188 class DeferredState {
1189 public:
1190 DeferredState() : fRenderTarget(NULL) {
1191 GR_DEBUGCODE(fInitialized = false;)
1192 }
1193 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1194 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1195
1196 void saveFrom(const GrDrawState& drawState) {
1197 fCommon = drawState.fCommon;
1198 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1199 fRenderTarget = drawState.fRenderTarget.get();
1200 SkSafeRef(fRenderTarget);
1201 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1202 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1203 // and recycle them to the cache (if no one else is holding a ref to the resources).
1204 for (int i = 0; i < kNumStages; ++i) {
1205 fStages[i].saveFrom(drawState.fStages[i]);
1206 }
1207 GR_DEBUGCODE(fInitialized = true;)
1208 }
1209
1210 void restoreTo(GrDrawState* drawState) {
1211 GrAssert(fInitialized);
1212 drawState->fCommon = fCommon;
1213 drawState->setRenderTarget(fRenderTarget);
1214 for (int i = 0; i < kNumStages; ++i) {
1215 fStages[i].restoreTo(&drawState->fStages[i]);
1216 }
1217 }
1218
1219 bool isEqual(const GrDrawState& state) const {
1220 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1221 return false;
1222 }
1223 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001224 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001225 return false;
1226 }
1227 }
1228 return true;
1229 }
1230
1231 private:
1232 GrRenderTarget* fRenderTarget;
1233 CommonState fCommon;
1234 GrEffectStage::DeferredStage fStages[kNumStages];
1235
1236 GR_DEBUGCODE(bool fInitialized;)
1237 };
1238
1239private:
1240 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1241 CommonState fCommon;
1242 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001243
reed@google.comfa35e3d2012-06-26 20:16:17 +00001244 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001245};
1246
1247#endif