blob: 5dccb1581dbd69197d5c334890b217a12f363a3b [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
11#include "GrColor.h"
12#include "GrMatrix.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrNoncopyable.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000015#include "GrSamplerState.h"
16#include "GrStencil.h"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000017#include "GrTexture.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000018#include "GrRenderTarget.h"
tomhudson@google.com1e8f0162012-07-20 16:25:18 +000019#include "effects/GrSingleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000020
21#include "SkXfermode.h"
22
bsalomon@google.comaf84e742012-10-05 13:23:24 +000023class GrPaint;
tomhudson@google.com93813632011-10-27 20:21:16 +000024
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000026public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000027 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000028
tomhudson@google.com93813632011-10-27 20:21:16 +000029 /**
30 * Number of texture stages. Each stage takes as input a color and
31 * 2D texture coordinates. The color input to the first enabled stage is the
32 * per-vertex color or the constant color (setColor/setAlpha) if there are
33 * no per-vertex colors. For subsequent stages the input color is the output
34 * color from the previous enabled stage. The output color of each stage is
35 * the input color modulated with the result of a texture lookup. Texture
36 * lookups are specified by a texture a sampler (setSamplerState). Texture
37 * coordinates for each stage come from the vertices based on a
38 * GrVertexLayout bitfield. The output fragment color is the output color of
39 * the last enabled stage. The presence or absence of texture coordinates
40 * for each stage in the vertex layout indicates whether a stage is enabled
41 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000042 *
43 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
rmistry@google.comd6176b02012-08-23 18:14:13 +000044 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
45 * through kNumStages-1 are earmarked for use by GrTextContext and
robertphillips@google.combf5cad42012-05-10 12:40:40 +000046 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000047 */
48 enum {
twiz@google.com58071162012-07-18 21:41:50 +000049 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000050 kMaxTexCoords = kNumStages
51 };
52
rmistry@google.comd6176b02012-08-23 18:14:13 +000053 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000054 : fRenderTarget(NULL) {
55
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000056 this->reset();
57 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000058
rmistry@google.comd6176b02012-08-23 18:14:13 +000059 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000060 : fRenderTarget(NULL) {
61
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000062 *this = state;
63 }
64
robertphillips@google.com9ec07532012-06-22 12:01:30 +000065 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000066 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000067 GrSafeSetNull(fRenderTarget);
68 }
69
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000070 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000071 * Resets to the default state.
72 * Sampler states *will* be modified: textures or CustomStage objects
73 * will be released.
rmistry@google.comd6176b02012-08-23 18:14:13 +000074 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000075 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000076
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000077 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000078
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000079 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000080 fViewMatrix.reset();
81 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000082 fSrcBlend = kOne_GrBlendCoeff;
83 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000084 fBlendConstant = 0x0;
85 fFlagBits = 0x0;
86 fVertexEdgeType = kHairLine_EdgeType;
87 fStencilSettings.setDisabled();
88 fFirstCoverageStage = kNumStages;
89 fCoverage = 0xffffffff;
90 fColorFilterMode = SkXfermode::kDst_Mode;
91 fColorFilterColor = 0x0;
92 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000093 }
94
95 /**
96 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
97 * encompases more than GrPaint. Aspects of GrDrawState that have no
98 * GrPaint equivalents are not modified. GrPaint has fewer stages than
99 * GrDrawState. The extra GrDrawState stages are disabled.
100 */
101 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000102
103 ///////////////////////////////////////////////////////////////////////////
104 /// @name Color
105 ////
106
107 /**
108 * Sets color for next draw to a premultiplied-alpha color.
109 *
110 * @param color the color to set.
111 */
112 void setColor(GrColor color) { fColor = color; }
113
114 GrColor getColor() const { return fColor; }
115
116 /**
117 * Sets the color to be used for the next draw to be
118 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
119 *
120 * @param alpha The alpha value to set as the color.
121 */
122 void setAlpha(uint8_t a) {
123 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
124 }
125
126 /**
127 * Add a color filter that can be represented by a color and a mode. Applied
128 * after color-computing texture stages.
129 */
130 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
131 fColorFilterColor = c;
132 fColorFilterMode = mode;
133 }
134
135 GrColor getColorFilterColor() const { return fColorFilterColor; }
136 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
137
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000138 /**
139 * Constructor sets the color to be 'color' which is undone by the destructor.
140 */
141 class AutoColorRestore : public ::GrNoncopyable {
142 public:
143 AutoColorRestore(GrDrawState* drawState, GrColor color) {
144 fDrawState = drawState;
145 fOldColor = fDrawState->getColor();
146 fDrawState->setColor(color);
147 }
148 ~AutoColorRestore() {
149 fDrawState->setColor(fOldColor);
150 }
151 private:
152 GrDrawState* fDrawState;
153 GrColor fOldColor;
154 };
155
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000156 /// @}
157
158 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000159 /// @name Coverage
160 ////
161
162 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000163 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000164 * initial value (after construction or reset()) is 0xff. The constant
165 * coverage is ignored when per-vertex coverage is provided.
166 */
167 void setCoverage(uint8_t coverage) {
168 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
169 }
170
171 /**
172 * Version of above that specifies 4 channel per-vertex color. The value
173 * should be premultiplied.
174 */
175 void setCoverage4(GrColor coverage) {
176 fCoverage = coverage;
177 }
178
179 GrColor getCoverage() const {
180 return fCoverage;
181 }
182
183 /// @}
184
185 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000186 /// @name Textures
187 ////
188
189 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000190 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000191 */
192 void createTextureEffect(int stage, GrTexture* texture) {
193 GrAssert(!this->getSampler(stage).getCustomStage());
194 this->sampler(stage)->setCustomStage(
195 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
196 }
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000197 void createTextureEffect(int stage, GrTexture* texture, const GrTextureParams& params) {
198 GrAssert(!this->getSampler(stage).getCustomStage());
199 this->sampler(stage)->setCustomStage(
200 SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref();
201 }
202
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000203
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000204 bool stagesDisabled() {
205 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000206 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000207 return false;
208 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000209 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000210 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000211 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000212
213 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000214 fSamplerStates[index].setCustomStage(NULL);
215 }
216
robertphillips@google.com972265d2012-06-13 18:49:30 +0000217 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000218 * Release all the textures and custom stages referred to by this
219 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000220 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000221 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000222 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000223 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000224 }
225 }
226
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000227 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000228 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000229 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
230 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000231 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000232 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000233 }
234 }
235 private:
236 GrDrawState* fDrawState;
237 };
238
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000239 /// @}
240
241 ///////////////////////////////////////////////////////////////////////////
242 /// @name Samplers
243 ////
244
245 /**
246 * Returns the current sampler for a stage.
247 */
248 const GrSamplerState& getSampler(int stage) const {
249 GrAssert((unsigned)stage < kNumStages);
250 return fSamplerStates[stage];
251 }
252
253 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000254 * Writable pointer to a stage's sampler.
255 */
256 GrSamplerState* sampler(int stage) {
257 GrAssert((unsigned)stage < kNumStages);
258 return fSamplerStates + stage;
259 }
260
261 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000262 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000263 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000264 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000265 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000266 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000267 fSamplerStates[i].preConcatMatrix(matrix);
268 }
269 }
270 }
271
bsalomon@google.come3d32162012-07-20 13:37:06 +0000272 /**
273 * Preconcats the matrix of all samplers in the mask with the inverse of a
274 * matrix. If the matrix inverse cannot be computed (and there is at least
275 * one enabled stage) then false is returned.
276 */
277 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
278 GrMatrix inv;
279 bool computed = false;
280 for (int i = 0; i < kNumStages; ++i) {
281 if (this->isStageEnabled(i)) {
282 if (!computed && !matrix.invert(&inv)) {
283 return false;
284 } else {
285 computed = true;
286 }
287 fSamplerStates[i].preConcatMatrix(inv);
288 }
289 }
290 return true;
291 }
292
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000293 /// @}
294
295 ///////////////////////////////////////////////////////////////////////////
296 /// @name Coverage / Color Stages
297 ////
298
299 /**
300 * A common pattern is to compute a color with the initial stages and then
301 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000302 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
303 * computed based on the pre-coverage-modulated color. The division of
304 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000305 * this method. Initially this is kNumStages (all stages
306 * are color-computing).
307 */
308 void setFirstCoverageStage(int firstCoverageStage) {
309 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000310 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000311 }
312
313 /**
314 * Gets the index of the first coverage-computing stage.
315 */
316 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000317 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000318 }
319
320 ///@}
321
322 ///////////////////////////////////////////////////////////////////////////
323 /// @name Blending
324 ////
325
326 /**
327 * Sets the blending function coeffecients.
328 *
329 * The blend function will be:
330 * D' = sat(S*srcCoef + D*dstCoef)
331 *
332 * where D is the existing destination color, S is the incoming source
333 * color, and D' is the new destination color that will be written. sat()
334 * is the saturation function.
335 *
336 * @param srcCoef coeffecient applied to the src color.
337 * @param dstCoef coeffecient applied to the dst color.
338 */
339 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
340 fSrcBlend = srcCoeff;
341 fDstBlend = dstCoeff;
342 #if GR_DEBUG
343 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000344 case kDC_GrBlendCoeff:
345 case kIDC_GrBlendCoeff:
346 case kDA_GrBlendCoeff:
347 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000348 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
349 "coverage stages.\n");
350 break;
351 default:
352 break;
353 }
354 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000355 case kSC_GrBlendCoeff:
356 case kISC_GrBlendCoeff:
357 case kSA_GrBlendCoeff:
358 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000359 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
360 "coverage stages.\n");
361 break;
362 default:
363 break;
364 }
365 #endif
366 }
367
368 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
369 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
370
371 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
372 GrBlendCoeff* dstBlendCoeff) const {
373 *srcBlendCoeff = fSrcBlend;
374 *dstBlendCoeff = fDstBlend;
375 }
376
377 /**
378 * Sets the blending function constant referenced by the following blending
379 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000380 * kConstC_GrBlendCoeff
381 * kIConstC_GrBlendCoeff
382 * kConstA_GrBlendCoeff
383 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000384 *
385 * @param constant the constant to set
386 */
387 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
388
389 /**
390 * Retrieves the last value set by setBlendConstant()
391 * @return the blending constant value
392 */
393 GrColor getBlendConstant() const { return fBlendConstant; }
394
395 /// @}
396
397 ///////////////////////////////////////////////////////////////////////////
398 /// @name View Matrix
399 ////
400
401 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000402 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000403 *
404 * In the post-view-matrix space the rectangle [0,w]x[0,h]
405 * fully covers the render target. (w and h are the width and height of the
406 * the rendertarget.)
407 */
408 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
409
410 /**
411 * Gets a writable pointer to the view matrix.
412 */
413 GrMatrix* viewMatrix() { return &fViewMatrix; }
414
415 /**
416 * Multiplies the current view matrix by a matrix
417 *
418 * After this call V' = V*m where V is the old view matrix,
419 * m is the parameter to this function, and V' is the new view matrix.
420 * (We consider positions to be column vectors so position vector p is
421 * transformed by matrix X as p' = X*p.)
422 *
423 * @param m the matrix used to modify the view matrix.
424 */
425 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
426
427 /**
428 * Multiplies the current view matrix by a matrix
429 *
430 * After this call V' = m*V where V is the old view matrix,
431 * m is the parameter to this function, and V' is the new view matrix.
432 * (We consider positions to be column vectors so position vector p is
433 * transformed by matrix X as p' = X*p.)
434 *
435 * @param m the matrix used to modify the view matrix.
436 */
437 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
438
439 /**
440 * Retrieves the current view matrix
441 * @return the current view matrix.
442 */
443 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
444
445 /**
446 * Retrieves the inverse of the current view matrix.
447 *
448 * If the current view matrix is invertible, return true, and if matrix
449 * is non-null, copy the inverse into it. If the current view matrix is
450 * non-invertible, return false and ignore the matrix parameter.
451 *
452 * @param matrix if not null, will receive a copy of the current inverse.
453 */
454 bool getViewInverse(GrMatrix* matrix) const {
455 // TODO: determine whether we really need to leave matrix unmodified
456 // at call sites when inversion fails.
457 GrMatrix inverse;
458 if (fViewMatrix.invert(&inverse)) {
459 if (matrix) {
460 *matrix = inverse;
461 }
462 return true;
463 }
464 return false;
465 }
466
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000467 ////////////////////////////////////////////////////////////////////////////
468
469 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000470 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
471 * Stage matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000472 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000473 class AutoViewMatrixRestore : public ::GrNoncopyable {
474 public:
475 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000476
477 AutoViewMatrixRestore(GrDrawState* ds,
478 const GrMatrix& preconcatMatrix,
479 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000480 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000481 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000482 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000483
484 ~AutoViewMatrixRestore() { this->restore(); }
485
486 void restore();
487
488 void set(GrDrawState* drawState,
489 const GrMatrix& preconcatMatrix,
490 uint32_t explicitCoordStageMask = 0);
491
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000492 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000493
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000494 private:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000495 GrDrawState* fDrawState;
496 GrMatrix fViewMatrix;
497 GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
498 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000499 };
500
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000501 ////////////////////////////////////////////////////////////////////////////
502
503 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
505 * destructor undoes the changes, restoring the view matrix that was set before the
506 * constructor. It is similar to passing the inverse of the current view matrix to
507 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000508 */
509 class AutoDeviceCoordDraw : ::GrNoncopyable {
510 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000511 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000512 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000513 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
514 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
515 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000516 */
517 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000518 uint32_t explicitCoordStageMask = 0) {
519 fDrawState = NULL;
520 this->set(drawState, explicitCoordStageMask);
521 }
522
523 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
524
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000525 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000526
527 void restore();
528
529 ~AutoDeviceCoordDraw() { this->restore(); }
530
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000531 private:
532 GrDrawState* fDrawState;
533 GrMatrix fViewMatrix;
534 GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000535 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000536 };
537
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000538 /// @}
539
540 ///////////////////////////////////////////////////////////////////////////
541 /// @name Render Target
542 ////
543
544 /**
545 * Sets the rendertarget used at the next drawing call
546 *
547 * @param target The render target to set.
548 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000549 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000550 GrSafeAssign(fRenderTarget, target);
551 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000552
553 /**
554 * Retrieves the currently set rendertarget.
555 *
556 * @return The currently set render target.
557 */
558 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
559 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
560
561 class AutoRenderTargetRestore : public ::GrNoncopyable {
562 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000563 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000564 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
565 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000566 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000567 this->set(ds, newTarget);
568 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000569 ~AutoRenderTargetRestore() { this->restore(); }
570
571 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000572 if (NULL != fDrawState) {
573 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000574 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000575 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000576 GrSafeSetNull(fSavedTarget);
577 }
578
579 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
580 this->restore();
581
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000582 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000583 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000584 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000585 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000586 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000587 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000588 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000589 }
590 private:
591 GrDrawState* fDrawState;
592 GrRenderTarget* fSavedTarget;
593 };
594
595 /// @}
596
597 ///////////////////////////////////////////////////////////////////////////
598 /// @name Stencil
599 ////
600
601 /**
602 * Sets the stencil settings to use for the next draw.
603 * Changing the clip has the side-effect of possibly zeroing
604 * out the client settable stencil bits. So multipass algorithms
605 * using stencil should not change the clip between passes.
606 * @param settings the stencil settings to use.
607 */
608 void setStencil(const GrStencilSettings& settings) {
609 fStencilSettings = settings;
610 }
611
612 /**
613 * Shortcut to disable stencil testing and ops.
614 */
615 void disableStencil() {
616 fStencilSettings.setDisabled();
617 }
618
619 const GrStencilSettings& getStencil() const { return fStencilSettings; }
620
621 GrStencilSettings* stencil() { return &fStencilSettings; }
622
623 /// @}
624
625 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000626 /// @name Color Matrix
627 ////
628
629 /**
630 * Sets the color matrix to use for the next draw.
631 * @param matrix the 5x4 matrix to apply to the incoming color
632 */
633 void setColorMatrix(const float matrix[20]) {
634 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
635 }
636
637 const float* getColorMatrix() const { return fColorMatrix; }
638
639 /// @}
640
641 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000642 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000643 // Edge equations can be specified to perform antialiasing. Because the
644 // edges are specified as per-vertex data, vertices that are shared by
645 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000647 ////
648
649 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000650 * When specifying edges as vertex data this enum specifies what type of
651 * edges are in use. The edges are always 4 GrScalars in memory, even when
652 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000653 *
654 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
655 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000656 */
657 enum VertexEdgeType {
658 /* 1-pixel wide line
659 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
660 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000661 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000662 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000663 being inside, positive outside. Edge specified in window space
664 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000665 kQuad_EdgeType,
666 /* Same as above but for hairline quadratics. Uses unsigned distance.
667 Coverage is min(0, 1-distance). */
668 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000669 /* Circle specified as center_x, center_y, outer_radius, inner_radius
670 all in window space (y-down). */
671 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000672
673 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000674 };
675
676 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000677 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000678 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
679 * are not specified the value of this setting has no effect.
680 */
681 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000682 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000683 fVertexEdgeType = type;
684 }
685
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000686 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000687
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000688 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000689
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000690 ///////////////////////////////////////////////////////////////////////////
691 /// @name State Flags
692 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000693
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000694 /**
695 * Flags that affect rendering. Controlled using enable/disableState(). All
696 * default to disabled.
697 */
698 enum StateBits {
699 /**
700 * Perform dithering. TODO: Re-evaluate whether we need this bit
701 */
702 kDither_StateBit = 0x01,
703 /**
704 * Perform HW anti-aliasing. This means either HW FSAA, if supported
705 * by the render target, or smooth-line rendering if a line primitive
706 * is drawn and line smoothing is supported by the 3D API.
707 */
708 kHWAntialias_StateBit = 0x02,
709 /**
710 * Draws will respect the clip, otherwise the clip is ignored.
711 */
712 kClip_StateBit = 0x04,
713 /**
714 * Disables writing to the color buffer. Useful when performing stencil
715 * operations.
716 */
717 kNoColorWrites_StateBit = 0x08,
718 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000719 * Draws will apply the color matrix, otherwise the color matrix is
720 * ignored.
721 */
bsalomon@google.com0342a852012-08-20 19:22:38 +0000722 kColorMatrix_StateBit = 0x10,
723
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000724 // Users of the class may add additional bits to the vector
725 kDummyStateBit,
726 kLastPublicStateBit = kDummyStateBit-1,
727 };
728
729 void resetStateFlags() {
730 fFlagBits = 0;
731 }
732
733 /**
734 * Enable render state settings.
735 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000736 * @param stateBits bitfield of StateBits specifing the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000737 */
738 void enableState(uint32_t stateBits) {
739 fFlagBits |= stateBits;
740 }
741
742 /**
743 * Disable render state settings.
744 *
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000745 * @param stateBits bitfield of StateBits specifing the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 */
747 void disableState(uint32_t stateBits) {
748 fFlagBits &= ~(stateBits);
749 }
750
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000751 /**
752 * Enable or disable stateBits based on a boolean.
753 *
754 * @param stateBits bitfield of StateBits to enable or disablt
755 * @param enable if true enable stateBits, otherwise disable
756 */
757 void setState(uint32_t stateBits, bool enable) {
758 if (enable) {
759 this->enableState(stateBits);
760 } else {
761 this->disableState(stateBits);
762 }
763 }
764
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765 bool isDitherState() const {
766 return 0 != (fFlagBits & kDither_StateBit);
767 }
768
769 bool isHWAntialiasState() const {
770 return 0 != (fFlagBits & kHWAntialias_StateBit);
771 }
772
773 bool isClipState() const {
774 return 0 != (fFlagBits & kClip_StateBit);
775 }
776
777 bool isColorWriteDisabled() const {
778 return 0 != (fFlagBits & kNoColorWrites_StateBit);
779 }
780
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000781 bool isStateFlagEnabled(uint32_t stateBit) const {
782 return 0 != (stateBit & fFlagBits);
783 }
784
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000785 /// @}
786
787 ///////////////////////////////////////////////////////////////////////////
788 /// @name Face Culling
789 ////
790
791 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000792 kInvalid_DrawFace = -1,
793
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000794 kBoth_DrawFace,
795 kCCW_DrawFace,
796 kCW_DrawFace,
797 };
798
799 /**
800 * Controls whether clockwise, counterclockwise, or both faces are drawn.
801 * @param face the face(s) to draw.
802 */
803 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000804 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000805 fDrawFace = face;
806 }
807
808 /**
809 * Gets whether the target is drawing clockwise, counterclockwise,
810 * or both faces.
811 * @return the current draw face(s).
812 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000813 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000814
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000815 /// @}
816
817 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000818
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000819 bool isStageEnabled(int s) const {
820 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000821 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000822 }
823
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000824 // Most stages are usually not used, so conditionals here
825 // reduce the expected number of bytes touched by 50%.
826 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000827 if (fColor != s.fColor ||
828 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
829 fRenderTarget != s.fRenderTarget ||
830 fSrcBlend != s.fSrcBlend ||
831 fDstBlend != s.fDstBlend ||
832 fBlendConstant != s.fBlendConstant ||
833 fFlagBits != s.fFlagBits ||
834 fVertexEdgeType != s.fVertexEdgeType ||
835 fStencilSettings != s.fStencilSettings ||
836 fFirstCoverageStage != s.fFirstCoverageStage ||
837 fCoverage != s.fCoverage ||
838 fColorFilterMode != s.fColorFilterMode ||
839 fColorFilterColor != s.fColorFilterColor ||
840 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000841 return false;
842 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000843
844 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000845 bool enabled = this->isStageEnabled(i);
846 if (enabled != s.isStageEnabled(i)) {
847 return false;
848 }
849 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000850 return false;
851 }
852 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000853 if (kColorMatrix_StateBit & s.fFlagBits) {
854 if (memcmp(fColorMatrix,
855 s.fColorMatrix,
856 sizeof(fColorMatrix))) {
857 return false;
858 }
859 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000860
861 return true;
862 }
863 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
864
rmistry@google.comd6176b02012-08-23 18:14:13 +0000865 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000866 // reduce the expected number of bytes touched by 50%.
867 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000868 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000869 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000870 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
871 fSrcBlend = s.fSrcBlend;
872 fDstBlend = s.fDstBlend;
873 fBlendConstant = s.fBlendConstant;
874 fFlagBits = s.fFlagBits;
875 fVertexEdgeType = s.fVertexEdgeType;
876 fStencilSettings = s.fStencilSettings;
877 fFirstCoverageStage = s.fFirstCoverageStage;
878 fCoverage = s.fCoverage;
879 fColorFilterMode = s.fColorFilterMode;
880 fColorFilterColor = s.fColorFilterColor;
881 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000882
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000883 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000884 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000885 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000886 }
887 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000888
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000889 if (kColorMatrix_StateBit & s.fFlagBits) {
890 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
891 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000892
893 return *this;
894 }
895
896private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000897
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000898 // These fields are roughly sorted by decreasing liklihood of being different in op==
899 GrColor fColor;
900 GrMatrix fViewMatrix;
901 GrRenderTarget* fRenderTarget;
902 GrBlendCoeff fSrcBlend;
903 GrBlendCoeff fDstBlend;
904 GrColor fBlendConstant;
905 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000906 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000907 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000908 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000909 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000910 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000911 GrColor fColorFilterColor;
912 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000913
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000914 // This field must be last; it will not be copied or compared
915 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000916 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000917 // only compared if the color matrix enable flag is set
918 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000919
reed@google.comfa35e3d2012-06-26 20:16:17 +0000920 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000921};
922
923#endif