blob: 54f2179fd58796b98e80d1a3550f36bfb5f153e9 [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.com2e3d1442012-03-26 20:33:54 +000013#include "GrRefCnt.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000014#include "GrSamplerState.h"
15#include "GrStencil.h"
bsalomon@google.com64aef2b2012-06-11 15:36:13 +000016#include "GrTexture.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000017#include "GrRenderTarget.h"
tomhudson@google.com1e8f0162012-07-20 16:25:18 +000018#include "effects/GrSingleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000019
20#include "SkXfermode.h"
21
bsalomon@google.comaf84e742012-10-05 13:23:24 +000022class GrPaint;
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 /**
bsalomon@google.com021fc732012-10-25 12:47:42 +000029 * Number of effect stages. Each stage takes as input a color and
tomhudson@google.com93813632011-10-27 20:21:16 +000030 * 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
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000044 * through kNumStages-2 are earmarked for use by GrTextContext and
45 * GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
46 * by GrClipMaskManager.
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.
bsalomon@google.com6f261be2012-10-24 19:07:10 +000072 * Sampler states *will* be modified: textures or GrEffect objects 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
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000078 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000079 fViewMatrix.reset();
80 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000081 fSrcBlend = kOne_GrBlendCoeff;
82 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000083 fBlendConstant = 0x0;
84 fFlagBits = 0x0;
85 fVertexEdgeType = kHairLine_EdgeType;
86 fStencilSettings.setDisabled();
87 fFirstCoverageStage = kNumStages;
88 fCoverage = 0xffffffff;
89 fColorFilterMode = SkXfermode::kDst_Mode;
90 fColorFilterColor = 0x0;
91 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000092 }
93
94 /**
95 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +000096 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +000097 * GrPaint equivalents are not modified. GrPaint has fewer stages than
98 * GrDrawState. The extra GrDrawState stages are disabled.
99 */
100 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000101
102 ///////////////////////////////////////////////////////////////////////////
103 /// @name Color
104 ////
105
106 /**
107 * Sets color for next draw to a premultiplied-alpha color.
108 *
109 * @param color the color to set.
110 */
111 void setColor(GrColor color) { fColor = color; }
112
113 GrColor getColor() const { return fColor; }
114
115 /**
116 * Sets the color to be used for the next draw to be
117 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
118 *
119 * @param alpha The alpha value to set as the color.
120 */
121 void setAlpha(uint8_t a) {
122 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
123 }
124
125 /**
126 * Add a color filter that can be represented by a color and a mode. Applied
127 * after color-computing texture stages.
128 */
129 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
130 fColorFilterColor = c;
131 fColorFilterMode = mode;
132 }
133
134 GrColor getColorFilterColor() const { return fColorFilterColor; }
135 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
136
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000137 /**
138 * Constructor sets the color to be 'color' which is undone by the destructor.
139 */
140 class AutoColorRestore : public ::GrNoncopyable {
141 public:
142 AutoColorRestore(GrDrawState* drawState, GrColor color) {
143 fDrawState = drawState;
144 fOldColor = fDrawState->getColor();
145 fDrawState->setColor(color);
146 }
147 ~AutoColorRestore() {
148 fDrawState->setColor(fOldColor);
149 }
150 private:
151 GrDrawState* fDrawState;
152 GrColor fOldColor;
153 };
154
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000155 /// @}
156
157 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000158 /// @name Coverage
159 ////
160
161 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000163 * initial value (after construction or reset()) is 0xff. The constant
164 * coverage is ignored when per-vertex coverage is provided.
165 */
166 void setCoverage(uint8_t coverage) {
167 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
168 }
169
170 /**
171 * Version of above that specifies 4 channel per-vertex color. The value
172 * should be premultiplied.
173 */
174 void setCoverage4(GrColor coverage) {
175 fCoverage = coverage;
176 }
177
178 GrColor getCoverage() const {
179 return fCoverage;
180 }
181
182 /// @}
183
184 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000185 /// @name Textures
186 ////
187
188 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000189 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000190 */
191 void createTextureEffect(int stage, GrTexture* texture) {
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000192 GrAssert(!this->getSampler(stage).getEffect());
bsalomon@google.com021fc732012-10-25 12:47:42 +0000193 this->sampler(stage)->setEffect(SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000194 }
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000195 void createTextureEffect(int stage, GrTexture* texture, const GrMatrix& matrix) {
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000196 GrAssert(!this->getSampler(stage).getEffect());
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000197 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture));
198 this->sampler(stage)->setEffect(effect, matrix)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000199 }
200 void createTextureEffect(int stage, GrTexture* texture,
201 const GrMatrix& matrix,
202 const GrTextureParams& params) {
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000203 GrAssert(!this->getSampler(stage).getEffect());
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000204 GrEffect* effect = SkNEW_ARGS(GrSingleTextureEffect, (texture, params));
205 this->sampler(stage)->setEffect(effect, matrix)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000206 }
207
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000208
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000209 bool stagesDisabled() {
210 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000211 if (NULL != fSamplerStates[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000212 return false;
213 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000214 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000215 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000216 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000217
218 void disableStage(int index) {
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000219 fSamplerStates[index].setEffect(NULL);
tomhudson@google.com676e6602012-07-10 17:21:48 +0000220 }
221
robertphillips@google.com972265d2012-06-13 18:49:30 +0000222 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000223 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000224 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000225 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000226 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000227 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000228 }
229 }
230
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000231 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000232 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000233 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
234 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000235 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000236 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000237 }
238 }
239 private:
240 GrDrawState* fDrawState;
241 };
242
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000243 /// @}
244
245 ///////////////////////////////////////////////////////////////////////////
246 /// @name Samplers
247 ////
248
249 /**
250 * Returns the current sampler for a stage.
251 */
252 const GrSamplerState& getSampler(int stage) const {
253 GrAssert((unsigned)stage < kNumStages);
254 return fSamplerStates[stage];
255 }
256
257 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000258 * Writable pointer to a stage's sampler.
259 */
260 GrSamplerState* sampler(int stage) {
261 GrAssert((unsigned)stage < kNumStages);
262 return fSamplerStates + stage;
263 }
264
265 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000266 * Called when the source coord system is changing. preConcat gives the transformation from the
267 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000268 */
bsalomon@google.com288d9542012-10-17 12:53:54 +0000269 void preConcatSamplerMatrices(const GrMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000270 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000271 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000272 fSamplerStates[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000273 }
274 }
275 }
276
bsalomon@google.come3d32162012-07-20 13:37:06 +0000277 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000278 * Called when the source coord system is changing. preConcatInverse is the inverse of the
279 * transformation from the old coord system to the new coord system. Returns false if the matrix
280 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000281 */
bsalomon@google.com288d9542012-10-17 12:53:54 +0000282 bool preConcatSamplerMatricesWithInverse(const GrMatrix& preConcatInverse) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000283 GrMatrix inv;
284 bool computed = false;
285 for (int i = 0; i < kNumStages; ++i) {
286 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000287 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000288 return false;
289 } else {
290 computed = true;
291 }
bsalomon@google.com288d9542012-10-17 12:53:54 +0000292 fSamplerStates[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000293 }
294 }
295 return true;
296 }
297
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000298 /// @}
299
300 ///////////////////////////////////////////////////////////////////////////
301 /// @name Coverage / Color Stages
302 ////
303
304 /**
305 * A common pattern is to compute a color with the initial stages and then
306 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000307 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
308 * computed based on the pre-coverage-modulated color. The division of
309 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000310 * this method. Initially this is kNumStages (all stages
311 * are color-computing).
312 */
313 void setFirstCoverageStage(int firstCoverageStage) {
314 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000315 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000316 }
317
318 /**
319 * Gets the index of the first coverage-computing stage.
320 */
321 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000322 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000323 }
324
325 ///@}
326
327 ///////////////////////////////////////////////////////////////////////////
328 /// @name Blending
329 ////
330
331 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000332 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000333 *
334 * The blend function will be:
335 * D' = sat(S*srcCoef + D*dstCoef)
336 *
337 * where D is the existing destination color, S is the incoming source
338 * color, and D' is the new destination color that will be written. sat()
339 * is the saturation function.
340 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000341 * @param srcCoef coefficient applied to the src color.
342 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000343 */
344 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
345 fSrcBlend = srcCoeff;
346 fDstBlend = dstCoeff;
347 #if GR_DEBUG
348 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000349 case kDC_GrBlendCoeff:
350 case kIDC_GrBlendCoeff:
351 case kDA_GrBlendCoeff:
352 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000353 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
354 "coverage stages.\n");
355 break;
356 default:
357 break;
358 }
359 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000360 case kSC_GrBlendCoeff:
361 case kISC_GrBlendCoeff:
362 case kSA_GrBlendCoeff:
363 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000364 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
365 "coverage stages.\n");
366 break;
367 default:
368 break;
369 }
370 #endif
371 }
372
373 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
374 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
375
376 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
377 GrBlendCoeff* dstBlendCoeff) const {
378 *srcBlendCoeff = fSrcBlend;
379 *dstBlendCoeff = fDstBlend;
380 }
381
382 /**
383 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000384 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000385 * kConstC_GrBlendCoeff
386 * kIConstC_GrBlendCoeff
387 * kConstA_GrBlendCoeff
388 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000389 *
390 * @param constant the constant to set
391 */
392 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
393
394 /**
395 * Retrieves the last value set by setBlendConstant()
396 * @return the blending constant value
397 */
398 GrColor getBlendConstant() const { return fBlendConstant; }
399
400 /// @}
401
402 ///////////////////////////////////////////////////////////////////////////
403 /// @name View Matrix
404 ////
405
406 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000407 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000408 *
409 * In the post-view-matrix space the rectangle [0,w]x[0,h]
410 * fully covers the render target. (w and h are the width and height of the
411 * the rendertarget.)
412 */
413 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
414
415 /**
416 * Gets a writable pointer to the view matrix.
417 */
418 GrMatrix* viewMatrix() { return &fViewMatrix; }
419
420 /**
421 * Multiplies the current view matrix by a matrix
422 *
423 * After this call V' = V*m where V is the old view matrix,
424 * m is the parameter to this function, and V' is the new view matrix.
425 * (We consider positions to be column vectors so position vector p is
426 * transformed by matrix X as p' = X*p.)
427 *
428 * @param m the matrix used to modify the view matrix.
429 */
430 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
431
432 /**
433 * Multiplies the current view matrix by a matrix
434 *
435 * After this call V' = m*V where V is the old view matrix,
436 * m is the parameter to this function, and V' is the new view matrix.
437 * (We consider positions to be column vectors so position vector p is
438 * transformed by matrix X as p' = X*p.)
439 *
440 * @param m the matrix used to modify the view matrix.
441 */
442 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
443
444 /**
445 * Retrieves the current view matrix
446 * @return the current view matrix.
447 */
448 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
449
450 /**
451 * Retrieves the inverse of the current view matrix.
452 *
453 * If the current view matrix is invertible, return true, and if matrix
454 * is non-null, copy the inverse into it. If the current view matrix is
455 * non-invertible, return false and ignore the matrix parameter.
456 *
457 * @param matrix if not null, will receive a copy of the current inverse.
458 */
459 bool getViewInverse(GrMatrix* matrix) const {
460 // TODO: determine whether we really need to leave matrix unmodified
461 // at call sites when inversion fails.
462 GrMatrix inverse;
463 if (fViewMatrix.invert(&inverse)) {
464 if (matrix) {
465 *matrix = inverse;
466 }
467 return true;
468 }
469 return false;
470 }
471
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000472 ////////////////////////////////////////////////////////////////////////////
473
474 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000475 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
476 * Stage matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000477 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000478 class AutoViewMatrixRestore : public ::GrNoncopyable {
479 public:
480 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000481
482 AutoViewMatrixRestore(GrDrawState* ds,
483 const GrMatrix& preconcatMatrix,
484 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000485 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000486 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000487 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000488
489 ~AutoViewMatrixRestore() { this->restore(); }
490
bsalomon@google.coma8347462012-10-08 18:59:39 +0000491 /**
492 * Can be called prior to destructor to restore the original matrix.
493 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000494 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000495
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000496 void set(GrDrawState* drawState,
497 const GrMatrix& preconcatMatrix,
498 uint32_t explicitCoordStageMask = 0);
499
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000500 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000501
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000502 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000503 GrDrawState* fDrawState;
504 GrMatrix fViewMatrix;
505 GrSamplerState::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
506 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000507 };
508
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000509 ////////////////////////////////////////////////////////////////////////////
510
511 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000512 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
513 * destructor undoes the changes, restoring the view matrix that was set before the
514 * constructor. It is similar to passing the inverse of the current view matrix to
515 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000516 */
517 class AutoDeviceCoordDraw : ::GrNoncopyable {
518 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000519 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000520 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000521 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
522 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
523 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000524 */
525 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000526 uint32_t explicitCoordStageMask = 0) {
527 fDrawState = NULL;
528 this->set(drawState, explicitCoordStageMask);
529 }
530
bsalomon@google.coma8347462012-10-08 18:59:39 +0000531 ~AutoDeviceCoordDraw() { this->restore(); }
532
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000533 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
534
bsalomon@google.coma8347462012-10-08 18:59:39 +0000535 /**
536 * Returns true if this object was successfully initialized on to a GrDrawState. It may
537 * return false because a non-default constructor or set() were never called or because
538 * the view matrix was not invertible.
539 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000540 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000541
bsalomon@google.coma8347462012-10-08 18:59:39 +0000542 /**
543 * Returns the matrix that was set previously set on the drawState. This is only valid
544 * if succeeded returns true.
545 */
546 const GrMatrix& getOriginalMatrix() const {
547 GrAssert(this->succeeded());
548 return fViewMatrix;
549 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000550
bsalomon@google.coma8347462012-10-08 18:59:39 +0000551 /**
552 * Can be called prior to destructor to restore the original matrix.
553 */
554 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000555
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000556 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000557 GrDrawState* fDrawState;
558 GrMatrix fViewMatrix;
559 GrSamplerState::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
560 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000561 };
562
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000563 /// @}
564
565 ///////////////////////////////////////////////////////////////////////////
566 /// @name Render Target
567 ////
568
569 /**
570 * Sets the rendertarget used at the next drawing call
571 *
572 * @param target The render target to set.
573 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000574 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000575 GrSafeAssign(fRenderTarget, target);
576 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000577
578 /**
579 * Retrieves the currently set rendertarget.
580 *
581 * @return The currently set render target.
582 */
583 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
584 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
585
586 class AutoRenderTargetRestore : public ::GrNoncopyable {
587 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000588 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000589 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
590 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000591 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 this->set(ds, newTarget);
593 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000594 ~AutoRenderTargetRestore() { this->restore(); }
595
596 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000597 if (NULL != fDrawState) {
598 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000599 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000601 GrSafeSetNull(fSavedTarget);
602 }
603
604 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
605 this->restore();
606
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000607 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000608 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000609 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000610 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000611 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000612 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000613 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000614 }
615 private:
616 GrDrawState* fDrawState;
617 GrRenderTarget* fSavedTarget;
618 };
619
620 /// @}
621
622 ///////////////////////////////////////////////////////////////////////////
623 /// @name Stencil
624 ////
625
626 /**
627 * Sets the stencil settings to use for the next draw.
628 * Changing the clip has the side-effect of possibly zeroing
629 * out the client settable stencil bits. So multipass algorithms
630 * using stencil should not change the clip between passes.
631 * @param settings the stencil settings to use.
632 */
633 void setStencil(const GrStencilSettings& settings) {
634 fStencilSettings = settings;
635 }
636
637 /**
638 * Shortcut to disable stencil testing and ops.
639 */
640 void disableStencil() {
641 fStencilSettings.setDisabled();
642 }
643
644 const GrStencilSettings& getStencil() const { return fStencilSettings; }
645
646 GrStencilSettings* stencil() { return &fStencilSettings; }
647
648 /// @}
649
650 ///////////////////////////////////////////////////////////////////////////
651 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000652 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000653 // edges are specified as per-vertex data, vertices that are shared by
654 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000655 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000656 ////
657
658 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000659 * When specifying edges as vertex data this enum specifies what type of
660 * edges are in use. The edges are always 4 GrScalars in memory, even when
661 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000662 *
663 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
664 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000665 */
666 enum VertexEdgeType {
667 /* 1-pixel wide line
668 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
669 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000670 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000671 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000672 being inside, positive outside. Edge specified in window space
673 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000674 kQuad_EdgeType,
675 /* Same as above but for hairline quadratics. Uses unsigned distance.
676 Coverage is min(0, 1-distance). */
677 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000678 /* Circle specified as center_x, center_y, outer_radius, inner_radius
679 all in window space (y-down). */
680 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000681
682 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000683 };
684
685 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000686 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000687 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
688 * are not specified the value of this setting has no effect.
689 */
690 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000691 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000692 fVertexEdgeType = type;
693 }
694
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000695 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000696
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000697 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000698
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000699 ///////////////////////////////////////////////////////////////////////////
700 /// @name State Flags
701 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000702
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000703 /**
704 * Flags that affect rendering. Controlled using enable/disableState(). All
705 * default to disabled.
706 */
707 enum StateBits {
708 /**
709 * Perform dithering. TODO: Re-evaluate whether we need this bit
710 */
711 kDither_StateBit = 0x01,
712 /**
713 * Perform HW anti-aliasing. This means either HW FSAA, if supported
714 * by the render target, or smooth-line rendering if a line primitive
715 * is drawn and line smoothing is supported by the 3D API.
716 */
717 kHWAntialias_StateBit = 0x02,
718 /**
719 * Draws will respect the clip, otherwise the clip is ignored.
720 */
721 kClip_StateBit = 0x04,
722 /**
723 * Disables writing to the color buffer. Useful when performing stencil
724 * operations.
725 */
726 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000727
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000728 // Users of the class may add additional bits to the vector
729 kDummyStateBit,
730 kLastPublicStateBit = kDummyStateBit-1,
731 };
732
733 void resetStateFlags() {
734 fFlagBits = 0;
735 }
736
737 /**
738 * Enable render state settings.
739 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000740 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000741 */
742 void enableState(uint32_t stateBits) {
743 fFlagBits |= stateBits;
744 }
745
746 /**
747 * Disable render state settings.
748 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000749 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000750 */
751 void disableState(uint32_t stateBits) {
752 fFlagBits &= ~(stateBits);
753 }
754
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000755 /**
756 * Enable or disable stateBits based on a boolean.
757 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000758 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000759 * @param enable if true enable stateBits, otherwise disable
760 */
761 void setState(uint32_t stateBits, bool enable) {
762 if (enable) {
763 this->enableState(stateBits);
764 } else {
765 this->disableState(stateBits);
766 }
767 }
768
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000769 bool isDitherState() const {
770 return 0 != (fFlagBits & kDither_StateBit);
771 }
772
773 bool isHWAntialiasState() const {
774 return 0 != (fFlagBits & kHWAntialias_StateBit);
775 }
776
777 bool isClipState() const {
778 return 0 != (fFlagBits & kClip_StateBit);
779 }
780
781 bool isColorWriteDisabled() const {
782 return 0 != (fFlagBits & kNoColorWrites_StateBit);
783 }
784
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000785 bool isStateFlagEnabled(uint32_t stateBit) const {
786 return 0 != (stateBit & fFlagBits);
787 }
788
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000789 /// @}
790
791 ///////////////////////////////////////////////////////////////////////////
792 /// @name Face Culling
793 ////
794
795 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000796 kInvalid_DrawFace = -1,
797
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000798 kBoth_DrawFace,
799 kCCW_DrawFace,
800 kCW_DrawFace,
801 };
802
803 /**
804 * Controls whether clockwise, counterclockwise, or both faces are drawn.
805 * @param face the face(s) to draw.
806 */
807 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000808 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000809 fDrawFace = face;
810 }
811
812 /**
813 * Gets whether the target is drawing clockwise, counterclockwise,
814 * or both faces.
815 * @return the current draw face(s).
816 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000817 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000818
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000819 /// @}
820
821 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000822
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000823 bool isStageEnabled(int s) const {
824 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com6f261be2012-10-24 19:07:10 +0000825 return (NULL != fSamplerStates[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000826 }
827
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000828 // Most stages are usually not used, so conditionals here
829 // reduce the expected number of bytes touched by 50%.
830 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000831 if (fColor != s.fColor ||
832 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
833 fRenderTarget != s.fRenderTarget ||
834 fSrcBlend != s.fSrcBlend ||
835 fDstBlend != s.fDstBlend ||
836 fBlendConstant != s.fBlendConstant ||
837 fFlagBits != s.fFlagBits ||
838 fVertexEdgeType != s.fVertexEdgeType ||
839 fStencilSettings != s.fStencilSettings ||
840 fFirstCoverageStage != s.fFirstCoverageStage ||
841 fCoverage != s.fCoverage ||
842 fColorFilterMode != s.fColorFilterMode ||
843 fColorFilterColor != s.fColorFilterColor ||
844 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000845 return false;
846 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000847
848 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000849 bool enabled = this->isStageEnabled(i);
850 if (enabled != s.isStageEnabled(i)) {
851 return false;
852 }
853 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000854 return false;
855 }
856 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000857 return true;
858 }
859 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
860
rmistry@google.comd6176b02012-08-23 18:14:13 +0000861 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000862 // reduce the expected number of bytes touched by 50%.
863 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000864 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000865 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000866 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
867 fSrcBlend = s.fSrcBlend;
868 fDstBlend = s.fDstBlend;
869 fBlendConstant = s.fBlendConstant;
870 fFlagBits = s.fFlagBits;
871 fVertexEdgeType = s.fVertexEdgeType;
872 fStencilSettings = s.fStencilSettings;
873 fFirstCoverageStage = s.fFirstCoverageStage;
874 fCoverage = s.fCoverage;
875 fColorFilterMode = s.fColorFilterMode;
876 fColorFilterColor = s.fColorFilterColor;
877 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000878
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000879 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000880 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000881 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000882 }
883 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000884
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000885 return *this;
886 }
887
888private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000889
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000890 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000891 GrColor fColor;
892 GrMatrix fViewMatrix;
893 GrRenderTarget* fRenderTarget;
894 GrBlendCoeff fSrcBlend;
895 GrBlendCoeff fDstBlend;
896 GrColor fBlendConstant;
897 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000898 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000899 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000900 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000901 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000902 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000903 GrColor fColorFilterColor;
904 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000905
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000906 // This field must be last; it will not be copied or compared
907 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000908 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000909
reed@google.comfa35e3d2012-06-26 20:16:17 +0000910 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000911};
912
913#endif