blob: dc3fdfe6a564534eacefc4df265095da649e7f5b [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() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000062 this->reset();
63 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000064
bsalomon@google.comca432082013-01-23 19:53:46 +000065 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000066 *this = state;
67 }
68
robertphillips@google.com9ec07532012-06-22 12:01:30 +000069 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000070 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000071 }
72
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000073 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000074 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000075 * GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000076 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000077 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000079 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000080
bsalomon@google.comca432082013-01-23 19:53:46 +000081 fRenderTarget.reset(NULL);
82
83 fCommon.fColor = 0xffffffff;
84 fCommon.fViewMatrix.reset();
85 fCommon.fSrcBlend = kOne_GrBlendCoeff;
86 fCommon.fDstBlend = kZero_GrBlendCoeff;
87 fCommon.fBlendConstant = 0x0;
88 fCommon.fFlagBits = 0x0;
89 fCommon.fVertexEdgeType = kHairLine_EdgeType;
90 fCommon.fStencilSettings.setDisabled();
91 fCommon.fFirstCoverageStage = kNumStages;
92 fCommon.fCoverage = 0xffffffff;
93 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
94 fCommon.fColorFilterColor = 0x0;
95 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000096 }
97
98 /**
99 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000100 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000101 * GrPaint equivalents are not modified. GrPaint has fewer stages than
102 * GrDrawState. The extra GrDrawState stages are disabled.
103 */
104 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000105
106 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.comcc782382013-01-28 20:39:48 +0000107 /// @name Vertex Format
108 ////
109
110 /**
111 * The format of vertices is represented as a bitfield of flags.
112 * Flags that indicate the layout of vertex data. Vertices always contain
113 * positions and may also contain up to GrDrawState::kMaxTexCoords sets
114 * of 2D texture coordinates, per-vertex colors, and per-vertex coverage.
115 * Each stage can
116 * use any of the texture coordinates as its input texture coordinates or it
117 * may use the positions as texture coordinates.
118 *
119 * If no texture coordinates are specified for a stage then the stage is
120 * disabled.
121 *
122 * Only one type of texture coord can be specified per stage. For
123 * example StageTexCoordVertexLayoutBit(0, 2) and
124 * StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
125 *
126 * The order in memory is always (position, texture coord 0, ..., color,
127 * coverage) with any unused fields omitted. Note that this means that if
128 * only texture coordinates 1 is referenced then there is no texture
129 * coordinates 0 and the order would be (position, texture coordinate 1
130 * [, color][, coverage]).
131 */
132
133 /**
134 * Generates a bit indicating that a texture stage uses texture coordinates
135 *
136 * @param stageIdx the stage that will use texture coordinates.
137 * @param texCoordIdx the index of the texture coordinates to use
138 *
139 * @return the bit to add to a GrVertexLayout bitfield.
140 */
141 static int StageTexCoordVertexLayoutBit(int stageIdx, int texCoordIdx) {
142 GrAssert(stageIdx < kNumStages);
143 GrAssert(texCoordIdx < kMaxTexCoords);
144 return 1 << (stageIdx + (texCoordIdx * kNumStages));
145 }
146
147 static bool StageUsesTexCoords(GrVertexLayout layout, int stageIdx);
148
149private:
150 // non-stage bits start at this index.
151 static const int STAGE_BIT_CNT = kNumStages * kMaxTexCoords;
152public:
153
154 /**
155 * Additional Bits that can be specified in GrVertexLayout.
156 */
157 enum VertexLayoutBits {
158 /* vertices have colors (GrColor) */
159 kColor_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 0),
160 /* vertices have coverage (GrColor)
161 */
162 kCoverage_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 1),
163 /* Use text vertices. (Pos and tex coords may be a different type for
164 * text [GrGpuTextVertex vs GrPoint].)
165 */
166 kTextFormat_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 2),
167
168 /* Each vertex specificies an edge. Distance to the edge is used to
169 * compute a coverage. See GrDrawState::setVertexEdgeType().
170 */
171 kEdge_VertexLayoutBit = 1 << (STAGE_BIT_CNT + 3),
172 // for below assert
173 kDummyVertexLayoutBit,
174 kHighVertexLayoutBit = kDummyVertexLayoutBit - 1
175 };
176 // make sure we haven't exceeded the number of bits in GrVertexLayout.
177 GR_STATIC_ASSERT(kHighVertexLayoutBit < ((uint64_t)1 << 8*sizeof(GrVertexLayout)));
178
179 ////////////////////////////////////////////////////////////////////////////
180 // Helpers for picking apart vertex layouts
181
182 /**
183 * Helper function to compute the size of a vertex from a vertex layout
184 * @return size of a single vertex.
185 */
186 static size_t VertexSize(GrVertexLayout vertexLayout);
187
188 /**
189 * Helper function for determining the index of texture coordinates that
190 * is input for a texture stage. Note that a stage may instead use positions
191 * as texture coordinates, in which case the result of the function is
192 * indistinguishable from the case when the stage is disabled.
193 *
194 * @param stageIdx the stage to query
195 * @param vertexLayout layout to query
196 *
197 * @return the texture coordinate index or -1 if the stage doesn't use
198 * separate (non-position) texture coordinates.
199 */
200 static int VertexTexCoordsForStage(int stageIdx, GrVertexLayout vertexLayout);
201
202 /**
203 * Helper function to compute the offset of texture coordinates in a vertex
204 * @return offset of texture coordinates in vertex layout or -1 if the
205 * layout has no texture coordinates. Will be 0 if positions are
206 * used as texture coordinates for the stage.
207 */
208 static int VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout);
209
210 /**
211 * Helper function to compute the offset of the color in a vertex
212 * @return offset of color in vertex layout or -1 if the
213 * layout has no color.
214 */
215 static int VertexColorOffset(GrVertexLayout vertexLayout);
216
217 /**
218 * Helper function to compute the offset of the coverage in a vertex
219 * @return offset of coverage in vertex layout or -1 if the
220 * layout has no coverage.
221 */
222 static int VertexCoverageOffset(GrVertexLayout vertexLayout);
223
224 /**
225 * Helper function to compute the offset of the edge pts in a vertex
226 * @return offset of edge in vertex layout or -1 if the
227 * layout has no edge.
228 */
229 static int VertexEdgeOffset(GrVertexLayout vertexLayout);
230
231 /**
232 * Helper function to determine if vertex layout contains explicit texture
233 * coordinates of some index.
234 *
235 * @param coordIndex the tex coord index to query
236 * @param vertexLayout layout to query
237 *
238 * @return true if vertex specifies texture coordinates for the index,
239 * false otherwise.
240 */
241 static bool VertexUsesTexCoordIdx(int coordIndex,
242 GrVertexLayout vertexLayout);
243
244 /**
245 * Helper function to compute the size of each vertex and the offsets of
246 * texture coordinates and color. Determines tex coord offsets by tex coord
247 * index rather than by stage. (Each stage can be mapped to any t.c. index
248 * by StageTexCoordVertexLayoutBit.)
249 *
250 * @param vertexLayout the layout to query
251 * @param texCoordOffsetsByIdx after return it is the offset of each
252 * tex coord index in the vertex or -1 if
253 * index isn't used. (optional)
254 * @param colorOffset after return it is the offset of the
255 * color field in each vertex, or -1 if
256 * there aren't per-vertex colors. (optional)
257 * @param coverageOffset after return it is the offset of the
258 * coverage field in each vertex, or -1 if
259 * there aren't per-vertex coeverages.
260 * (optional)
261 * @param edgeOffset after return it is the offset of the
262 * edge eq field in each vertex, or -1 if
263 * there aren't per-vertex edge equations.
264 * (optional)
265 * @return size of a single vertex
266 */
267 static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
268 int texCoordOffsetsByIdx[kMaxTexCoords],
269 int *colorOffset,
270 int *coverageOffset,
271 int* edgeOffset);
272
273 /**
274 * Helper function to compute the size of each vertex and the offsets of
275 * texture coordinates and color. Determines tex coord offsets by stage
276 * rather than by index. (Each stage can be mapped to any t.c. index
277 * by StageTexCoordVertexLayoutBit.) If a stage uses positions for
278 * tex coords then that stage's offset will be 0 (positions are always at 0).
279 *
280 * @param vertexLayout the layout to query
281 * @param texCoordOffsetsByStage after return it is the offset of each
282 * tex coord index in the vertex or -1 if
283 * index isn't used. (optional)
284 * @param colorOffset after return it is the offset of the
285 * color field in each vertex, or -1 if
286 * there aren't per-vertex colors.
287 * (optional)
288 * @param coverageOffset after return it is the offset of the
289 * coverage field in each vertex, or -1 if
290 * there aren't per-vertex coeverages.
291 * (optional)
292 * @param edgeOffset after return it is the offset of the
293 * edge eq field in each vertex, or -1 if
294 * there aren't per-vertex edge equations.
295 * (optional)
296 * @return size of a single vertex
297 */
298 static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
299 int texCoordOffsetsByStage[kNumStages],
300 int* colorOffset,
301 int* coverageOffset,
302 int* edgeOffset);
303
304 // determine if src alpha is guaranteed to be one for all src pixels
305 bool srcAlphaWillBeOne(GrVertexLayout vertexLayout) const;
306
307 /**
308 * Accessing positions, texture coords, or colors, of a vertex within an
309 * array is a hassle involving casts and simple math. These helpers exist
310 * to keep GrDrawTarget clients' code a bit nicer looking.
311 */
312
313 /**
314 * Gets a pointer to a GrPoint of a vertex's position or texture
315 * coordinate.
316 * @param vertices the vetex array
317 * @param vertexIndex the index of the vertex in the array
318 * @param vertexSize the size of each vertex in the array
319 * @param offset the offset in bytes of the vertex component.
320 * Defaults to zero (corresponding to vertex position)
321 * @return pointer to the vertex component as a GrPoint
322 */
323 static GrPoint* GetVertexPoint(void* vertices,
324 int vertexIndex,
325 int vertexSize,
326 int offset = 0) {
327 intptr_t start = GrTCast<intptr_t>(vertices);
328 return GrTCast<GrPoint*>(start + offset +
329 vertexIndex * vertexSize);
330 }
331 static const GrPoint* GetVertexPoint(const void* vertices,
332 int vertexIndex,
333 int vertexSize,
334 int offset = 0) {
335 intptr_t start = GrTCast<intptr_t>(vertices);
336 return GrTCast<const GrPoint*>(start + offset +
337 vertexIndex * vertexSize);
338 }
339
340 /**
341 * Gets a pointer to a GrColor inside a vertex within a vertex array.
342 * @param vertices the vetex array
343 * @param vertexIndex the index of the vertex in the array
344 * @param vertexSize the size of each vertex in the array
345 * @param offset the offset in bytes of the vertex color
346 * @return pointer to the vertex component as a GrColor
347 */
348 static GrColor* GetVertexColor(void* vertices,
349 int vertexIndex,
350 int vertexSize,
351 int offset) {
352 intptr_t start = GrTCast<intptr_t>(vertices);
353 return GrTCast<GrColor*>(start + offset +
354 vertexIndex * vertexSize);
355 }
356 static const GrColor* GetVertexColor(const void* vertices,
357 int vertexIndex,
358 int vertexSize,
359 int offset) {
360 const intptr_t start = GrTCast<intptr_t>(vertices);
361 return GrTCast<const GrColor*>(start + offset +
362 vertexIndex * vertexSize);
363 }
364
365 static void VertexLayoutUnitTest();
366
367 /// @}
368
369 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000370 /// @name Color
371 ////
372
373 /**
374 * Sets color for next draw to a premultiplied-alpha color.
375 *
376 * @param color the color to set.
377 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000378 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000379
bsalomon@google.comca432082013-01-23 19:53:46 +0000380 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000381
382 /**
383 * Sets the color to be used for the next draw to be
384 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
385 *
386 * @param alpha The alpha value to set as the color.
387 */
388 void setAlpha(uint8_t a) {
389 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
390 }
391
392 /**
393 * Add a color filter that can be represented by a color and a mode. Applied
394 * after color-computing texture stages.
395 */
396 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000397 fCommon.fColorFilterColor = c;
398 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000399 }
400
bsalomon@google.comca432082013-01-23 19:53:46 +0000401 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
402 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000403
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000404 /**
405 * Constructor sets the color to be 'color' which is undone by the destructor.
406 */
407 class AutoColorRestore : public ::GrNoncopyable {
408 public:
409 AutoColorRestore(GrDrawState* drawState, GrColor color) {
410 fDrawState = drawState;
411 fOldColor = fDrawState->getColor();
412 fDrawState->setColor(color);
413 }
414 ~AutoColorRestore() {
415 fDrawState->setColor(fOldColor);
416 }
417 private:
418 GrDrawState* fDrawState;
419 GrColor fOldColor;
420 };
421
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000422 /// @}
423
424 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000425 /// @name Coverage
426 ////
427
428 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000429 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000430 * initial value (after construction or reset()) is 0xff. The constant
431 * coverage is ignored when per-vertex coverage is provided.
432 */
433 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000434 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000435 }
436
437 /**
438 * Version of above that specifies 4 channel per-vertex color. The value
439 * should be premultiplied.
440 */
441 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000442 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000443 }
444
445 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000446 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000447 }
448
449 /// @}
450
451 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000452 /// @name Effect Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000453 ////
454
bsalomon@google.comadc65362013-01-28 14:26:09 +0000455 const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
456 fStages[stageIdx].setEffect(effect);
457 return effect;
458 }
459
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000460 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000461 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000462 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000463 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000464 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000465 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000466 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000467 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000468 void createTextureEffect(int stageIdx,
469 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000470 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000471 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000472 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000473 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comadc65362013-01-28 14:26:09 +0000474 this->setEffect(stageIdx, effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000475 }
476
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000477 bool stagesDisabled() {
478 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000479 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000480 return false;
481 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000482 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000483 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000484 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000485
bsalomon@google.comadc65362013-01-28 14:26:09 +0000486 void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000487
robertphillips@google.com972265d2012-06-13 18:49:30 +0000488 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000489 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000490 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000491 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000492 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000493 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000494 }
495 }
496
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000497 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000498 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000499 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
500 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000501 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000502 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000503 }
504 }
505 private:
506 GrDrawState* fDrawState;
507 };
508
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000509 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000510 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000511 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000512 const GrEffectStage& getStage(int stageIdx) const {
513 GrAssert((unsigned)stageIdx < kNumStages);
514 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000515 }
516
517 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000518 * Called when the source coord system is changing. preConcat gives the transformation from the
519 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000520 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000521 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000522 this->preConcatStageMatrices(~0U, preConcat);
523 }
524 /**
525 * Version of above that applies the update matrix selectively to stages via a mask.
526 */
527 void preConcatStageMatrices(uint32_t stageMask, const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000528 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcabe00e2013-01-28 16:46:55 +0000529 if (((1 << i) & stageMask) && this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000530 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 }
532 }
533 }
534
bsalomon@google.come3d32162012-07-20 13:37:06 +0000535 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000536 * Called when the source coord system is changing. preConcatInverse is the inverse of the
537 * transformation from the old coord system to the new coord system. Returns false if the matrix
538 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000539 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000540 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
541 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000542 bool computed = false;
543 for (int i = 0; i < kNumStages; ++i) {
544 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000545 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000546 return false;
547 } else {
548 computed = true;
549 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000550 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000551 }
552 }
553 return true;
554 }
555
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000556 /// @}
557
558 ///////////////////////////////////////////////////////////////////////////
559 /// @name Coverage / Color Stages
560 ////
561
562 /**
563 * A common pattern is to compute a color with the initial stages and then
564 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000565 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
566 * computed based on the pre-coverage-modulated color. The division of
567 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000568 * this method. Initially this is kNumStages (all stages
569 * are color-computing).
570 */
571 void setFirstCoverageStage(int firstCoverageStage) {
572 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000573 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000574 }
575
576 /**
577 * Gets the index of the first coverage-computing stage.
578 */
579 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000580 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000581 }
582
583 ///@}
584
585 ///////////////////////////////////////////////////////////////////////////
586 /// @name Blending
587 ////
588
589 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000590 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 *
592 * The blend function will be:
593 * D' = sat(S*srcCoef + D*dstCoef)
594 *
595 * where D is the existing destination color, S is the incoming source
596 * color, and D' is the new destination color that will be written. sat()
597 * is the saturation function.
598 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000599 * @param srcCoef coefficient applied to the src color.
600 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000601 */
602 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000603 fCommon.fSrcBlend = srcCoeff;
604 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000605 #if GR_DEBUG
606 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000607 case kDC_GrBlendCoeff:
608 case kIDC_GrBlendCoeff:
609 case kDA_GrBlendCoeff:
610 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000611 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
612 "coverage stages.\n");
613 break;
614 default:
615 break;
616 }
617 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000618 case kSC_GrBlendCoeff:
619 case kISC_GrBlendCoeff:
620 case kSA_GrBlendCoeff:
621 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000622 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
623 "coverage stages.\n");
624 break;
625 default:
626 break;
627 }
628 #endif
629 }
630
bsalomon@google.comca432082013-01-23 19:53:46 +0000631 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
632 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633
634 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
635 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000636 *srcBlendCoeff = fCommon.fSrcBlend;
637 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 }
639
640 /**
641 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000642 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000643 * kConstC_GrBlendCoeff
644 * kIConstC_GrBlendCoeff
645 * kConstA_GrBlendCoeff
646 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000647 *
648 * @param constant the constant to set
649 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000650 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000651
652 /**
653 * Retrieves the last value set by setBlendConstant()
654 * @return the blending constant value
655 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000656 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000657
658 /// @}
659
660 ///////////////////////////////////////////////////////////////////////////
661 /// @name View Matrix
662 ////
663
664 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000665 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000666 *
667 * In the post-view-matrix space the rectangle [0,w]x[0,h]
668 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000669 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000671 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000672
673 /**
674 * Gets a writable pointer to the view matrix.
675 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000676 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000677
678 /**
679 * Multiplies the current view matrix by a matrix
680 *
681 * After this call V' = V*m where V is the old view matrix,
682 * m is the parameter to this function, and V' is the new view matrix.
683 * (We consider positions to be column vectors so position vector p is
684 * transformed by matrix X as p' = X*p.)
685 *
686 * @param m the matrix used to modify the view matrix.
687 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000688 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000689
690 /**
691 * Multiplies the current view matrix by a matrix
692 *
693 * After this call V' = m*V where V is the old view matrix,
694 * m is the parameter to this function, and V' is the new view matrix.
695 * (We consider positions to be column vectors so position vector p is
696 * transformed by matrix X as p' = X*p.)
697 *
698 * @param m the matrix used to modify the view matrix.
699 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000700 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701
702 /**
703 * Retrieves the current view matrix
704 * @return the current view matrix.
705 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000706 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000707
708 /**
709 * Retrieves the inverse of the current view matrix.
710 *
711 * If the current view matrix is invertible, return true, and if matrix
712 * is non-null, copy the inverse into it. If the current view matrix is
713 * non-invertible, return false and ignore the matrix parameter.
714 *
715 * @param matrix if not null, will receive a copy of the current inverse.
716 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000717 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000718 // TODO: determine whether we really need to leave matrix unmodified
719 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000720 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000721 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 if (matrix) {
723 *matrix = inverse;
724 }
725 return true;
726 }
727 return false;
728 }
729
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000730 ////////////////////////////////////////////////////////////////////////////
731
732 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000733 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000734 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000735 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000736 class AutoViewMatrixRestore : public ::GrNoncopyable {
737 public:
738 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000739
740 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000741 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000742 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000743 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000744 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000745 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000746
747 ~AutoViewMatrixRestore() { this->restore(); }
748
bsalomon@google.coma8347462012-10-08 18:59:39 +0000749 /**
750 * Can be called prior to destructor to restore the original matrix.
751 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000752 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000753
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000754 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000755 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000756 uint32_t explicitCoordStageMask = 0);
757
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000758 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000759
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000760 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000761 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000762 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000763 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000764 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000765 };
766
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000767 ////////////////////////////////////////////////////////////////////////////
768
769 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000770 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
771 * destructor undoes the changes, restoring the view matrix that was set before the
772 * constructor. It is similar to passing the inverse of the current view matrix to
773 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000774 */
775 class AutoDeviceCoordDraw : ::GrNoncopyable {
776 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000777 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000778 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000779 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
780 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
781 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000782 */
783 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000784 uint32_t explicitCoordStageMask = 0) {
785 fDrawState = NULL;
786 this->set(drawState, explicitCoordStageMask);
787 }
788
bsalomon@google.coma8347462012-10-08 18:59:39 +0000789 ~AutoDeviceCoordDraw() { this->restore(); }
790
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000791 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
792
bsalomon@google.coma8347462012-10-08 18:59:39 +0000793 /**
794 * Returns true if this object was successfully initialized on to a GrDrawState. It may
795 * return false because a non-default constructor or set() were never called or because
796 * the view matrix was not invertible.
797 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000798 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000799
bsalomon@google.coma8347462012-10-08 18:59:39 +0000800 /**
801 * Returns the matrix that was set previously set on the drawState. This is only valid
802 * if succeeded returns true.
803 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000804 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000805 GrAssert(this->succeeded());
806 return fViewMatrix;
807 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000808
bsalomon@google.coma8347462012-10-08 18:59:39 +0000809 /**
810 * Can be called prior to destructor to restore the original matrix.
811 */
812 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000813
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000814 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000815 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000816 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000817 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000818 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000819 };
820
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 /// @}
822
823 ///////////////////////////////////////////////////////////////////////////
824 /// @name Render Target
825 ////
826
827 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000828 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000829 *
830 * @param target The render target to set.
831 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000832 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000833 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000834 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000835
836 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000837 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000838 *
839 * @return The currently set render target.
840 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000841 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
842 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000843
844 class AutoRenderTargetRestore : public ::GrNoncopyable {
845 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000846 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000847 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
848 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000849 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000850 this->set(ds, newTarget);
851 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000852 ~AutoRenderTargetRestore() { this->restore(); }
853
854 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000855 if (NULL != fDrawState) {
856 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000857 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000858 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000859 GrSafeSetNull(fSavedTarget);
860 }
861
862 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
863 this->restore();
864
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000865 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000866 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000867 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000868 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000869 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000870 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000871 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000872 }
873 private:
874 GrDrawState* fDrawState;
875 GrRenderTarget* fSavedTarget;
876 };
877
878 /// @}
879
880 ///////////////////////////////////////////////////////////////////////////
881 /// @name Stencil
882 ////
883
884 /**
885 * Sets the stencil settings to use for the next draw.
886 * Changing the clip has the side-effect of possibly zeroing
887 * out the client settable stencil bits. So multipass algorithms
888 * using stencil should not change the clip between passes.
889 * @param settings the stencil settings to use.
890 */
891 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000892 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000893 }
894
895 /**
896 * Shortcut to disable stencil testing and ops.
897 */
898 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000899 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000900 }
901
bsalomon@google.comca432082013-01-23 19:53:46 +0000902 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000903
bsalomon@google.comca432082013-01-23 19:53:46 +0000904 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000905
906 /// @}
907
908 ///////////////////////////////////////////////////////////////////////////
909 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000910 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000911 // edges are specified as per-vertex data, vertices that are shared by
912 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000913 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000914 ////
915
916 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000917 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000918 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000919 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000920 *
921 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
922 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000923 */
924 enum VertexEdgeType {
925 /* 1-pixel wide line
926 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
927 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000928 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000929 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000930 being inside, positive outside. Edge specified in window space
931 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000932 kQuad_EdgeType,
933 /* Same as above but for hairline quadratics. Uses unsigned distance.
934 Coverage is min(0, 1-distance). */
935 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000936 /* Circle specified as center_x, center_y, outer_radius, inner_radius
937 all in window space (y-down). */
938 kCircle_EdgeType,
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000939 /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
940 all in window space (y-down). */
941 kEllipse_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000942
943 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000944 };
945
946 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000947 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000948 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
949 * are not specified the value of this setting has no effect.
950 */
951 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000952 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.comca432082013-01-23 19:53:46 +0000953 fCommon.fVertexEdgeType = type;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000954 }
955
bsalomon@google.comca432082013-01-23 19:53:46 +0000956 VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000957
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000958 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000959
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000960 ///////////////////////////////////////////////////////////////////////////
961 /// @name State Flags
962 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000963
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000964 /**
965 * Flags that affect rendering. Controlled using enable/disableState(). All
966 * default to disabled.
967 */
968 enum StateBits {
969 /**
970 * Perform dithering. TODO: Re-evaluate whether we need this bit
971 */
972 kDither_StateBit = 0x01,
973 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000974 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
975 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
976 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000977 */
978 kHWAntialias_StateBit = 0x02,
979 /**
980 * Draws will respect the clip, otherwise the clip is ignored.
981 */
982 kClip_StateBit = 0x04,
983 /**
984 * Disables writing to the color buffer. Useful when performing stencil
985 * operations.
986 */
987 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000988
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000989 /**
990 * Usually coverage is applied after color blending. The color is blended using the coeffs
991 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
992 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
993 * this case there is no distinction between coverage and color and the caller needs direct
994 * control over the blend coeffs. When set, there will be a single blend step controlled by
995 * setBlendFunc() which will use coverage*color as the src color.
996 */
997 kCoverageDrawing_StateBit = 0x10,
998
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000999 // Users of the class may add additional bits to the vector
1000 kDummyStateBit,
1001 kLastPublicStateBit = kDummyStateBit-1,
1002 };
1003
1004 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +00001005 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001006 }
1007
1008 /**
1009 * Enable render state settings.
1010 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001011 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001012 */
1013 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001014 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001015 }
1016
1017 /**
1018 * Disable render state settings.
1019 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001020 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001021 */
1022 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001023 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001024 }
1025
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001026 /**
1027 * Enable or disable stateBits based on a boolean.
1028 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +00001029 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +00001030 * @param enable if true enable stateBits, otherwise disable
1031 */
1032 void setState(uint32_t stateBits, bool enable) {
1033 if (enable) {
1034 this->enableState(stateBits);
1035 } else {
1036 this->disableState(stateBits);
1037 }
1038 }
1039
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001040 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001041 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001042 }
1043
1044 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001045 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001046 }
1047
1048 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001049 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001050 }
1051
1052 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001053 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001054 }
1055
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001056 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001057 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +00001058 }
1059
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001060 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001061 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001062 }
1063
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001064 /// @}
1065
1066 ///////////////////////////////////////////////////////////////////////////
1067 /// @name Face Culling
1068 ////
1069
1070 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001071 kInvalid_DrawFace = -1,
1072
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001073 kBoth_DrawFace,
1074 kCCW_DrawFace,
1075 kCW_DrawFace,
1076 };
1077
1078 /**
1079 * Controls whether clockwise, counterclockwise, or both faces are drawn.
1080 * @param face the face(s) to draw.
1081 */
1082 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +00001083 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +00001084 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001085 }
1086
1087 /**
1088 * Gets whether the target is drawing clockwise, counterclockwise,
1089 * or both faces.
1090 * @return the current draw face(s).
1091 */
bsalomon@google.comca432082013-01-23 19:53:46 +00001092 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +00001093
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001094 /// @}
1095
1096 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +00001097
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001098 bool isStageEnabled(int s) const {
1099 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +00001100 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +00001101 }
1102
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001103 // Most stages are usually not used, so conditionals here
1104 // reduce the expected number of bytes touched by 50%.
1105 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +00001106 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001107 return false;
1108 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001109
1110 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +00001111 bool enabled = this->isStageEnabled(i);
1112 if (enabled != s.isStageEnabled(i)) {
1113 return false;
1114 }
bsalomon@google.com08283af2012-10-26 13:01:20 +00001115 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001116 return false;
1117 }
1118 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001119 return true;
1120 }
1121 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
1122
bsalomon@google.comca432082013-01-23 19:53:46 +00001123 GrDrawState& operator= (const GrDrawState& s) {
1124 this->setRenderTarget(s.fRenderTarget.get());
1125 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001126 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +00001127 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +00001128 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001129 }
1130 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001131 return *this;
1132 }
1133
1134private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +00001135
bsalomon@google.comca432082013-01-23 19:53:46 +00001136 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
1137 struct CommonState {
1138 // These fields are roughly sorted by decreasing likelihood of being different in op==
1139 GrColor fColor;
1140 SkMatrix fViewMatrix;
1141 GrBlendCoeff fSrcBlend;
1142 GrBlendCoeff fDstBlend;
1143 GrColor fBlendConstant;
1144 uint32_t fFlagBits;
1145 VertexEdgeType fVertexEdgeType;
1146 GrStencilSettings fStencilSettings;
1147 int fFirstCoverageStage;
1148 GrColor fCoverage;
1149 SkXfermode::Mode fColorFilterMode;
1150 GrColor fColorFilterColor;
1151 DrawFace fDrawFace;
1152 bool operator== (const CommonState& other) const {
1153 return fColor == other.fColor &&
1154 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
1155 fSrcBlend == other.fSrcBlend &&
1156 fDstBlend == other.fDstBlend &&
1157 fBlendConstant == other.fBlendConstant &&
1158 fFlagBits == other.fFlagBits &&
1159 fVertexEdgeType == other.fVertexEdgeType &&
1160 fStencilSettings == other.fStencilSettings &&
1161 fFirstCoverageStage == other.fFirstCoverageStage &&
1162 fCoverage == other.fCoverage &&
1163 fColorFilterMode == other.fColorFilterMode &&
1164 fColorFilterColor == other.fColorFilterColor &&
1165 fDrawFace == other.fDrawFace;
1166 }
1167 bool operator!= (const CommonState& other) const { return !(*this == other); }
1168 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +00001169
bsalomon@google.comca432082013-01-23 19:53:46 +00001170 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
1171 DeferredState must directly reference GrEffects, however. */
1172 struct SavedEffectStage {
1173 SavedEffectStage() : fEffect(NULL) {}
1174 const GrEffect* fEffect;
1175 GrEffectStage::SavedCoordChange fCoordChange;
1176 };
1177
1178public:
1179 /**
1180 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
1181 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
1182 * dispose mechanism returns them to the cache. This allows recycling resources through the
1183 * the cache while they are in a deferred draw queue.
1184 */
1185 class DeferredState {
1186 public:
1187 DeferredState() : fRenderTarget(NULL) {
1188 GR_DEBUGCODE(fInitialized = false;)
1189 }
1190 // TODO: Remove this when DeferredState no longer holds a ref to the RT
1191 ~DeferredState() { SkSafeUnref(fRenderTarget); }
1192
1193 void saveFrom(const GrDrawState& drawState) {
1194 fCommon = drawState.fCommon;
1195 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
1196 fRenderTarget = drawState.fRenderTarget.get();
1197 SkSafeRef(fRenderTarget);
1198 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
1199 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
1200 // and recycle them to the cache (if no one else is holding a ref to the resources).
1201 for (int i = 0; i < kNumStages; ++i) {
1202 fStages[i].saveFrom(drawState.fStages[i]);
1203 }
1204 GR_DEBUGCODE(fInitialized = true;)
1205 }
1206
1207 void restoreTo(GrDrawState* drawState) {
1208 GrAssert(fInitialized);
1209 drawState->fCommon = fCommon;
1210 drawState->setRenderTarget(fRenderTarget);
1211 for (int i = 0; i < kNumStages; ++i) {
1212 fStages[i].restoreTo(&drawState->fStages[i]);
1213 }
1214 }
1215
1216 bool isEqual(const GrDrawState& state) const {
1217 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
1218 return false;
1219 }
1220 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +00001221 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +00001222 return false;
1223 }
1224 }
1225 return true;
1226 }
1227
1228 private:
1229 GrRenderTarget* fRenderTarget;
1230 CommonState fCommon;
1231 GrEffectStage::DeferredStage fStages[kNumStages];
1232
1233 GR_DEBUGCODE(bool fInitialized;)
1234 };
1235
1236private:
1237 SkAutoTUnref<GrRenderTarget> fRenderTarget;
1238 CommonState fCommon;
1239 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001240
reed@google.comfa35e3d2012-06-26 20:16:17 +00001241 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001242};
1243
1244#endif