blob: 648c83ea7a35a2904bd1c9ccbff97e1e24723cef [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
tomhudson@google.com93813632011-10-27 20:21:16 +000023
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024class GrDrawState : public GrRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000025public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000026 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000027
tomhudson@google.com93813632011-10-27 20:21:16 +000028 /**
29 * Number of texture stages. Each stage takes as input a color and
30 * 2D texture coordinates. The color input to the first enabled stage is the
31 * per-vertex color or the constant color (setColor/setAlpha) if there are
32 * no per-vertex colors. For subsequent stages the input color is the output
33 * color from the previous enabled stage. The output color of each stage is
34 * the input color modulated with the result of a texture lookup. Texture
35 * lookups are specified by a texture a sampler (setSamplerState). Texture
36 * coordinates for each stage come from the vertices based on a
37 * GrVertexLayout bitfield. The output fragment color is the output color of
38 * the last enabled stage. The presence or absence of texture coordinates
39 * for each stage in the vertex layout indicates whether a stage is enabled
40 * or not.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000041 *
42 * Stages 0 through GrPaint::kTotalStages-1 are reserved for setting up
rmistry@google.comd6176b02012-08-23 18:14:13 +000043 * the draw (i.e., textures and filter masks). Stages GrPaint::kTotalStages
44 * through kNumStages-1 are earmarked for use by GrTextContext and
robertphillips@google.combf5cad42012-05-10 12:40:40 +000045 * GrPathRenderer-derived classes.
tomhudson@google.com93813632011-10-27 20:21:16 +000046 */
47 enum {
twiz@google.com58071162012-07-18 21:41:50 +000048 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000049 kMaxTexCoords = kNumStages
50 };
51
rmistry@google.comd6176b02012-08-23 18:14:13 +000052 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000053 : fRenderTarget(NULL) {
54
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000055 this->reset();
56 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000057
rmistry@google.comd6176b02012-08-23 18:14:13 +000058 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000059 : fRenderTarget(NULL) {
60
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000061 *this = state;
62 }
63
robertphillips@google.com9ec07532012-06-22 12:01:30 +000064 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000065 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000066 GrSafeSetNull(fRenderTarget);
67 }
68
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000069 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000070 * Resets to the default state.
71 * Sampler states *will* be modified: textures or CustomStage objects
72 * will be released.
rmistry@google.comd6176b02012-08-23 18:14:13 +000073 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000074 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000075
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000076 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000077 GrSafeSetNull(fRenderTarget);
78
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000079 // make sure any pad is zero for memcmp
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080 // all GrDrawState members should default to something valid by the
81 // the memset except those initialized individually below. There should
82 // be no padding between the individually initialized members.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000083 memset(this->podStart(), 0, this->memsetSize());
84
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000085 // pedantic assertion that our ptrs will
86 // be NULL (0 ptr is mem addr 0)
87 GrAssert((intptr_t)(void*)NULL == 0LL);
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000088 GR_STATIC_ASSERT(0 == kBoth_DrawFace);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000089 GrAssert(fStencilSettings.isDisabled());
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000090
91 // memset exceptions
92 fColor = 0xffffffff;
bsalomon@google.com2401ae82012-01-17 21:03:05 +000093 fCoverage = 0xffffffff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000094 fFirstCoverageStage = kNumStages;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000095 fColorFilterMode = SkXfermode::kDst_Mode;
bsalomon@google.com47059542012-06-06 20:51:20 +000096 fSrcBlend = kOne_GrBlendCoeff;
97 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000098 fViewMatrix.reset();
99
100 // ensure values that will be memcmp'ed in == but not memset in reset()
101 // are tightly packed
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000102 GrAssert(this->memsetSize() + sizeof(fColor) + sizeof(fCoverage) +
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000103 sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000104 sizeof(fSrcBlend) + sizeof(fDstBlend) + sizeof(fRenderTarget) ==
105 this->podSize());
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000106 }
107
108 ///////////////////////////////////////////////////////////////////////////
109 /// @name Color
110 ////
111
112 /**
113 * Sets color for next draw to a premultiplied-alpha color.
114 *
115 * @param color the color to set.
116 */
117 void setColor(GrColor color) { fColor = color; }
118
119 GrColor getColor() const { return fColor; }
120
121 /**
122 * Sets the color to be used for the next draw to be
123 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
124 *
125 * @param alpha The alpha value to set as the color.
126 */
127 void setAlpha(uint8_t a) {
128 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
129 }
130
131 /**
132 * Add a color filter that can be represented by a color and a mode. Applied
133 * after color-computing texture stages.
134 */
135 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
136 fColorFilterColor = c;
137 fColorFilterMode = mode;
138 }
139
140 GrColor getColorFilterColor() const { return fColorFilterColor; }
141 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
142
143 /// @}
144
145 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000146 /// @name Coverage
147 ////
148
149 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000150 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000151 * initial value (after construction or reset()) is 0xff. The constant
152 * coverage is ignored when per-vertex coverage is provided.
153 */
154 void setCoverage(uint8_t coverage) {
155 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
156 }
157
158 /**
159 * Version of above that specifies 4 channel per-vertex color. The value
160 * should be premultiplied.
161 */
162 void setCoverage4(GrColor coverage) {
163 fCoverage = coverage;
164 }
165
166 GrColor getCoverage() const {
167 return fCoverage;
168 }
169
170 /// @}
171
172 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000173 /// @name Textures
174 ////
175
176 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000177 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000178 */
179 void createTextureEffect(int stage, GrTexture* texture) {
180 GrAssert(!this->getSampler(stage).getCustomStage());
181 this->sampler(stage)->setCustomStage(
182 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
183 }
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000184 void createTextureEffect(int stage, GrTexture* texture, const GrTextureParams& params) {
185 GrAssert(!this->getSampler(stage).getCustomStage());
186 this->sampler(stage)->setCustomStage(
187 SkNEW_ARGS(GrSingleTextureEffect, (texture, params)))->unref();
188 }
189
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000190
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000191 bool stagesDisabled() {
192 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000193 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000194 return false;
195 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000196 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000197 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000198 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000199
200 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000201 fSamplerStates[index].setCustomStage(NULL);
202 }
203
robertphillips@google.com972265d2012-06-13 18:49:30 +0000204 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000205 * Release all the textures and custom stages referred to by this
206 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000207 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000208 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000209 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000210 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000211 }
212 }
213
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000214 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000215 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000216 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
217 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000218 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000219 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000220 }
221 }
222 private:
223 GrDrawState* fDrawState;
224 };
225
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000226 /// @}
227
228 ///////////////////////////////////////////////////////////////////////////
229 /// @name Samplers
230 ////
231
232 /**
233 * Returns the current sampler for a stage.
234 */
235 const GrSamplerState& getSampler(int stage) const {
236 GrAssert((unsigned)stage < kNumStages);
237 return fSamplerStates[stage];
238 }
239
240 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000241 * Writable pointer to a stage's sampler.
242 */
243 GrSamplerState* sampler(int stage) {
244 GrAssert((unsigned)stage < kNumStages);
245 return fSamplerStates + stage;
246 }
247
248 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000249 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000250 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000251 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000252 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000253 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000254 fSamplerStates[i].preConcatMatrix(matrix);
255 }
256 }
257 }
258
bsalomon@google.come3d32162012-07-20 13:37:06 +0000259 /**
260 * Preconcats the matrix of all samplers in the mask with the inverse of a
261 * matrix. If the matrix inverse cannot be computed (and there is at least
262 * one enabled stage) then false is returned.
263 */
264 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
265 GrMatrix inv;
266 bool computed = false;
267 for (int i = 0; i < kNumStages; ++i) {
268 if (this->isStageEnabled(i)) {
269 if (!computed && !matrix.invert(&inv)) {
270 return false;
271 } else {
272 computed = true;
273 }
274 fSamplerStates[i].preConcatMatrix(inv);
275 }
276 }
277 return true;
278 }
279
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000280 /// @}
281
282 ///////////////////////////////////////////////////////////////////////////
283 /// @name Coverage / Color Stages
284 ////
285
286 /**
287 * A common pattern is to compute a color with the initial stages and then
288 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000289 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
290 * computed based on the pre-coverage-modulated color. The division of
291 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000292 * this method. Initially this is kNumStages (all stages
293 * are color-computing).
294 */
295 void setFirstCoverageStage(int firstCoverageStage) {
296 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000297 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000298 }
299
300 /**
301 * Gets the index of the first coverage-computing stage.
302 */
303 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000304 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000305 }
306
307 ///@}
308
309 ///////////////////////////////////////////////////////////////////////////
310 /// @name Blending
311 ////
312
313 /**
314 * Sets the blending function coeffecients.
315 *
316 * The blend function will be:
317 * D' = sat(S*srcCoef + D*dstCoef)
318 *
319 * where D is the existing destination color, S is the incoming source
320 * color, and D' is the new destination color that will be written. sat()
321 * is the saturation function.
322 *
323 * @param srcCoef coeffecient applied to the src color.
324 * @param dstCoef coeffecient applied to the dst color.
325 */
326 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
327 fSrcBlend = srcCoeff;
328 fDstBlend = dstCoeff;
329 #if GR_DEBUG
330 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000331 case kDC_GrBlendCoeff:
332 case kIDC_GrBlendCoeff:
333 case kDA_GrBlendCoeff:
334 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000335 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
336 "coverage stages.\n");
337 break;
338 default:
339 break;
340 }
341 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000342 case kSC_GrBlendCoeff:
343 case kISC_GrBlendCoeff:
344 case kSA_GrBlendCoeff:
345 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000346 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
347 "coverage stages.\n");
348 break;
349 default:
350 break;
351 }
352 #endif
353 }
354
355 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
356 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
357
358 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
359 GrBlendCoeff* dstBlendCoeff) const {
360 *srcBlendCoeff = fSrcBlend;
361 *dstBlendCoeff = fDstBlend;
362 }
363
364 /**
365 * Sets the blending function constant referenced by the following blending
366 * coeffecients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000367 * kConstC_GrBlendCoeff
368 * kIConstC_GrBlendCoeff
369 * kConstA_GrBlendCoeff
370 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000371 *
372 * @param constant the constant to set
373 */
374 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
375
376 /**
377 * Retrieves the last value set by setBlendConstant()
378 * @return the blending constant value
379 */
380 GrColor getBlendConstant() const { return fBlendConstant; }
381
382 /// @}
383
384 ///////////////////////////////////////////////////////////////////////////
385 /// @name View Matrix
386 ////
387
388 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000389 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000390 *
391 * In the post-view-matrix space the rectangle [0,w]x[0,h]
392 * fully covers the render target. (w and h are the width and height of the
393 * the rendertarget.)
394 */
395 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
396
397 /**
398 * Gets a writable pointer to the view matrix.
399 */
400 GrMatrix* viewMatrix() { return &fViewMatrix; }
401
402 /**
403 * Multiplies the current view matrix by a matrix
404 *
405 * After this call V' = V*m where V is the old view matrix,
406 * m is the parameter to this function, and V' is the new view matrix.
407 * (We consider positions to be column vectors so position vector p is
408 * transformed by matrix X as p' = X*p.)
409 *
410 * @param m the matrix used to modify the view matrix.
411 */
412 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
413
414 /**
415 * Multiplies the current view matrix by a matrix
416 *
417 * After this call V' = m*V where V is the old view matrix,
418 * m is the parameter to this function, and V' is the new view matrix.
419 * (We consider positions to be column vectors so position vector p is
420 * transformed by matrix X as p' = X*p.)
421 *
422 * @param m the matrix used to modify the view matrix.
423 */
424 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
425
426 /**
427 * Retrieves the current view matrix
428 * @return the current view matrix.
429 */
430 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
431
432 /**
433 * Retrieves the inverse of the current view matrix.
434 *
435 * If the current view matrix is invertible, return true, and if matrix
436 * is non-null, copy the inverse into it. If the current view matrix is
437 * non-invertible, return false and ignore the matrix parameter.
438 *
439 * @param matrix if not null, will receive a copy of the current inverse.
440 */
441 bool getViewInverse(GrMatrix* matrix) const {
442 // TODO: determine whether we really need to leave matrix unmodified
443 // at call sites when inversion fails.
444 GrMatrix inverse;
445 if (fViewMatrix.invert(&inverse)) {
446 if (matrix) {
447 *matrix = inverse;
448 }
449 return true;
450 }
451 return false;
452 }
453
454 class AutoViewMatrixRestore : public ::GrNoncopyable {
455 public:
456 AutoViewMatrixRestore() : fDrawState(NULL) {}
457 AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) {
458 fDrawState = NULL;
459 this->set(ds, newMatrix);
460 }
461 AutoViewMatrixRestore(GrDrawState* ds) {
462 fDrawState = NULL;
463 this->set(ds);
464 }
465 ~AutoViewMatrixRestore() {
466 this->set(NULL, GrMatrix::I());
467 }
468 void set(GrDrawState* ds, const GrMatrix& newMatrix) {
469 if (NULL != fDrawState) {
470 fDrawState->setViewMatrix(fSavedMatrix);
471 }
472 if (NULL != ds) {
473 fSavedMatrix = ds->getViewMatrix();
474 ds->setViewMatrix(newMatrix);
475 }
476 fDrawState = ds;
477 }
478 void set(GrDrawState* ds) {
479 if (NULL != fDrawState) {
480 fDrawState->setViewMatrix(fSavedMatrix);
481 }
482 if (NULL != ds) {
483 fSavedMatrix = ds->getViewMatrix();
484 }
485 fDrawState = ds;
486 }
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000487 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488 private:
489 GrDrawState* fDrawState;
490 GrMatrix fSavedMatrix;
tomhudson@google.com93813632011-10-27 20:21:16 +0000491 };
492
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000493 /// @}
494
495 ///////////////////////////////////////////////////////////////////////////
496 /// @name Render Target
497 ////
498
499 /**
500 * Sets the rendertarget used at the next drawing call
501 *
502 * @param target The render target to set.
503 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000504 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000505 GrSafeAssign(fRenderTarget, target);
506 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000507
508 /**
509 * Retrieves the currently set rendertarget.
510 *
511 * @return The currently set render target.
512 */
513 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
514 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
515
516 class AutoRenderTargetRestore : public ::GrNoncopyable {
517 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000518 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000519 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
520 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000521 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000522 this->set(ds, newTarget);
523 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000524 ~AutoRenderTargetRestore() { this->restore(); }
525
526 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000527 if (NULL != fDrawState) {
528 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000529 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000530 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000531 GrSafeSetNull(fSavedTarget);
532 }
533
534 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
535 this->restore();
536
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000537 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000538 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000539 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000540 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000541 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000542 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000543 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000544 }
545 private:
546 GrDrawState* fDrawState;
547 GrRenderTarget* fSavedTarget;
548 };
549
550 /// @}
551
552 ///////////////////////////////////////////////////////////////////////////
553 /// @name Stencil
554 ////
555
556 /**
557 * Sets the stencil settings to use for the next draw.
558 * Changing the clip has the side-effect of possibly zeroing
559 * out the client settable stencil bits. So multipass algorithms
560 * using stencil should not change the clip between passes.
561 * @param settings the stencil settings to use.
562 */
563 void setStencil(const GrStencilSettings& settings) {
564 fStencilSettings = settings;
565 }
566
567 /**
568 * Shortcut to disable stencil testing and ops.
569 */
570 void disableStencil() {
571 fStencilSettings.setDisabled();
572 }
573
574 const GrStencilSettings& getStencil() const { return fStencilSettings; }
575
576 GrStencilSettings* stencil() { return &fStencilSettings; }
577
578 /// @}
579
580 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000581 /// @name Color Matrix
582 ////
583
584 /**
585 * Sets the color matrix to use for the next draw.
586 * @param matrix the 5x4 matrix to apply to the incoming color
587 */
588 void setColorMatrix(const float matrix[20]) {
589 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
590 }
591
592 const float* getColorMatrix() const { return fColorMatrix; }
593
594 /// @}
595
596 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 // @name Edge AA
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000598 // Edge equations can be specified to perform antialiasing. Because the
599 // edges are specified as per-vertex data, vertices that are shared by
600 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000601 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000602 ////
603
604 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000605 * When specifying edges as vertex data this enum specifies what type of
606 * edges are in use. The edges are always 4 GrScalars in memory, even when
607 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000608 *
609 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
610 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000611 */
612 enum VertexEdgeType {
613 /* 1-pixel wide line
614 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
615 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000616 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000617 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000618 being inside, positive outside. Edge specified in window space
619 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000620 kQuad_EdgeType,
621 /* Same as above but for hairline quadratics. Uses unsigned distance.
622 Coverage is min(0, 1-distance). */
623 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000624 /* Circle specified as center_x, center_y, outer_radius, inner_radius
625 all in window space (y-down). */
626 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000627
628 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000629 };
630
631 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000632 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000633 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
634 * are not specified the value of this setting has no effect.
635 */
636 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000637 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000638 fVertexEdgeType = type;
639 }
640
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000641 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000642
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000643 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000644
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000645 ///////////////////////////////////////////////////////////////////////////
646 /// @name State Flags
647 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000648
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000649 /**
650 * Flags that affect rendering. Controlled using enable/disableState(). All
651 * default to disabled.
652 */
653 enum StateBits {
654 /**
655 * Perform dithering. TODO: Re-evaluate whether we need this bit
656 */
657 kDither_StateBit = 0x01,
658 /**
659 * Perform HW anti-aliasing. This means either HW FSAA, if supported
660 * by the render target, or smooth-line rendering if a line primitive
661 * is drawn and line smoothing is supported by the 3D API.
662 */
663 kHWAntialias_StateBit = 0x02,
664 /**
665 * Draws will respect the clip, otherwise the clip is ignored.
666 */
667 kClip_StateBit = 0x04,
668 /**
669 * Disables writing to the color buffer. Useful when performing stencil
670 * operations.
671 */
672 kNoColorWrites_StateBit = 0x08,
673 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000674 * Draws will apply the color matrix, otherwise the color matrix is
675 * ignored.
676 */
bsalomon@google.com0342a852012-08-20 19:22:38 +0000677 kColorMatrix_StateBit = 0x10,
678
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000679 // Users of the class may add additional bits to the vector
680 kDummyStateBit,
681 kLastPublicStateBit = kDummyStateBit-1,
682 };
683
684 void resetStateFlags() {
685 fFlagBits = 0;
686 }
687
688 /**
689 * Enable render state settings.
690 *
691 * @param flags bitfield of StateBits specifing the states to enable
692 */
693 void enableState(uint32_t stateBits) {
694 fFlagBits |= stateBits;
695 }
696
697 /**
698 * Disable render state settings.
699 *
700 * @param flags bitfield of StateBits specifing the states to disable
701 */
702 void disableState(uint32_t stateBits) {
703 fFlagBits &= ~(stateBits);
704 }
705
706 bool isDitherState() const {
707 return 0 != (fFlagBits & kDither_StateBit);
708 }
709
710 bool isHWAntialiasState() const {
711 return 0 != (fFlagBits & kHWAntialias_StateBit);
712 }
713
714 bool isClipState() const {
715 return 0 != (fFlagBits & kClip_StateBit);
716 }
717
718 bool isColorWriteDisabled() const {
719 return 0 != (fFlagBits & kNoColorWrites_StateBit);
720 }
721
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 bool isStateFlagEnabled(uint32_t stateBit) const {
723 return 0 != (stateBit & fFlagBits);
724 }
725
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000726 /// @}
727
728 ///////////////////////////////////////////////////////////////////////////
729 /// @name Face Culling
730 ////
731
732 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000733 kInvalid_DrawFace = -1,
734
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000735 kBoth_DrawFace,
736 kCCW_DrawFace,
737 kCW_DrawFace,
738 };
739
740 /**
741 * Controls whether clockwise, counterclockwise, or both faces are drawn.
742 * @param face the face(s) to draw.
743 */
744 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000745 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000746 fDrawFace = face;
747 }
748
749 /**
750 * Gets whether the target is drawing clockwise, counterclockwise,
751 * or both faces.
752 * @return the current draw face(s).
753 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000754 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000755
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000756 /// @}
757
758 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000759
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000760 bool isStageEnabled(int s) const {
761 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000762 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000763 }
764
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000765 // Most stages are usually not used, so conditionals here
766 // reduce the expected number of bytes touched by 50%.
767 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000768 if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000769 return false;
770 }
771
772 if (!s.fViewMatrix.cheapEqualTo(fViewMatrix)) {
773 return false;
774 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000775
776 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000777 bool enabled = this->isStageEnabled(i);
778 if (enabled != s.isStageEnabled(i)) {
779 return false;
780 }
781 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000782 return false;
783 }
784 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000785 if (kColorMatrix_StateBit & s.fFlagBits) {
786 if (memcmp(fColorMatrix,
787 s.fColorMatrix,
788 sizeof(fColorMatrix))) {
789 return false;
790 }
791 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000792
793 return true;
794 }
795 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
796
rmistry@google.comd6176b02012-08-23 18:14:13 +0000797 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000798 // reduce the expected number of bytes touched by 50%.
799 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000800 memcpy(this->podStart(), s.podStart(), this->podSize());
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000801
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000802 fViewMatrix = s.fViewMatrix;
803
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000804 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000805 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000806 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000807 }
808 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000809
810 SkSafeRef(fRenderTarget); // already copied by memcpy
811
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000812 if (kColorMatrix_StateBit & s.fFlagBits) {
813 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
814 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000815
816 return *this;
817 }
818
819private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000820
821 const void* podStart() const {
822 return reinterpret_cast<const void*>(&fPodStartMarker);
823 }
824 void* podStart() {
825 return reinterpret_cast<void*>(&fPodStartMarker);
826 }
827 size_t memsetSize() const {
828 return reinterpret_cast<size_t>(&fMemsetEndMarker) -
829 reinterpret_cast<size_t>(&fPodStartMarker) +
830 sizeof(fMemsetEndMarker);
831 }
832 size_t podSize() const {
833 // Can't use offsetof() with non-POD types, so stuck with pointer math.
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000834 return reinterpret_cast<size_t>(&fPodEndMarker) -
835 reinterpret_cast<size_t>(&fPodStartMarker) +
836 sizeof(fPodEndMarker);
837 }
838
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000839 // @{ these fields can be initialized with memset to 0
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000840 union {
841 GrColor fBlendConstant;
842 GrColor fPodStartMarker;
843 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000844 GrColor fColorFilterColor;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000845 DrawFace fDrawFace;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000846 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000847 GrStencilSettings fStencilSettings;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000848 union {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000849 uint32_t fFlagBits;
850 uint32_t fMemsetEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000851 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000852 // @}
853
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000854 // @{ Initialized to values other than zero, but memcmp'ed in operator==
855 // and memcpy'ed in operator=.
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000856 GrRenderTarget* fRenderTarget;
857
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000858 int fFirstCoverageStage;
859
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000860 GrColor fColor;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000861 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000862 SkXfermode::Mode fColorFilterMode;
863 GrBlendCoeff fSrcBlend;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000864 union {
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000865 GrBlendCoeff fDstBlend;
866 GrBlendCoeff fPodEndMarker;
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000867 };
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000868 // @}
869
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000870 GrMatrix fViewMatrix;
871
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000872 // This field must be last; it will not be copied or compared
873 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000874 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000875 // only compared if the color matrix enable flag is set
876 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000877
reed@google.comfa35e3d2012-06-26 20:16:17 +0000878 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000879};
880
881#endif