blob: f3d5e37d20fec0cccec632444d4bcfffaa2a4386 [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
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000045 * through kNumStages-2 are earmarked for use by GrTextContext and
46 * GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
47 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000048 */
49 enum {
twiz@google.com58071162012-07-18 21:41:50 +000050 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000051 kMaxTexCoords = kNumStages
52 };
53
rmistry@google.comd6176b02012-08-23 18:14:13 +000054 GrDrawState()
robertphillips@google.com9ec07532012-06-22 12:01:30 +000055 : fRenderTarget(NULL) {
56
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000057 this->reset();
58 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000059
rmistry@google.comd6176b02012-08-23 18:14:13 +000060 GrDrawState(const GrDrawState& state)
robertphillips@google.com9ec07532012-06-22 12:01:30 +000061 : fRenderTarget(NULL) {
62
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000063 *this = state;
64 }
65
robertphillips@google.com9ec07532012-06-22 12:01:30 +000066 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000067 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000068 GrSafeSetNull(fRenderTarget);
69 }
70
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000071 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000072 * Resets to the default state.
73 * Sampler states *will* be modified: textures or CustomStage objects
74 * will be released.
rmistry@google.comd6176b02012-08-23 18:14:13 +000075 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000076 void reset() {
robertphillips@google.com9ec07532012-06-22 12:01:30 +000077
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000078 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000079
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000080 fColor = 0xffffffff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000081 fViewMatrix.reset();
82 GrSafeSetNull(fRenderTarget);
bsalomon@google.com47059542012-06-06 20:51:20 +000083 fSrcBlend = kOne_GrBlendCoeff;
84 fDstBlend = kZero_GrBlendCoeff;
bsalomon@google.com861b3a22012-09-26 17:28:25 +000085 fBlendConstant = 0x0;
86 fFlagBits = 0x0;
87 fVertexEdgeType = kHairLine_EdgeType;
88 fStencilSettings.setDisabled();
89 fFirstCoverageStage = kNumStages;
90 fCoverage = 0xffffffff;
91 fColorFilterMode = SkXfermode::kDst_Mode;
92 fColorFilterColor = 0x0;
93 fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000094 }
95
96 /**
97 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +000098 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +000099 * GrPaint equivalents are not modified. GrPaint has fewer stages than
100 * GrDrawState. The extra GrDrawState stages are disabled.
101 */
102 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000103
104 ///////////////////////////////////////////////////////////////////////////
105 /// @name Color
106 ////
107
108 /**
109 * Sets color for next draw to a premultiplied-alpha color.
110 *
111 * @param color the color to set.
112 */
113 void setColor(GrColor color) { fColor = color; }
114
115 GrColor getColor() const { return fColor; }
116
117 /**
118 * Sets the color to be used for the next draw to be
119 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
120 *
121 * @param alpha The alpha value to set as the color.
122 */
123 void setAlpha(uint8_t a) {
124 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
125 }
126
127 /**
128 * Add a color filter that can be represented by a color and a mode. Applied
129 * after color-computing texture stages.
130 */
131 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
132 fColorFilterColor = c;
133 fColorFilterMode = mode;
134 }
135
136 GrColor getColorFilterColor() const { return fColorFilterColor; }
137 SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
138
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000139 /**
140 * Constructor sets the color to be 'color' which is undone by the destructor.
141 */
142 class AutoColorRestore : public ::GrNoncopyable {
143 public:
144 AutoColorRestore(GrDrawState* drawState, GrColor color) {
145 fDrawState = drawState;
146 fOldColor = fDrawState->getColor();
147 fDrawState->setColor(color);
148 }
149 ~AutoColorRestore() {
150 fDrawState->setColor(fOldColor);
151 }
152 private:
153 GrDrawState* fDrawState;
154 GrColor fOldColor;
155 };
156
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000157 /// @}
158
159 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000160 /// @name Coverage
161 ////
162
163 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000165 * initial value (after construction or reset()) is 0xff. The constant
166 * coverage is ignored when per-vertex coverage is provided.
167 */
168 void setCoverage(uint8_t coverage) {
169 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
170 }
171
172 /**
173 * Version of above that specifies 4 channel per-vertex color. The value
174 * should be premultiplied.
175 */
176 void setCoverage4(GrColor coverage) {
177 fCoverage = coverage;
178 }
179
180 GrColor getCoverage() const {
181 return fCoverage;
182 }
183
184 /// @}
185
186 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000187 /// @name Textures
188 ////
189
190 /**
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000191 * Creates a GrSingleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000192 */
193 void createTextureEffect(int stage, GrTexture* texture) {
194 GrAssert(!this->getSampler(stage).getCustomStage());
195 this->sampler(stage)->setCustomStage(
196 SkNEW_ARGS(GrSingleTextureEffect, (texture)))->unref();
197 }
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000198 void createTextureEffect(int stage, GrTexture* texture, const GrMatrix& matrix) {
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000199 GrAssert(!this->getSampler(stage).getCustomStage());
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000200 GrCustomStage* customStage = SkNEW_ARGS(GrSingleTextureEffect, (texture));
201 this->sampler(stage)->setCustomStage(customStage, matrix)->unref();
202 }
203 void createTextureEffect(int stage, GrTexture* texture,
204 const GrMatrix& matrix,
205 const GrTextureParams& params) {
206 GrAssert(!this->getSampler(stage).getCustomStage());
207 GrCustomStage* customStage = SkNEW_ARGS(GrSingleTextureEffect, (texture, params));
208 this->sampler(stage)->setCustomStage(customStage, matrix)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000209 }
210
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000211
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000212 bool stagesDisabled() {
213 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000214 if (NULL != fSamplerStates[i].getCustomStage()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000215 return false;
216 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000217 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000218 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000219 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000220
221 void disableStage(int index) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000222 fSamplerStates[index].setCustomStage(NULL);
223 }
224
robertphillips@google.com972265d2012-06-13 18:49:30 +0000225 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000226 * Release all the textures and custom stages referred to by this
227 * draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000228 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000229 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000230 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000231 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000232 }
233 }
234
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000235 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000236 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000237 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
238 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000239 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000240 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000241 }
242 }
243 private:
244 GrDrawState* fDrawState;
245 };
246
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000247 /// @}
248
249 ///////////////////////////////////////////////////////////////////////////
250 /// @name Samplers
251 ////
252
253 /**
254 * Returns the current sampler for a stage.
255 */
256 const GrSamplerState& getSampler(int stage) const {
257 GrAssert((unsigned)stage < kNumStages);
258 return fSamplerStates[stage];
259 }
260
261 /**
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000262 * Writable pointer to a stage's sampler.
263 */
264 GrSamplerState* sampler(int stage) {
265 GrAssert((unsigned)stage < kNumStages);
266 return fSamplerStates + stage;
267 }
268
269 /**
bsalomon@google.come3d32162012-07-20 13:37:06 +0000270 * Preconcats the matrix of all samplers of enabled stages with a matrix.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000271 */
bsalomon@google.come3d32162012-07-20 13:37:06 +0000272 void preConcatSamplerMatrices(const GrMatrix& matrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000273 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000274 if (this->isStageEnabled(i)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000275 fSamplerStates[i].preConcatMatrix(matrix);
276 }
277 }
278 }
279
bsalomon@google.come3d32162012-07-20 13:37:06 +0000280 /**
281 * Preconcats the matrix of all samplers in the mask with the inverse of a
282 * matrix. If the matrix inverse cannot be computed (and there is at least
283 * one enabled stage) then false is returned.
284 */
285 bool preConcatSamplerMatricesWithInverse(const GrMatrix& matrix) {
286 GrMatrix inv;
287 bool computed = false;
288 for (int i = 0; i < kNumStages; ++i) {
289 if (this->isStageEnabled(i)) {
290 if (!computed && !matrix.invert(&inv)) {
291 return false;
292 } else {
293 computed = true;
294 }
295 fSamplerStates[i].preConcatMatrix(inv);
296 }
297 }
298 return true;
299 }
300
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000301 /// @}
302
303 ///////////////////////////////////////////////////////////////////////////
304 /// @name Coverage / Color Stages
305 ////
306
307 /**
308 * A common pattern is to compute a color with the initial stages and then
309 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000310 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
311 * computed based on the pre-coverage-modulated color. The division of
312 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000313 * this method. Initially this is kNumStages (all stages
314 * are color-computing).
315 */
316 void setFirstCoverageStage(int firstCoverageStage) {
317 GrAssert((unsigned)firstCoverageStage <= kNumStages);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000318 fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000319 }
320
321 /**
322 * Gets the index of the first coverage-computing stage.
323 */
324 int getFirstCoverageStage() const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000325 return fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000326 }
327
328 ///@}
329
330 ///////////////////////////////////////////////////////////////////////////
331 /// @name Blending
332 ////
333
334 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000335 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000336 *
337 * The blend function will be:
338 * D' = sat(S*srcCoef + D*dstCoef)
339 *
340 * where D is the existing destination color, S is the incoming source
341 * color, and D' is the new destination color that will be written. sat()
342 * is the saturation function.
343 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000344 * @param srcCoef coefficient applied to the src color.
345 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000346 */
347 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
348 fSrcBlend = srcCoeff;
349 fDstBlend = dstCoeff;
350 #if GR_DEBUG
351 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000352 case kDC_GrBlendCoeff:
353 case kIDC_GrBlendCoeff:
354 case kDA_GrBlendCoeff:
355 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000356 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
357 "coverage stages.\n");
358 break;
359 default:
360 break;
361 }
362 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000363 case kSC_GrBlendCoeff:
364 case kISC_GrBlendCoeff:
365 case kSA_GrBlendCoeff:
366 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000367 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
368 "coverage stages.\n");
369 break;
370 default:
371 break;
372 }
373 #endif
374 }
375
376 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
377 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
378
379 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
380 GrBlendCoeff* dstBlendCoeff) const {
381 *srcBlendCoeff = fSrcBlend;
382 *dstBlendCoeff = fDstBlend;
383 }
384
385 /**
386 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000387 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000388 * kConstC_GrBlendCoeff
389 * kIConstC_GrBlendCoeff
390 * kConstA_GrBlendCoeff
391 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000392 *
393 * @param constant the constant to set
394 */
395 void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
396
397 /**
398 * Retrieves the last value set by setBlendConstant()
399 * @return the blending constant value
400 */
401 GrColor getBlendConstant() const { return fBlendConstant; }
402
403 /// @}
404
405 ///////////////////////////////////////////////////////////////////////////
406 /// @name View Matrix
407 ////
408
409 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000410 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000411 *
412 * In the post-view-matrix space the rectangle [0,w]x[0,h]
413 * fully covers the render target. (w and h are the width and height of the
414 * the rendertarget.)
415 */
416 void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
417
418 /**
419 * Gets a writable pointer to the view matrix.
420 */
421 GrMatrix* viewMatrix() { return &fViewMatrix; }
422
423 /**
424 * Multiplies the current view matrix by a matrix
425 *
426 * After this call V' = V*m where V is the old view matrix,
427 * m is the parameter to this function, and V' is the new view matrix.
428 * (We consider positions to be column vectors so position vector p is
429 * transformed by matrix X as p' = X*p.)
430 *
431 * @param m the matrix used to modify the view matrix.
432 */
433 void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
434
435 /**
436 * Multiplies the current view matrix by a matrix
437 *
438 * After this call V' = m*V where V is the old view matrix,
439 * m is the parameter to this function, and V' is the new view matrix.
440 * (We consider positions to be column vectors so position vector p is
441 * transformed by matrix X as p' = X*p.)
442 *
443 * @param m the matrix used to modify the view matrix.
444 */
445 void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
446
447 /**
448 * Retrieves the current view matrix
449 * @return the current view matrix.
450 */
451 const GrMatrix& getViewMatrix() const { return fViewMatrix; }
452
453 /**
454 * Retrieves the inverse of the current view matrix.
455 *
456 * If the current view matrix is invertible, return true, and if matrix
457 * is non-null, copy the inverse into it. If the current view matrix is
458 * non-invertible, return false and ignore the matrix parameter.
459 *
460 * @param matrix if not null, will receive a copy of the current inverse.
461 */
462 bool getViewInverse(GrMatrix* matrix) const {
463 // TODO: determine whether we really need to leave matrix unmodified
464 // at call sites when inversion fails.
465 GrMatrix inverse;
466 if (fViewMatrix.invert(&inverse)) {
467 if (matrix) {
468 *matrix = inverse;
469 }
470 return true;
471 }
472 return false;
473 }
474
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000475 ////////////////////////////////////////////////////////////////////////////
476
477 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000478 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
479 * Stage matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000480 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 class AutoViewMatrixRestore : public ::GrNoncopyable {
482 public:
483 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000484
485 AutoViewMatrixRestore(GrDrawState* ds,
486 const GrMatrix& preconcatMatrix,
487 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000488 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000489 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000490 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000491
492 ~AutoViewMatrixRestore() { this->restore(); }
493
bsalomon@google.coma8347462012-10-08 18:59:39 +0000494 /**
495 * Can be called prior to destructor to restore the original matrix.
496 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000497 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000498
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000499 void set(GrDrawState* drawState,
500 const GrMatrix& preconcatMatrix,
501 uint32_t explicitCoordStageMask = 0);
502
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000503 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000504
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000505 private:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000506 GrDrawState* fDrawState;
507 GrMatrix fViewMatrix;
508 GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
509 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000510 };
511
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000512 ////////////////////////////////////////////////////////////////////////////
513
514 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000515 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
516 * destructor undoes the changes, restoring the view matrix that was set before the
517 * constructor. It is similar to passing the inverse of the current view matrix to
518 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000519 */
520 class AutoDeviceCoordDraw : ::GrNoncopyable {
521 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000522 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000523 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000524 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
525 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
526 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000527 */
528 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000529 uint32_t explicitCoordStageMask = 0) {
530 fDrawState = NULL;
531 this->set(drawState, explicitCoordStageMask);
532 }
533
bsalomon@google.coma8347462012-10-08 18:59:39 +0000534 ~AutoDeviceCoordDraw() { this->restore(); }
535
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000536 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
537
bsalomon@google.coma8347462012-10-08 18:59:39 +0000538 /**
539 * Returns true if this object was successfully initialized on to a GrDrawState. It may
540 * return false because a non-default constructor or set() were never called or because
541 * the view matrix was not invertible.
542 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000543 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000544
bsalomon@google.coma8347462012-10-08 18:59:39 +0000545 /**
546 * Returns the matrix that was set previously set on the drawState. This is only valid
547 * if succeeded returns true.
548 */
549 const GrMatrix& getOriginalMatrix() const {
550 GrAssert(this->succeeded());
551 return fViewMatrix;
552 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000553
bsalomon@google.coma8347462012-10-08 18:59:39 +0000554 /**
555 * Can be called prior to destructor to restore the original matrix.
556 */
557 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000558
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000559 private:
560 GrDrawState* fDrawState;
561 GrMatrix fViewMatrix;
562 GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000563 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000564 };
565
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000566 /// @}
567
568 ///////////////////////////////////////////////////////////////////////////
569 /// @name Render Target
570 ////
571
572 /**
573 * Sets the rendertarget used at the next drawing call
574 *
575 * @param target The render target to set.
576 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000577 void setRenderTarget(GrRenderTarget* target) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000578 GrSafeAssign(fRenderTarget, target);
579 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000580
581 /**
582 * Retrieves the currently set rendertarget.
583 *
584 * @return The currently set render target.
585 */
586 const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
587 GrRenderTarget* getRenderTarget() { return fRenderTarget; }
588
589 class AutoRenderTargetRestore : public ::GrNoncopyable {
590 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000591 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000592 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
593 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000594 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000595 this->set(ds, newTarget);
596 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000597 ~AutoRenderTargetRestore() { this->restore(); }
598
599 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000600 if (NULL != fDrawState) {
601 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000602 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000603 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000604 GrSafeSetNull(fSavedTarget);
605 }
606
607 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
608 this->restore();
609
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000610 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000611 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000613 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000614 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000615 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000616 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 }
618 private:
619 GrDrawState* fDrawState;
620 GrRenderTarget* fSavedTarget;
621 };
622
623 /// @}
624
625 ///////////////////////////////////////////////////////////////////////////
626 /// @name Stencil
627 ////
628
629 /**
630 * Sets the stencil settings to use for the next draw.
631 * Changing the clip has the side-effect of possibly zeroing
632 * out the client settable stencil bits. So multipass algorithms
633 * using stencil should not change the clip between passes.
634 * @param settings the stencil settings to use.
635 */
636 void setStencil(const GrStencilSettings& settings) {
637 fStencilSettings = settings;
638 }
639
640 /**
641 * Shortcut to disable stencil testing and ops.
642 */
643 void disableStencil() {
644 fStencilSettings.setDisabled();
645 }
646
647 const GrStencilSettings& getStencil() const { return fStencilSettings; }
648
649 GrStencilSettings* stencil() { return &fStencilSettings; }
650
651 /// @}
652
653 ///////////////////////////////////////////////////////////////////////////
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000654 /// @name Color Matrix
655 ////
656
657 /**
658 * Sets the color matrix to use for the next draw.
659 * @param matrix the 5x4 matrix to apply to the incoming color
660 */
661 void setColorMatrix(const float matrix[20]) {
662 memcpy(fColorMatrix, matrix, sizeof(fColorMatrix));
663 }
664
665 const float* getColorMatrix() const { return fColorMatrix; }
666
667 /// @}
668
669 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000670 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000671 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000672 // edges are specified as per-vertex data, vertices that are shared by
673 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000674 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000675 ////
676
677 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000678 * When specifying edges as vertex data this enum specifies what type of
679 * edges are in use. The edges are always 4 GrScalars in memory, even when
680 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000681 *
682 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
683 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000684 */
685 enum VertexEdgeType {
686 /* 1-pixel wide line
687 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
688 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000689 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000690 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000691 being inside, positive outside. Edge specified in window space
692 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000693 kQuad_EdgeType,
694 /* Same as above but for hairline quadratics. Uses unsigned distance.
695 Coverage is min(0, 1-distance). */
696 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000697 /* Circle specified as center_x, center_y, outer_radius, inner_radius
698 all in window space (y-down). */
699 kCircle_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000700
701 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000702 };
703
704 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000705 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000706 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
707 * are not specified the value of this setting has no effect.
708 */
709 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000710 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000711 fVertexEdgeType = type;
712 }
713
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000714 VertexEdgeType getVertexEdgeType() const { return fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000715
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000716 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000717
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000718 ///////////////////////////////////////////////////////////////////////////
719 /// @name State Flags
720 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000721
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000722 /**
723 * Flags that affect rendering. Controlled using enable/disableState(). All
724 * default to disabled.
725 */
726 enum StateBits {
727 /**
728 * Perform dithering. TODO: Re-evaluate whether we need this bit
729 */
730 kDither_StateBit = 0x01,
731 /**
732 * Perform HW anti-aliasing. This means either HW FSAA, if supported
733 * by the render target, or smooth-line rendering if a line primitive
734 * is drawn and line smoothing is supported by the 3D API.
735 */
736 kHWAntialias_StateBit = 0x02,
737 /**
738 * Draws will respect the clip, otherwise the clip is ignored.
739 */
740 kClip_StateBit = 0x04,
741 /**
742 * Disables writing to the color buffer. Useful when performing stencil
743 * operations.
744 */
745 kNoColorWrites_StateBit = 0x08,
746 /**
senorblanco@chromium.org50bdad82012-01-03 20:51:57 +0000747 * Draws will apply the color matrix, otherwise the color matrix is
748 * ignored.
749 */
bsalomon@google.com0342a852012-08-20 19:22:38 +0000750 kColorMatrix_StateBit = 0x10,
751
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000752 // Users of the class may add additional bits to the vector
753 kDummyStateBit,
754 kLastPublicStateBit = kDummyStateBit-1,
755 };
756
757 void resetStateFlags() {
758 fFlagBits = 0;
759 }
760
761 /**
762 * Enable render state settings.
763 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000764 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765 */
766 void enableState(uint32_t stateBits) {
767 fFlagBits |= stateBits;
768 }
769
770 /**
771 * Disable render state settings.
772 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000773 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000774 */
775 void disableState(uint32_t stateBits) {
776 fFlagBits &= ~(stateBits);
777 }
778
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000779 /**
780 * Enable or disable stateBits based on a boolean.
781 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000782 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000783 * @param enable if true enable stateBits, otherwise disable
784 */
785 void setState(uint32_t stateBits, bool enable) {
786 if (enable) {
787 this->enableState(stateBits);
788 } else {
789 this->disableState(stateBits);
790 }
791 }
792
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000793 bool isDitherState() const {
794 return 0 != (fFlagBits & kDither_StateBit);
795 }
796
797 bool isHWAntialiasState() const {
798 return 0 != (fFlagBits & kHWAntialias_StateBit);
799 }
800
801 bool isClipState() const {
802 return 0 != (fFlagBits & kClip_StateBit);
803 }
804
805 bool isColorWriteDisabled() const {
806 return 0 != (fFlagBits & kNoColorWrites_StateBit);
807 }
808
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000809 bool isStateFlagEnabled(uint32_t stateBit) const {
810 return 0 != (stateBit & fFlagBits);
811 }
812
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000813 /// @}
814
815 ///////////////////////////////////////////////////////////////////////////
816 /// @name Face Culling
817 ////
818
819 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000820 kInvalid_DrawFace = -1,
821
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000822 kBoth_DrawFace,
823 kCCW_DrawFace,
824 kCW_DrawFace,
825 };
826
827 /**
828 * Controls whether clockwise, counterclockwise, or both faces are drawn.
829 * @param face the face(s) to draw.
830 */
831 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000832 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000833 fDrawFace = face;
834 }
835
836 /**
837 * Gets whether the target is drawing clockwise, counterclockwise,
838 * or both faces.
839 * @return the current draw face(s).
840 */
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000841 DrawFace getDrawFace() const { return fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000842
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000843 /// @}
844
845 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000846
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000847 bool isStageEnabled(int s) const {
848 GrAssert((unsigned)s < kNumStages);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000849 return (NULL != fSamplerStates[s].getCustomStage());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000850 }
851
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000852 // Most stages are usually not used, so conditionals here
853 // reduce the expected number of bytes touched by 50%.
854 bool operator ==(const GrDrawState& s) const {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000855 if (fColor != s.fColor ||
856 !s.fViewMatrix.cheapEqualTo(fViewMatrix) ||
857 fRenderTarget != s.fRenderTarget ||
858 fSrcBlend != s.fSrcBlend ||
859 fDstBlend != s.fDstBlend ||
860 fBlendConstant != s.fBlendConstant ||
861 fFlagBits != s.fFlagBits ||
862 fVertexEdgeType != s.fVertexEdgeType ||
863 fStencilSettings != s.fStencilSettings ||
864 fFirstCoverageStage != s.fFirstCoverageStage ||
865 fCoverage != s.fCoverage ||
866 fColorFilterMode != s.fColorFilterMode ||
867 fColorFilterColor != s.fColorFilterColor ||
868 fDrawFace != s.fDrawFace) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000869 return false;
870 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000871
872 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000873 bool enabled = this->isStageEnabled(i);
874 if (enabled != s.isStageEnabled(i)) {
875 return false;
876 }
877 if (enabled && this->fSamplerStates[i] != s.fSamplerStates[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000878 return false;
879 }
880 }
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000881 if (kColorMatrix_StateBit & s.fFlagBits) {
882 if (memcmp(fColorMatrix,
883 s.fColorMatrix,
884 sizeof(fColorMatrix))) {
885 return false;
886 }
887 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000888
889 return true;
890 }
891 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
892
rmistry@google.comd6176b02012-08-23 18:14:13 +0000893 // Most stages are usually not used, so conditionals here
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000894 // reduce the expected number of bytes touched by 50%.
895 GrDrawState& operator =(const GrDrawState& s) {
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000896 fColor = s.fColor;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000897 fViewMatrix = s.fViewMatrix;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000898 SkRefCnt_SafeAssign(fRenderTarget, s.fRenderTarget);
899 fSrcBlend = s.fSrcBlend;
900 fDstBlend = s.fDstBlend;
901 fBlendConstant = s.fBlendConstant;
902 fFlagBits = s.fFlagBits;
903 fVertexEdgeType = s.fVertexEdgeType;
904 fStencilSettings = s.fStencilSettings;
905 fFirstCoverageStage = s.fFirstCoverageStage;
906 fCoverage = s.fCoverage;
907 fColorFilterMode = s.fColorFilterMode;
908 fColorFilterColor = s.fColorFilterColor;
909 fDrawFace = s.fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000910
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000911 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000912 if (s.isStageEnabled(i)) {
tomhudson@google.com02b1ea22012-04-30 20:19:07 +0000913 this->fSamplerStates[i] = s.fSamplerStates[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000914 }
915 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000916
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000917 if (kColorMatrix_StateBit & s.fFlagBits) {
918 memcpy(this->fColorMatrix, s.fColorMatrix, sizeof(fColorMatrix));
919 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000920
921 return *this;
922 }
923
924private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000925
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000926 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000927 GrColor fColor;
928 GrMatrix fViewMatrix;
929 GrRenderTarget* fRenderTarget;
930 GrBlendCoeff fSrcBlend;
931 GrBlendCoeff fDstBlend;
932 GrColor fBlendConstant;
933 uint32_t fFlagBits;
robertphillips@google.comc077d1e2012-05-28 14:10:15 +0000934 VertexEdgeType fVertexEdgeType;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000935 GrStencilSettings fStencilSettings;
robertphillips@google.com69ffcf02012-06-26 21:01:05 +0000936 int fFirstCoverageStage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000937 GrColor fCoverage;
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000938 SkXfermode::Mode fColorFilterMode;
bsalomon@google.com861b3a22012-09-26 17:28:25 +0000939 GrColor fColorFilterColor;
940 DrawFace fDrawFace;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000941
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000942 // This field must be last; it will not be copied or compared
943 // if the corresponding fTexture[] is NULL.
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +0000944 GrSamplerState fSamplerStates[kNumStages];
bsalomon@google.com9b1517e2012-03-05 17:58:34 +0000945 // only compared if the color matrix enable flag is set
946 float fColorMatrix[20]; // 5 x 4 matrix
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000947
reed@google.comfa35e3d2012-06-26 20:16:17 +0000948 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000949};
950
951#endif