blob: ba9eb217d6336b717a2c32916f839c86ebbd86e1 [file] [log] [blame]
tomhudson@google.com93813632011-10-27 20:21:16 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrDrawState_DEFINED
9#define GrDrawState_DEFINED
10
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +000011#include "GrBackendEffectFactory.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000012#include "GrColor.h"
bsalomon@google.comb9086a02012-11-01 18:02:54 +000013#include "SkMatrix.h"
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000014#include "GrRefCnt.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000015#include "GrEffectStage.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000016#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"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000019#include "effects/GrSimpleTextureEffect.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 /**
bsalomon@google.com13221342012-10-26 13:41:59 +000030 * Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
31 * GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
32 * output from the previous enabled stage and a position. The position is either derived from
33 * the interpolated vertex positions or explicit per-vertex coords, depending upon the
34 * GrVertexLayout used to draw.
robertphillips@google.combf5cad42012-05-10 12:40:40 +000035 *
bsalomon@google.com13221342012-10-26 13:41:59 +000036 * The stages are divided into two sets, color-computing and coverage-computing. The final color
37 * stage produces the final pixel color. The coverage-computing stages function exactly as the
38 * color-computing but the output of the final coverage stage is treated as a fractional pixel
39 * coverage rather than as input to the src/dst color blend step.
40 *
41 * The input color to the first enabled color-stage is either the constant color or interpolated
42 * per-vertex colors, depending upon GrVertexLayout. The input to the first coverage stage is
43 * either a constant coverage (usually full-coverage), interpolated per-vertex coverage, or
44 * edge-AA computed coverage. (This latter is going away as soon as it can be rewritten as a
45 * GrEffect).
46 *
bsalomon@google.comcf939ae2012-12-13 19:59:23 +000047 * See the documentation of kCoverageDrawing_StateBit for information about disabling the
48 * the color / coverage distinction.
49 *
bsalomon@google.com13221342012-10-26 13:41:59 +000050 * Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
51 * GrPaint. Stages GrPaint::kTotalStages through kNumStages-2 are earmarked for use by
52 * GrTextContext and GrPathRenderer-derived classes. kNumStages-1 is earmarked for clipping
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +000053 * by GrClipMaskManager.
tomhudson@google.com93813632011-10-27 20:21:16 +000054 */
55 enum {
twiz@google.com58071162012-07-18 21:41:50 +000056 kNumStages = 5,
tomhudson@google.com93813632011-10-27 20:21:16 +000057 kMaxTexCoords = kNumStages
58 };
59
bsalomon@google.comca432082013-01-23 19:53:46 +000060 GrDrawState() {
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000061 this->reset();
62 }
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000063
bsalomon@google.comca432082013-01-23 19:53:46 +000064 GrDrawState(const GrDrawState& state) {
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000065 *this = state;
66 }
67
robertphillips@google.com9ec07532012-06-22 12:01:30 +000068 virtual ~GrDrawState() {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000069 this->disableStages();
robertphillips@google.com9ec07532012-06-22 12:01:30 +000070 }
71
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000072 /**
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +000073 * Resets to the default state.
bsalomon@google.com08283af2012-10-26 13:01:20 +000074 * GrEffects will be removed from all stages.
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.comca432082013-01-23 19:53:46 +000080 fRenderTarget.reset(NULL);
81
82 fCommon.fColor = 0xffffffff;
83 fCommon.fViewMatrix.reset();
84 fCommon.fSrcBlend = kOne_GrBlendCoeff;
85 fCommon.fDstBlend = kZero_GrBlendCoeff;
86 fCommon.fBlendConstant = 0x0;
87 fCommon.fFlagBits = 0x0;
88 fCommon.fVertexEdgeType = kHairLine_EdgeType;
89 fCommon.fStencilSettings.setDisabled();
90 fCommon.fFirstCoverageStage = kNumStages;
91 fCommon.fCoverage = 0xffffffff;
92 fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
93 fCommon.fColorFilterColor = 0x0;
94 fCommon.fDrawFace = kBoth_DrawFace;
bsalomon@google.comaf84e742012-10-05 13:23:24 +000095 }
96
97 /**
98 * Initializes the GrDrawState based on a GrPaint. Note that GrDrawState
bsalomon@google.com1e269b52012-10-15 14:25:31 +000099 * encompasses more than GrPaint. Aspects of GrDrawState that have no
bsalomon@google.comaf84e742012-10-05 13:23:24 +0000100 * GrPaint equivalents are not modified. GrPaint has fewer stages than
101 * GrDrawState. The extra GrDrawState stages are disabled.
102 */
103 void setFromPaint(const GrPaint& paint);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000104
105 ///////////////////////////////////////////////////////////////////////////
106 /// @name Color
107 ////
108
109 /**
110 * Sets color for next draw to a premultiplied-alpha color.
111 *
112 * @param color the color to set.
113 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000114 void setColor(GrColor color) { fCommon.fColor = color; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000115
bsalomon@google.comca432082013-01-23 19:53:46 +0000116 GrColor getColor() const { return fCommon.fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000117
118 /**
119 * Sets the color to be used for the next draw to be
120 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
121 *
122 * @param alpha The alpha value to set as the color.
123 */
124 void setAlpha(uint8_t a) {
125 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
126 }
127
128 /**
129 * Add a color filter that can be represented by a color and a mode. Applied
130 * after color-computing texture stages.
131 */
132 void setColorFilter(GrColor c, SkXfermode::Mode mode) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000133 fCommon.fColorFilterColor = c;
134 fCommon.fColorFilterMode = mode;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000135 }
136
bsalomon@google.comca432082013-01-23 19:53:46 +0000137 GrColor getColorFilterColor() const { return fCommon.fColorFilterColor; }
138 SkXfermode::Mode getColorFilterMode() const { return fCommon.fColorFilterMode; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000139
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000140 /**
141 * Constructor sets the color to be 'color' which is undone by the destructor.
142 */
143 class AutoColorRestore : public ::GrNoncopyable {
144 public:
145 AutoColorRestore(GrDrawState* drawState, GrColor color) {
146 fDrawState = drawState;
147 fOldColor = fDrawState->getColor();
148 fDrawState->setColor(color);
149 }
150 ~AutoColorRestore() {
151 fDrawState->setColor(fOldColor);
152 }
153 private:
154 GrDrawState* fDrawState;
155 GrColor fOldColor;
156 };
157
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000158 /// @}
159
160 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000161 /// @name Coverage
162 ////
163
164 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000166 * initial value (after construction or reset()) is 0xff. The constant
167 * coverage is ignored when per-vertex coverage is provided.
168 */
169 void setCoverage(uint8_t coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000170 fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000171 }
172
173 /**
174 * Version of above that specifies 4 channel per-vertex color. The value
175 * should be premultiplied.
176 */
177 void setCoverage4(GrColor coverage) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000178 fCommon.fCoverage = coverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000179 }
180
181 GrColor getCoverage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000182 return fCommon.fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000183 }
184
185 /// @}
186
187 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000188 /// @name Textures
189 ////
190
191 /**
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000192 * Creates a GrSimpleTextureEffect.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000193 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000194 void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000195 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000196 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000197 this->stage(stageIdx)->setEffect(effect)->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000198 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000199 void createTextureEffect(int stageIdx,
200 GrTexture* texture,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000201 const SkMatrix& matrix,
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000202 const GrTextureParams& params) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000203 GrAssert(!this->getStage(stageIdx).getEffect());
bsalomon@google.com68b58c92013-01-17 16:50:08 +0000204 GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000205 this->stage(stageIdx)->setEffect(effect)->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000206 }
207
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000208 bool stagesDisabled() {
209 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000210 if (NULL != fStages[i].getEffect()) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000211 return false;
212 }
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000213 }
tomhudson@google.com3eee8fb2012-06-25 12:30:34 +0000214 return true;
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000215 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000216
bsalomon@google.com08283af2012-10-26 13:01:20 +0000217 void disableStage(int stageIdx) {
218 fStages[stageIdx].setEffect(NULL);
tomhudson@google.com676e6602012-07-10 17:21:48 +0000219 }
220
robertphillips@google.com972265d2012-06-13 18:49:30 +0000221 /**
bsalomon@google.comf271cc72012-10-24 19:35:13 +0000222 * Release all the GrEffects referred to by this draw state.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000223 */
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000224 void disableStages() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000225 for (int i = 0; i < kNumStages; ++i) {
tomhudson@google.com676e6602012-07-10 17:21:48 +0000226 this->disableStage(i);
robertphillips@google.com972265d2012-06-13 18:49:30 +0000227 }
228 }
229
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000230 class AutoStageDisable : public ::GrNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000231 public:
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000232 AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
233 ~AutoStageDisable() {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000234 if (NULL != fDrawState) {
tomhudson@google.com7d6afdd2012-06-22 20:10:50 +0000235 fDrawState->disableStages();
robertphillips@google.com972265d2012-06-13 18:49:30 +0000236 }
237 }
238 private:
239 GrDrawState* fDrawState;
240 };
241
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000242 /// @}
243
244 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com08283af2012-10-26 13:01:20 +0000245 /// @name Stages
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000246 ////
247
248 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000249 * Returns the current stage by index.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000250 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000251 const GrEffectStage& getStage(int stageIdx) const {
252 GrAssert((unsigned)stageIdx < kNumStages);
253 return fStages[stageIdx];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000254 }
255
256 /**
bsalomon@google.com08283af2012-10-26 13:01:20 +0000257 * Writable pointer to a stage.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000258 */
bsalomon@google.com08283af2012-10-26 13:01:20 +0000259 GrEffectStage* stage(int stageIdx) {
260 GrAssert((unsigned)stageIdx < kNumStages);
261 return fStages + stageIdx;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000262 }
263
264 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000265 * Called when the source coord system is changing. preConcat gives the transformation from the
266 * old coord system to the new coord system.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000267 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000268 void preConcatStageMatrices(const SkMatrix& preConcat) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000269 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000270 if (this->isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000271 fStages[i].preConcatCoordChange(preConcat);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000272 }
273 }
274 }
275
bsalomon@google.come3d32162012-07-20 13:37:06 +0000276 /**
bsalomon@google.com288d9542012-10-17 12:53:54 +0000277 * Called when the source coord system is changing. preConcatInverse is the inverse of the
278 * transformation from the old coord system to the new coord system. Returns false if the matrix
279 * cannot be inverted.
bsalomon@google.come3d32162012-07-20 13:37:06 +0000280 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000281 bool preConcatStageMatricesWithInverse(const SkMatrix& preConcatInverse) {
282 SkMatrix inv;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000283 bool computed = false;
284 for (int i = 0; i < kNumStages; ++i) {
285 if (this->isStageEnabled(i)) {
bsalomon@google.com288d9542012-10-17 12:53:54 +0000286 if (!computed && !preConcatInverse.invert(&inv)) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000287 return false;
288 } else {
289 computed = true;
290 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000291 fStages[i].preConcatCoordChange(preConcatInverse);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000292 }
293 }
294 return true;
295 }
296
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000297 /// @}
298
299 ///////////////////////////////////////////////////////////////////////////
300 /// @name Coverage / Color Stages
301 ////
302
303 /**
304 * A common pattern is to compute a color with the initial stages and then
305 * modulate that color by a coverage value in later stage(s) (AA, mask-
rmistry@google.comd6176b02012-08-23 18:14:13 +0000306 * filters, glyph mask, etc). Color-filters, xfermodes, etc should be
307 * computed based on the pre-coverage-modulated color. The division of
308 * stages between color-computing and coverage-computing is specified by
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000309 * this method. Initially this is kNumStages (all stages
310 * are color-computing).
311 */
312 void setFirstCoverageStage(int firstCoverageStage) {
313 GrAssert((unsigned)firstCoverageStage <= kNumStages);
bsalomon@google.comca432082013-01-23 19:53:46 +0000314 fCommon.fFirstCoverageStage = firstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000315 }
316
317 /**
318 * Gets the index of the first coverage-computing stage.
319 */
320 int getFirstCoverageStage() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000321 return fCommon.fFirstCoverageStage;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000322 }
323
324 ///@}
325
326 ///////////////////////////////////////////////////////////////////////////
327 /// @name Blending
328 ////
329
330 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000331 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000332 *
333 * The blend function will be:
334 * D' = sat(S*srcCoef + D*dstCoef)
335 *
336 * where D is the existing destination color, S is the incoming source
337 * color, and D' is the new destination color that will be written. sat()
338 * is the saturation function.
339 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000340 * @param srcCoef coefficient applied to the src color.
341 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000342 */
343 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000344 fCommon.fSrcBlend = srcCoeff;
345 fCommon.fDstBlend = dstCoeff;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000346 #if GR_DEBUG
347 switch (dstCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000348 case kDC_GrBlendCoeff:
349 case kIDC_GrBlendCoeff:
350 case kDA_GrBlendCoeff:
351 case kIDA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000352 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
353 "coverage stages.\n");
354 break;
355 default:
356 break;
357 }
358 switch (srcCoeff) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000359 case kSC_GrBlendCoeff:
360 case kISC_GrBlendCoeff:
361 case kSA_GrBlendCoeff:
362 case kISA_GrBlendCoeff:
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000363 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
364 "coverage stages.\n");
365 break;
366 default:
367 break;
368 }
369 #endif
370 }
371
bsalomon@google.comca432082013-01-23 19:53:46 +0000372 GrBlendCoeff getSrcBlendCoeff() const { return fCommon.fSrcBlend; }
373 GrBlendCoeff getDstBlendCoeff() const { return fCommon.fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000374
375 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
376 GrBlendCoeff* dstBlendCoeff) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000377 *srcBlendCoeff = fCommon.fSrcBlend;
378 *dstBlendCoeff = fCommon.fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000379 }
380
381 /**
382 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000383 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000384 * kConstC_GrBlendCoeff
385 * kIConstC_GrBlendCoeff
386 * kConstA_GrBlendCoeff
387 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000388 *
389 * @param constant the constant to set
390 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000391 void setBlendConstant(GrColor constant) { fCommon.fBlendConstant = constant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000392
393 /**
394 * Retrieves the last value set by setBlendConstant()
395 * @return the blending constant value
396 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000397 GrColor getBlendConstant() const { return fCommon.fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000398
399 /// @}
400
401 ///////////////////////////////////////////////////////////////////////////
402 /// @name View Matrix
403 ////
404
405 /**
robertphillips@google.coma72eef32012-05-01 17:22:59 +0000406 * Sets the matrix applied to vertex positions.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000407 *
408 * In the post-view-matrix space the rectangle [0,w]x[0,h]
409 * fully covers the render target. (w and h are the width and height of the
bsalomon@google.comca432082013-01-23 19:53:46 +0000410 * the render-target.)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000411 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000412 void setViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix = m; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000413
414 /**
415 * Gets a writable pointer to the view matrix.
416 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000417 SkMatrix* viewMatrix() { return &fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000418
419 /**
420 * Multiplies the current view matrix by a matrix
421 *
422 * After this call V' = V*m where V is the old view matrix,
423 * m is the parameter to this function, and V' is the new view matrix.
424 * (We consider positions to be column vectors so position vector p is
425 * transformed by matrix X as p' = X*p.)
426 *
427 * @param m the matrix used to modify the view matrix.
428 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000429 void preConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.preConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000430
431 /**
432 * Multiplies the current view matrix by a matrix
433 *
434 * After this call V' = m*V where V is the old view matrix,
435 * m is the parameter to this function, and V' is the new view matrix.
436 * (We consider positions to be column vectors so position vector p is
437 * transformed by matrix X as p' = X*p.)
438 *
439 * @param m the matrix used to modify the view matrix.
440 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000441 void postConcatViewMatrix(const SkMatrix& m) { fCommon.fViewMatrix.postConcat(m); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000442
443 /**
444 * Retrieves the current view matrix
445 * @return the current view matrix.
446 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000447 const SkMatrix& getViewMatrix() const { return fCommon.fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000448
449 /**
450 * Retrieves the inverse of the current view matrix.
451 *
452 * If the current view matrix is invertible, return true, and if matrix
453 * is non-null, copy the inverse into it. If the current view matrix is
454 * non-invertible, return false and ignore the matrix parameter.
455 *
456 * @param matrix if not null, will receive a copy of the current inverse.
457 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000458 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000459 // TODO: determine whether we really need to leave matrix unmodified
460 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000461 SkMatrix inverse;
bsalomon@google.comca432082013-01-23 19:53:46 +0000462 if (fCommon.fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000463 if (matrix) {
464 *matrix = inverse;
465 }
466 return true;
467 }
468 return false;
469 }
470
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000471 ////////////////////////////////////////////////////////////////////////////
472
473 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000474 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.comc196b522012-10-25 21:52:43 +0000475 * Effect matrices are automatically adjusted to compensate.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000476 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000477 class AutoViewMatrixRestore : public ::GrNoncopyable {
478 public:
479 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000480
481 AutoViewMatrixRestore(GrDrawState* ds,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000482 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000483 uint32_t explicitCoordStageMask = 0) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000484 fDrawState = NULL;
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000485 this->set(ds, preconcatMatrix, explicitCoordStageMask);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000486 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000487
488 ~AutoViewMatrixRestore() { this->restore(); }
489
bsalomon@google.coma8347462012-10-08 18:59:39 +0000490 /**
491 * Can be called prior to destructor to restore the original matrix.
492 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000493 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000494
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000495 void set(GrDrawState* drawState,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000496 const SkMatrix& preconcatMatrix,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000497 uint32_t explicitCoordStageMask = 0);
498
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000499 bool isSet() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000500
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000501 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000502 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000503 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000504 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000505 uint32_t fRestoreMask;
tomhudson@google.com93813632011-10-27 20:21:16 +0000506 };
507
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000508 ////////////////////////////////////////////////////////////////////////////
509
510 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000511 * This sets the view matrix to identity and adjusts stage matrices to compensate. The
512 * destructor undoes the changes, restoring the view matrix that was set before the
513 * constructor. It is similar to passing the inverse of the current view matrix to
514 * AutoViewMatrixRestore, but lazily computes the inverse only if necessary.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000515 */
516 class AutoDeviceCoordDraw : ::GrNoncopyable {
517 public:
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000518 AutoDeviceCoordDraw() : fDrawState(NULL) {}
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000519 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000520 * If a stage's texture matrix is applied to explicit per-vertex coords, rather than to
521 * positions, then we don't want to modify its matrix. The explicitCoordStageMask is used
522 * to specify such stages.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000523 */
524 AutoDeviceCoordDraw(GrDrawState* drawState,
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000525 uint32_t explicitCoordStageMask = 0) {
526 fDrawState = NULL;
527 this->set(drawState, explicitCoordStageMask);
528 }
529
bsalomon@google.coma8347462012-10-08 18:59:39 +0000530 ~AutoDeviceCoordDraw() { this->restore(); }
531
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000532 bool set(GrDrawState* drawState, uint32_t explicitCoordStageMask = 0);
533
bsalomon@google.coma8347462012-10-08 18:59:39 +0000534 /**
535 * Returns true if this object was successfully initialized on to a GrDrawState. It may
536 * return false because a non-default constructor or set() were never called or because
537 * the view matrix was not invertible.
538 */
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000539 bool succeeded() const { return NULL != fDrawState; }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000540
bsalomon@google.coma8347462012-10-08 18:59:39 +0000541 /**
542 * Returns the matrix that was set previously set on the drawState. This is only valid
543 * if succeeded returns true.
544 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000545 const SkMatrix& getOriginalMatrix() const {
bsalomon@google.coma8347462012-10-08 18:59:39 +0000546 GrAssert(this->succeeded());
547 return fViewMatrix;
548 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000549
bsalomon@google.coma8347462012-10-08 18:59:39 +0000550 /**
551 * Can be called prior to destructor to restore the original matrix.
552 */
553 void restore();
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000554
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000555 private:
bsalomon@google.com288d9542012-10-17 12:53:54 +0000556 GrDrawState* fDrawState;
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000557 SkMatrix fViewMatrix;
bsalomon@google.com08283af2012-10-26 13:01:20 +0000558 GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
bsalomon@google.com288d9542012-10-17 12:53:54 +0000559 uint32_t fRestoreMask;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000560 };
561
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000562 /// @}
563
564 ///////////////////////////////////////////////////////////////////////////
565 /// @name Render Target
566 ////
567
568 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000569 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000570 *
571 * @param target The render target to set.
572 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000573 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000574 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000575 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000576
577 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000578 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000579 *
580 * @return The currently set render target.
581 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000582 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
583 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000584
585 class AutoRenderTargetRestore : public ::GrNoncopyable {
586 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000587 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000588 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
589 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000590 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 this->set(ds, newTarget);
592 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000593 ~AutoRenderTargetRestore() { this->restore(); }
594
595 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000596 if (NULL != fDrawState) {
597 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000598 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000599 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000600 GrSafeSetNull(fSavedTarget);
601 }
602
603 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
604 this->restore();
605
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000606 if (NULL != ds) {
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000607 GrAssert(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000608 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000609 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000610 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000611 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000612 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000613 }
614 private:
615 GrDrawState* fDrawState;
616 GrRenderTarget* fSavedTarget;
617 };
618
619 /// @}
620
621 ///////////////////////////////////////////////////////////////////////////
622 /// @name Stencil
623 ////
624
625 /**
626 * Sets the stencil settings to use for the next draw.
627 * Changing the clip has the side-effect of possibly zeroing
628 * out the client settable stencil bits. So multipass algorithms
629 * using stencil should not change the clip between passes.
630 * @param settings the stencil settings to use.
631 */
632 void setStencil(const GrStencilSettings& settings) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000633 fCommon.fStencilSettings = settings;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000634 }
635
636 /**
637 * Shortcut to disable stencil testing and ops.
638 */
639 void disableStencil() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000640 fCommon.fStencilSettings.setDisabled();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641 }
642
bsalomon@google.comca432082013-01-23 19:53:46 +0000643 const GrStencilSettings& getStencil() const { return fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000644
bsalomon@google.comca432082013-01-23 19:53:46 +0000645 GrStencilSettings* stencil() { return &fCommon.fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646
647 /// @}
648
649 ///////////////////////////////////////////////////////////////////////////
650 // @name Edge AA
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000651 // Edge equations can be specified to perform anti-aliasing. Because the
bsalomon@google.com7ffe6812012-05-11 17:32:43 +0000652 // edges are specified as per-vertex data, vertices that are shared by
653 // multiple edges must be split.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 //
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000655 ////
656
657 /**
tomhudson@google.com93813632011-10-27 20:21:16 +0000658 * When specifying edges as vertex data this enum specifies what type of
bsalomon@google.com81712882012-11-01 17:12:34 +0000659 * edges are in use. The edges are always 4 SkScalars in memory, even when
tomhudson@google.com93813632011-10-27 20:21:16 +0000660 * the edge type requires fewer than 4.
bsalomon@google.com93c96602012-04-27 13:05:21 +0000661 *
662 * TODO: Fix the fact that HairLine and Circle edge types use y-down coords.
663 * (either adjust in VS or use origin_upper_left in GLSL)
tomhudson@google.com93813632011-10-27 20:21:16 +0000664 */
665 enum VertexEdgeType {
666 /* 1-pixel wide line
667 2D implicit line eq (a*x + b*y +c = 0). 4th component unused */
668 kHairLine_EdgeType,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000669 /* Quadratic specified by u^2-v canonical coords (only 2
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000670 components used). Coverage based on signed distance with negative
bsalomon@google.com93c96602012-04-27 13:05:21 +0000671 being inside, positive outside. Edge specified in window space
672 (y-down) */
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000673 kQuad_EdgeType,
674 /* Same as above but for hairline quadratics. Uses unsigned distance.
675 Coverage is min(0, 1-distance). */
676 kHairQuad_EdgeType,
bsalomon@google.com93c96602012-04-27 13:05:21 +0000677 /* Circle specified as center_x, center_y, outer_radius, inner_radius
678 all in window space (y-down). */
679 kCircle_EdgeType,
jvanverth@google.com46d3d392013-01-22 13:34:01 +0000680 /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
681 all in window space (y-down). */
682 kEllipse_EdgeType,
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000683
684 kVertexEdgeTypeCnt
tomhudson@google.com93813632011-10-27 20:21:16 +0000685 };
686
687 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000688 * Determines the interpretation per-vertex edge data when the
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000689 * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges
690 * are not specified the value of this setting has no effect.
691 */
692 void setVertexEdgeType(VertexEdgeType type) {
bsalomon@google.com69cc6ad2012-01-17 14:25:10 +0000693 GrAssert(type >=0 && type < kVertexEdgeTypeCnt);
bsalomon@google.comca432082013-01-23 19:53:46 +0000694 fCommon.fVertexEdgeType = type;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000695 }
696
bsalomon@google.comca432082013-01-23 19:53:46 +0000697 VertexEdgeType getVertexEdgeType() const { return fCommon.fVertexEdgeType; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000698
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000699 /// @}
tomhudson@google.com62b09682011-11-09 16:39:17 +0000700
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701 ///////////////////////////////////////////////////////////////////////////
702 /// @name State Flags
703 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000704
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000705 /**
706 * Flags that affect rendering. Controlled using enable/disableState(). All
707 * default to disabled.
708 */
709 enum StateBits {
710 /**
711 * Perform dithering. TODO: Re-evaluate whether we need this bit
712 */
713 kDither_StateBit = 0x01,
714 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000715 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
716 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
717 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000718 */
719 kHWAntialias_StateBit = 0x02,
720 /**
721 * Draws will respect the clip, otherwise the clip is ignored.
722 */
723 kClip_StateBit = 0x04,
724 /**
725 * Disables writing to the color buffer. Useful when performing stencil
726 * operations.
727 */
728 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000729
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000730 /**
731 * Usually coverage is applied after color blending. The color is blended using the coeffs
732 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
733 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
734 * this case there is no distinction between coverage and color and the caller needs direct
735 * control over the blend coeffs. When set, there will be a single blend step controlled by
736 * setBlendFunc() which will use coverage*color as the src color.
737 */
738 kCoverageDrawing_StateBit = 0x10,
739
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000740 // Users of the class may add additional bits to the vector
741 kDummyStateBit,
742 kLastPublicStateBit = kDummyStateBit-1,
743 };
744
745 void resetStateFlags() {
bsalomon@google.comca432082013-01-23 19:53:46 +0000746 fCommon.fFlagBits = 0;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000747 }
748
749 /**
750 * Enable render state settings.
751 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000752 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000753 */
754 void enableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000755 fCommon.fFlagBits |= stateBits;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000756 }
757
758 /**
759 * Disable render state settings.
760 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000761 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762 */
763 void disableState(uint32_t stateBits) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000764 fCommon.fFlagBits &= ~(stateBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000765 }
766
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000767 /**
768 * Enable or disable stateBits based on a boolean.
769 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000770 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000771 * @param enable if true enable stateBits, otherwise disable
772 */
773 void setState(uint32_t stateBits, bool enable) {
774 if (enable) {
775 this->enableState(stateBits);
776 } else {
777 this->disableState(stateBits);
778 }
779 }
780
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000781 bool isDitherState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000782 return 0 != (fCommon.fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000783 }
784
785 bool isHWAntialiasState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000786 return 0 != (fCommon.fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000787 }
788
789 bool isClipState() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000790 return 0 != (fCommon.fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791 }
792
793 bool isColorWriteDisabled() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000794 return 0 != (fCommon.fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000795 }
796
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000797 bool isCoverageDrawing() const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000798 return 0 != (fCommon.fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000799 }
800
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000801 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000802 return 0 != (stateBit & fCommon.fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000803 }
804
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000805 /// @}
806
807 ///////////////////////////////////////////////////////////////////////////
808 /// @name Face Culling
809 ////
810
811 enum DrawFace {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000812 kInvalid_DrawFace = -1,
813
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000814 kBoth_DrawFace,
815 kCCW_DrawFace,
816 kCW_DrawFace,
817 };
818
819 /**
820 * Controls whether clockwise, counterclockwise, or both faces are drawn.
821 * @param face the face(s) to draw.
822 */
823 void setDrawFace(DrawFace face) {
bsalomon@google.com978c8c62012-05-21 14:45:49 +0000824 GrAssert(kInvalid_DrawFace != face);
bsalomon@google.comca432082013-01-23 19:53:46 +0000825 fCommon.fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000826 }
827
828 /**
829 * Gets whether the target is drawing clockwise, counterclockwise,
830 * or both faces.
831 * @return the current draw face(s).
832 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000833 DrawFace getDrawFace() const { return fCommon.fDrawFace; }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000834
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000835 /// @}
836
837 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000838
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000839 bool isStageEnabled(int s) const {
840 GrAssert((unsigned)s < kNumStages);
bsalomon@google.com08283af2012-10-26 13:01:20 +0000841 return (NULL != fStages[s].getEffect());
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000842 }
843
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000844 // Most stages are usually not used, so conditionals here
845 // reduce the expected number of bytes touched by 50%.
846 bool operator ==(const GrDrawState& s) const {
bsalomon@google.comca432082013-01-23 19:53:46 +0000847 if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000848 return false;
849 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000850
851 for (int i = 0; i < kNumStages; i++) {
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000852 bool enabled = this->isStageEnabled(i);
853 if (enabled != s.isStageEnabled(i)) {
854 return false;
855 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000856 if (enabled && this->fStages[i] != s.fStages[i]) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000857 return false;
858 }
859 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000860 return true;
861 }
862 bool operator !=(const GrDrawState& s) const { return !(*this == s); }
863
bsalomon@google.comca432082013-01-23 19:53:46 +0000864 GrDrawState& operator= (const GrDrawState& s) {
865 this->setRenderTarget(s.fRenderTarget.get());
866 fCommon = s.fCommon;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000867 for (int i = 0; i < kNumStages; i++) {
tomhudson@google.come742bf02012-07-13 19:54:19 +0000868 if (s.isStageEnabled(i)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000869 this->fStages[i] = s.fStages[i];
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000870 }
871 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000872 return *this;
873 }
874
875private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000876
bsalomon@google.comca432082013-01-23 19:53:46 +0000877 /** Fields that are identical in GrDrawState and GrDrawState::DeferredState. */
878 struct CommonState {
879 // These fields are roughly sorted by decreasing likelihood of being different in op==
880 GrColor fColor;
881 SkMatrix fViewMatrix;
882 GrBlendCoeff fSrcBlend;
883 GrBlendCoeff fDstBlend;
884 GrColor fBlendConstant;
885 uint32_t fFlagBits;
886 VertexEdgeType fVertexEdgeType;
887 GrStencilSettings fStencilSettings;
888 int fFirstCoverageStage;
889 GrColor fCoverage;
890 SkXfermode::Mode fColorFilterMode;
891 GrColor fColorFilterColor;
892 DrawFace fDrawFace;
893 bool operator== (const CommonState& other) const {
894 return fColor == other.fColor &&
895 fViewMatrix.cheapEqualTo(other.fViewMatrix) &&
896 fSrcBlend == other.fSrcBlend &&
897 fDstBlend == other.fDstBlend &&
898 fBlendConstant == other.fBlendConstant &&
899 fFlagBits == other.fFlagBits &&
900 fVertexEdgeType == other.fVertexEdgeType &&
901 fStencilSettings == other.fStencilSettings &&
902 fFirstCoverageStage == other.fFirstCoverageStage &&
903 fCoverage == other.fCoverage &&
904 fColorFilterMode == other.fColorFilterMode &&
905 fColorFilterColor == other.fColorFilterColor &&
906 fDrawFace == other.fDrawFace;
907 }
908 bool operator!= (const CommonState& other) const { return !(*this == other); }
909 };
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000910
bsalomon@google.comca432082013-01-23 19:53:46 +0000911 /** GrDrawState uses GrEffectStages to hold stage state which holds a ref on GrEffectRef.
912 DeferredState must directly reference GrEffects, however. */
913 struct SavedEffectStage {
914 SavedEffectStage() : fEffect(NULL) {}
915 const GrEffect* fEffect;
916 GrEffectStage::SavedCoordChange fCoordChange;
917 };
918
919public:
920 /**
921 * DeferredState contains all of the data of a GrDrawState but does not hold refs on GrResource
922 * objects. Resources are allowed to hit zero ref count while in DeferredStates. Their internal
923 * dispose mechanism returns them to the cache. This allows recycling resources through the
924 * the cache while they are in a deferred draw queue.
925 */
926 class DeferredState {
927 public:
928 DeferredState() : fRenderTarget(NULL) {
929 GR_DEBUGCODE(fInitialized = false;)
930 }
931 // TODO: Remove this when DeferredState no longer holds a ref to the RT
932 ~DeferredState() { SkSafeUnref(fRenderTarget); }
933
934 void saveFrom(const GrDrawState& drawState) {
935 fCommon = drawState.fCommon;
936 // TODO: Here we will copy the GrRenderTarget pointer without taking a ref.
937 fRenderTarget = drawState.fRenderTarget.get();
938 SkSafeRef(fRenderTarget);
939 // Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
940 // ref gets fully unref'ed it will cause the underlying effect to unref its resources
941 // and recycle them to the cache (if no one else is holding a ref to the resources).
942 for (int i = 0; i < kNumStages; ++i) {
943 fStages[i].saveFrom(drawState.fStages[i]);
944 }
945 GR_DEBUGCODE(fInitialized = true;)
946 }
947
948 void restoreTo(GrDrawState* drawState) {
949 GrAssert(fInitialized);
950 drawState->fCommon = fCommon;
951 drawState->setRenderTarget(fRenderTarget);
952 for (int i = 0; i < kNumStages; ++i) {
953 fStages[i].restoreTo(&drawState->fStages[i]);
954 }
955 }
956
957 bool isEqual(const GrDrawState& state) const {
958 if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
959 return false;
960 }
961 for (int i = 0; i < kNumStages; ++i) {
bsalomon@google.comdcd69bf2013-01-24 18:28:51 +0000962 if (!fStages[i].isEqual(state.fStages[i])) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000963 return false;
964 }
965 }
966 return true;
967 }
968
969 private:
970 GrRenderTarget* fRenderTarget;
971 CommonState fCommon;
972 GrEffectStage::DeferredStage fStages[kNumStages];
973
974 GR_DEBUGCODE(bool fInitialized;)
975 };
976
977private:
978 SkAutoTUnref<GrRenderTarget> fRenderTarget;
979 CommonState fCommon;
980 GrEffectStage fStages[kNumStages];
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000981
reed@google.comfa35e3d2012-06-26 20:16:17 +0000982 typedef GrRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000983};
984
985#endif