blob: 90bdc64507dc544356d9cb2d8860f1fe8142a953 [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"
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +000012#include "GrBlend.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000013#include "GrColor.h"
bsalomon@google.com08283af2012-10-26 13:01:20 +000014#include "GrEffectStage.h"
bsalomon@google.com73818dc2013-03-28 13:23:29 +000015#include "GrPaint.h"
robertphillips@google.com9ec07532012-06-22 12:01:30 +000016#include "GrRenderTarget.h"
jvanverth@google.comcc782382013-01-28 20:39:48 +000017#include "GrStencil.h"
18#include "GrTemplates.h"
19#include "GrTexture.h"
bsalomon@google.com31ec7982013-03-27 18:14:57 +000020#include "GrTypesPriv.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000021#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000022
jvanverth@google.comcc782382013-01-28 20:39:48 +000023#include "SkMatrix.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000024#include "SkTypes.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000025#include "SkXfermode.h"
26
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +000027class GrDrawState : public SkRefCnt {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000028public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000029 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000030
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000031 GrDrawState() {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000032 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000033 this->reset();
34 }
tomhudson@google.com93813632011-10-27 20:21:16 +000035
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000036 GrDrawState(const SkMatrix& initialViewMatrix) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000037 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000038 this->reset(initialViewMatrix);
39 }
bsalomon@google.com137f1342013-05-29 21:27:53 +000040
41 /**
42 * Copies another draw state.
43 **/
commit-bot@chromium.orgfaa5ae42013-07-23 11:13:56 +000044 GrDrawState(const GrDrawState& state) : INHERITED() {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000045 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000046 *this = state;
47 }
48
bsalomon@google.com137f1342013-05-29 21:27:53 +000049 /**
50 * Copies another draw state with a preconcat to the view matrix.
51 **/
52 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000053 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com137f1342013-05-29 21:27:53 +000054 *this = state;
55 if (!preConcatMatrix.isIdentity()) {
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000056 for (int i = 0; i < fColorStages.count(); ++i) {
57 fColorStages[i].localCoordChange(preConcatMatrix);
58 }
59 for (int i = 0; i < fCoverageStages.count(); ++i) {
60 fCoverageStages[i].localCoordChange(preConcatMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +000061 }
egdaniel9514d242014-07-18 06:15:43 -070062 this->invalidateBlendOptFlags();
bsalomon@google.com137f1342013-05-29 21:27:53 +000063 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000064 }
65
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000066 virtual ~GrDrawState() { SkASSERT(0 == fBlockEffectRemovalCnt); }
bsalomon@google.com137f1342013-05-29 21:27:53 +000067
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000068 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +000069 * Resets to the default state. GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000070 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000071 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000072
bsalomon@google.com137f1342013-05-29 21:27:53 +000073 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000074
75 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000076 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
77 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000078 * equivalents are set to default values. Clipping will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000079 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000080 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000081
82 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +000083 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +000084 ////
85
jvanverth@google.com9b855c72013-03-01 18:21:22 +000086 enum {
jvanverth@google.com054ae992013-04-01 20:06:51 +000087 kMaxVertexAttribCnt = kLast_GrVertexAttribBinding + 4,
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000088 };
89
jvanverth@google.com9b855c72013-03-01 18:21:22 +000090 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +000091 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
92 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
93 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000094 *
jvanverth@google.com054ae992013-04-01 20:06:51 +000095 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
96 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000097 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000098
jvanverth@google.com9b855c72013-03-01 18:21:22 +000099 /**
robertphillips@google.com42903302013-04-20 12:26:07 +0000100 * Sets vertex attributes for next draw. The object driving the templatization
101 * should be a global GrVertexAttrib array that is never changed.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000102 */
robertphillips@google.com42903302013-04-20 12:26:07 +0000103 template <const GrVertexAttrib A[]> void setVertexAttribs(int count) {
104 this->setVertexAttribs(A, count);
105 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +0000106
bsalomon2ed5ef82014-07-07 08:44:05 -0700107 const GrVertexAttrib* getVertexAttribs() const { return fVAPtr; }
108 int getVertexAttribCount() const { return fVACount; }
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000109
110 size_t getVertexSize() const;
111
112 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000113 * Sets default vertex attributes for next draw. The default is a single attribute:
114 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000115 */
116 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000117
jvanverth@google.com054ae992013-04-01 20:06:51 +0000118 /**
119 * Getters for index into getVertexAttribs() for particular bindings. -1 is returned if the
120 * binding does not appear in the current attribs. These bindings should appear only once in
121 * the attrib array.
122 */
123
124 int positionAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700125 return fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000126 }
127 int localCoordAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700128 return fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000129 }
130 int colorVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700131 return fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000132 }
133 int coverageVertexAttributeIndex() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700134 return fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000135 }
136
137 bool hasLocalCoordAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700138 return -1 != fFixedFunctionVertexAttribIndices[kLocalCoord_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000139 }
140 bool hasColorVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700141 return -1 != fFixedFunctionVertexAttribIndices[kColor_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000142 }
143 bool hasCoverageVertexAttribute() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700144 return -1 != fFixedFunctionVertexAttribIndices[kCoverage_GrVertexAttribBinding];
jvanverth@google.com054ae992013-04-01 20:06:51 +0000145 }
146
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000147 bool validateVertexAttribs() const;
148
jvanverth@google.comcc782382013-01-28 20:39:48 +0000149 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000150 * Helper to save/restore vertex attribs
151 */
152 class AutoVertexAttribRestore {
153 public:
154 AutoVertexAttribRestore(GrDrawState* drawState) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000155 SkASSERT(NULL != drawState);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000156 fDrawState = drawState;
bsalomon2ed5ef82014-07-07 08:44:05 -0700157 fVAPtr = drawState->fVAPtr;
158 fVACount = drawState->fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000159 fDrawState->setDefaultVertexAttribs();
160 }
161
162 ~AutoVertexAttribRestore(){
commit-bot@chromium.orgfe070ba2013-10-16 14:43:12 +0000163 fDrawState->setVertexAttribs(fVAPtr, fVACount);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000164 }
165
166 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000167 GrDrawState* fDrawState;
168 const GrVertexAttrib* fVAPtr;
169 int fVACount;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000170 };
171
172 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000173 * Accessing positions, local coords, or colors, of a vertex within an array is a hassle
174 * involving casts and simple math. These helpers exist to keep GrDrawTarget clients' code a bit
175 * nicer looking.
jvanverth@google.comcc782382013-01-28 20:39:48 +0000176 */
177
178 /**
179 * Gets a pointer to a GrPoint of a vertex's position or texture
180 * coordinate.
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000181 * @param vertices the vertex array
jvanverth@google.comcc782382013-01-28 20:39:48 +0000182 * @param vertexIndex the index of the vertex in the array
183 * @param vertexSize the size of each vertex in the array
184 * @param offset the offset in bytes of the vertex component.
185 * Defaults to zero (corresponding to vertex position)
186 * @return pointer to the vertex component as a GrPoint
187 */
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000188 static SkPoint* GetVertexPoint(void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000189 int vertexIndex,
190 int vertexSize,
191 int offset = 0) {
192 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000193 return GrTCast<SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000194 vertexIndex * vertexSize);
195 }
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000196 static const SkPoint* GetVertexPoint(const void* vertices,
jvanverth@google.comcc782382013-01-28 20:39:48 +0000197 int vertexIndex,
198 int vertexSize,
199 int offset = 0) {
200 intptr_t start = GrTCast<intptr_t>(vertices);
commit-bot@chromium.org972f9cd2014-03-28 17:58:28 +0000201 return GrTCast<const SkPoint*>(start + offset +
jvanverth@google.comcc782382013-01-28 20:39:48 +0000202 vertexIndex * vertexSize);
203 }
204
205 /**
206 * Gets a pointer to a GrColor inside a vertex within a vertex array.
207 * @param vertices the vetex array
208 * @param vertexIndex the index of the vertex in the array
209 * @param vertexSize the size of each vertex in the array
210 * @param offset the offset in bytes of the vertex color
211 * @return pointer to the vertex component as a GrColor
212 */
213 static GrColor* GetVertexColor(void* vertices,
214 int vertexIndex,
215 int vertexSize,
216 int offset) {
217 intptr_t start = GrTCast<intptr_t>(vertices);
218 return GrTCast<GrColor*>(start + offset +
219 vertexIndex * vertexSize);
220 }
221 static const GrColor* GetVertexColor(const void* vertices,
222 int vertexIndex,
223 int vertexSize,
224 int offset) {
225 const intptr_t start = GrTCast<intptr_t>(vertices);
226 return GrTCast<const GrColor*>(start + offset +
227 vertexIndex * vertexSize);
228 }
229
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000230 /// @}
231
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000232 /**
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000233 * Determines whether src alpha is guaranteed to be one for all src pixels
234 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000235 bool srcAlphaWillBeOne() const;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000236
237 /**
238 * Determines whether the output coverage is guaranteed to be one for all pixels hit by a draw.
239 */
jvanverth@google.com054ae992013-04-01 20:06:51 +0000240 bool hasSolidCoverage() const;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000241
242 /// @}
243
244 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000245 /// @name Color
246 ////
247
248 /**
249 * Sets color for next draw to a premultiplied-alpha color.
250 *
251 * @param color the color to set.
252 */
egdaniel9514d242014-07-18 06:15:43 -0700253 void setColor(GrColor color) {
254 fColor = color;
255 this->invalidateBlendOptFlags();
256 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000257
bsalomon2ed5ef82014-07-07 08:44:05 -0700258 GrColor getColor() const { return fColor; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000259
260 /**
261 * Sets the color to be used for the next draw to be
262 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
263 *
264 * @param alpha The alpha value to set as the color.
265 */
266 void setAlpha(uint8_t a) {
267 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
268 }
269
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000270 /// @}
271
272 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000273 /// @name Coverage
274 ////
275
276 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000277 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000278 * initial value (after construction or reset()) is 0xff. The constant
279 * coverage is ignored when per-vertex coverage is provided.
280 */
281 void setCoverage(uint8_t coverage) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700282 fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
egdaniel9514d242014-07-18 06:15:43 -0700283 this->invalidateBlendOptFlags();
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000284 }
285
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000286 uint8_t getCoverage() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700287 return GrColorUnpackR(fCoverage);
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000288 }
289
commit-bot@chromium.orge0a868c2013-11-22 07:02:11 +0000290 GrColor getCoverageColor() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700291 return fCoverage;
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000292 }
293
294 /// @}
295
296 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000297 /// @name Effect Stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000298 /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
299 /// shader. Its inputs are the output from the previous stage as well as some variables
300 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
301 /// the fragment position, local coordinates).
302 ///
303 /// The stages are divided into two sets, color-computing and coverage-computing. The final
304 /// color stage produces the final pixel color. The coverage-computing stages function exactly
305 /// as the color-computing but the output of the final coverage stage is treated as a fractional
306 /// pixel coverage rather than as input to the src/dst color blend step.
307 ///
308 /// The input color to the first color-stage is either the constant color or interpolated
309 /// per-vertex colors. The input to the first coverage stage is either a constant coverage
310 /// (usually full-coverage) or interpolated per-vertex coverage.
311 ///
312 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
313 /// the color / coverage distinction.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000314 ////
315
bsalomon97b9ab72014-07-08 06:52:35 -0700316 const GrEffect* addColorEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000317 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000318 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
egdaniel9514d242014-07-18 06:15:43 -0700319 this->invalidateBlendOptFlags();
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000320 return effect;
321 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000322
bsalomon97b9ab72014-07-08 06:52:35 -0700323 const GrEffect* addCoverageEffect(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000324 SkASSERT(NULL != effect);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000325 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
egdaniel9514d242014-07-18 06:15:43 -0700326 this->invalidateBlendOptFlags();
bsalomon@google.comadc65362013-01-28 14:26:09 +0000327 return effect;
328 }
329
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000330 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000331 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000332 */
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000333 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700334 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000335 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000336
337 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700338 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000339 }
340
341 void addColorTextureEffect(GrTexture* texture,
342 const SkMatrix& matrix,
343 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700344 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000345 }
346
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000347 void addCoverageTextureEffect(GrTexture* texture,
348 const SkMatrix& matrix,
349 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700350 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000351 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000352
robertphillips@google.com972265d2012-06-13 18:49:30 +0000353 /**
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000354 * When this object is destroyed it will remove any effects from the draw state that were added
355 * after its constructor.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000356 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000357 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000358 public:
bsalomon@google.com2fad5a82013-06-13 19:47:23 +0000359 AutoRestoreEffects() : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000360
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000361 AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL), fColorEffectCnt(0), fCoverageEffectCnt(0) {
362 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000363 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000364
365 ~AutoRestoreEffects() { this->set(NULL); }
366
367 void set(GrDrawState* ds) {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000368 if (NULL != fDrawState) {
egdaniel9514d242014-07-18 06:15:43 -0700369 int m = fDrawState->fColorStages.count() - fColorEffectCnt;
370 SkASSERT(m >= 0);
371 fDrawState->fColorStages.pop_back_n(m);
372
373 int n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt;
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000374 SkASSERT(n >= 0);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000375 fDrawState->fCoverageStages.pop_back_n(n);
egdaniel9514d242014-07-18 06:15:43 -0700376 if (m + n > 0) {
377 fDrawState->invalidateBlendOptFlags();
378 }
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000379 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000380 }
381 fDrawState = ds;
382 if (NULL != ds) {
383 fColorEffectCnt = ds->fColorStages.count();
384 fCoverageEffectCnt = ds->fCoverageStages.count();
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000385 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
robertphillips@google.com972265d2012-06-13 18:49:30 +0000386 }
387 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000388
bsalomon8af05232014-06-03 06:34:58 -0700389 bool isSet() const { return NULL != fDrawState; }
390
robertphillips@google.com972265d2012-06-13 18:49:30 +0000391 private:
392 GrDrawState* fDrawState;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000393 int fColorEffectCnt;
394 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000395 };
396
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000397 int numColorStages() const { return fColorStages.count(); }
398 int numCoverageStages() const { return fCoverageStages.count(); }
399 int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000400
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000401 const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
402 const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000403
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000404 /**
405 * Checks whether any of the effects will read the dst pixel color.
406 */
bsalomon@google.comd09ab842013-05-15 17:30:26 +0000407 bool willEffectReadDstColor() const;
reed@google.com67e7cde2013-03-20 17:47:16 +0000408
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000409 /// @}
410
411 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000412 /// @name Blending
413 ////
414
415 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000416 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000417 *
418 * The blend function will be:
419 * D' = sat(S*srcCoef + D*dstCoef)
420 *
421 * where D is the existing destination color, S is the incoming source
422 * color, and D' is the new destination color that will be written. sat()
423 * is the saturation function.
424 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000425 * @param srcCoef coefficient applied to the src color.
426 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000427 */
428 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700429 fSrcBlend = srcCoeff;
430 fDstBlend = dstCoeff;
egdaniel9514d242014-07-18 06:15:43 -0700431 this->invalidateBlendOptFlags();
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000432 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000433 if (GrBlendCoeffRefsDst(dstCoeff)) {
434 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000435 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000436 if (GrBlendCoeffRefsSrc(srcCoeff)) {
437 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000438 }
439 #endif
440 }
441
bsalomon2ed5ef82014-07-07 08:44:05 -0700442 GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
443 GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000444
445 void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
446 GrBlendCoeff* dstBlendCoeff) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700447 *srcBlendCoeff = fSrcBlend;
448 *dstBlendCoeff = fDstBlend;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000449 }
450
451 /**
452 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000453 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000454 * kConstC_GrBlendCoeff
455 * kIConstC_GrBlendCoeff
456 * kConstA_GrBlendCoeff
457 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000458 *
459 * @param constant the constant to set
460 */
egdaniel9514d242014-07-18 06:15:43 -0700461 void setBlendConstant(GrColor constant) {
462 fBlendConstant = constant;
463 this->invalidateBlendOptFlags();
464 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000465
466 /**
467 * Retrieves the last value set by setBlendConstant()
468 * @return the blending constant value
469 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700470 GrColor getBlendConstant() const { return fBlendConstant; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000471
bsalomon@google.com2b446732013-02-12 16:47:41 +0000472 /**
473 * Determines whether multiplying the computed per-pixel color by the pixel's fractional
474 * coverage before the blend will give the correct final destination color. In general it
475 * will not as coverage is applied after blending.
476 */
477 bool canTweakAlphaForCoverage() const;
478
479 /**
480 * Optimizations for blending / coverage to that can be applied based on the current state.
481 */
482 enum BlendOptFlags {
483 /**
484 * No optimization
485 */
486 kNone_BlendOpt = 0,
487 /**
488 * Don't draw at all
489 */
490 kSkipDraw_BlendOptFlag = 0x1,
491 /**
bsalomon@google.com2b446732013-02-12 16:47:41 +0000492 * The coverage value does not have to be computed separately from alpha, the the output
493 * color can be the modulation of the two.
494 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700495 kCoverageAsAlpha_BlendOptFlag = 0x2,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000496 /**
497 * Instead of emitting a src color, emit coverage in the alpha channel and r,g,b are
498 * "don't cares".
499 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700500 kEmitCoverage_BlendOptFlag = 0x4,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000501 /**
502 * Emit transparent black instead of the src color, no need to compute coverage.
503 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700504 kEmitTransBlack_BlendOptFlag = 0x8,
egdaniel9514d242014-07-18 06:15:43 -0700505 /**
506 * Flag used to invalidate the cached BlendOptFlags, OptSrcCoeff, and OptDstCoeff cached by
507 * the get BlendOpts function.
508 */
egdaniel0f1a7c42014-07-30 13:18:32 -0700509 kInvalid_BlendOptFlag = 1 << 31,
bsalomon@google.com2b446732013-02-12 16:47:41 +0000510 };
511 GR_DECL_BITFIELD_OPS_FRIENDS(BlendOptFlags);
512
egdaniel9514d242014-07-18 06:15:43 -0700513 void invalidateBlendOptFlags() {
514 fBlendOptFlags = kInvalid_BlendOptFlag;
515 }
516
bsalomon@google.com2b446732013-02-12 16:47:41 +0000517 /**
egdaniel02cafcc2014-07-21 11:37:28 -0700518 * We don't use suplied vertex color attributes if our blend mode is EmitCoverage or
519 * EmitTransBlack
520 */
521 bool canIgnoreColorAttribute() const;
522
523 /**
bsalomon@google.com2b446732013-02-12 16:47:41 +0000524 * Determines what optimizations can be applied based on the blend. The coefficients may have
525 * to be tweaked in order for the optimization to work. srcCoeff and dstCoeff are optional
526 * params that receive the tweaked coefficients. Normally the function looks at the current
527 * state to see if coverage is enabled. By setting forceCoverage the caller can speculatively
528 * determine the blend optimizations that would be used if there was partial pixel coverage.
529 *
530 * Subclasses of GrDrawTarget that actually draw (as opposed to those that just buffer for
531 * playback) must call this function and respect the flags that replace the output color.
egdaniel9514d242014-07-18 06:15:43 -0700532 *
533 * If the cached BlendOptFlags does not have the invalidate bit set, then getBlendOpts will
534 * simply returned the cached flags and coefficients. Otherwise it will calculate the values.
bsalomon@google.com2b446732013-02-12 16:47:41 +0000535 */
536 BlendOptFlags getBlendOpts(bool forceCoverage = false,
537 GrBlendCoeff* srcCoeff = NULL,
538 GrBlendCoeff* dstCoeff = NULL) const;
539
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000540 /// @}
541
542 ///////////////////////////////////////////////////////////////////////////
543 /// @name View Matrix
544 ////
545
546 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000547 * Sets the view matrix to identity and updates any installed effects to compensate for the
548 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000549 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000550 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000551
552 /**
553 * Retrieves the current view matrix
554 * @return the current view matrix.
555 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700556 const SkMatrix& getViewMatrix() const { return fViewMatrix; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000557
558 /**
559 * Retrieves the inverse of the current view matrix.
560 *
561 * If the current view matrix is invertible, return true, and if matrix
562 * is non-null, copy the inverse into it. If the current view matrix is
563 * non-invertible, return false and ignore the matrix parameter.
564 *
565 * @param matrix if not null, will receive a copy of the current inverse.
566 */
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000567 bool getViewInverse(SkMatrix* matrix) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000568 // TODO: determine whether we really need to leave matrix unmodified
569 // at call sites when inversion fails.
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000570 SkMatrix inverse;
bsalomon2ed5ef82014-07-07 08:44:05 -0700571 if (fViewMatrix.invert(&inverse)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000572 if (matrix) {
573 *matrix = inverse;
574 }
575 return true;
576 }
577 return false;
578 }
579
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000580 ////////////////////////////////////////////////////////////////////////////
581
582 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000583 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000584 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000585 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000586 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000587 public:
588 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000589
bsalomon@google.comc7818882013-03-20 19:19:53 +0000590 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000591 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000592 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000593 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000594
595 ~AutoViewMatrixRestore() { this->restore(); }
596
bsalomon@google.coma8347462012-10-08 18:59:39 +0000597 /**
598 * Can be called prior to destructor to restore the original matrix.
599 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000600 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000601
bsalomon@google.comc7818882013-03-20 19:19:53 +0000602 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000603
bsalomon@google.com137f1342013-05-29 21:27:53 +0000604 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
605 is not invertible. */
606 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000607
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000608 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000609 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
610
611 GrDrawState* fDrawState;
612 SkMatrix fViewMatrix;
613 int fNumColorStages;
614 SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000615 };
616
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000617 /// @}
618
619 ///////////////////////////////////////////////////////////////////////////
620 /// @name Render Target
621 ////
622
623 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000624 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000625 *
626 * @param target The render target to set.
627 */
rmistry@google.comd6176b02012-08-23 18:14:13 +0000628 void setRenderTarget(GrRenderTarget* target) {
bsalomon@google.comca432082013-01-23 19:53:46 +0000629 fRenderTarget.reset(SkSafeRef(target));
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000630 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000631
632 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000633 * Retrieves the currently set render-target.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000634 *
635 * @return The currently set render target.
636 */
bsalomon@google.comca432082013-01-23 19:53:46 +0000637 const GrRenderTarget* getRenderTarget() const { return fRenderTarget.get(); }
638 GrRenderTarget* getRenderTarget() { return fRenderTarget.get(); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000639
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000640 class AutoRenderTargetRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000641 public:
bsalomon@google.comcadbcb82012-01-06 19:22:11 +0000642 AutoRenderTargetRestore() : fDrawState(NULL), fSavedTarget(NULL) {}
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000643 AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
644 fDrawState = NULL;
robertphillips@google.com7460b372012-04-25 16:54:51 +0000645 fSavedTarget = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000646 this->set(ds, newTarget);
647 }
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000648 ~AutoRenderTargetRestore() { this->restore(); }
649
650 void restore() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000651 if (NULL != fDrawState) {
652 fDrawState->setRenderTarget(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000653 fDrawState = NULL;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000654 }
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000655 SkSafeSetNull(fSavedTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000656 }
657
658 void set(GrDrawState* ds, GrRenderTarget* newTarget) {
659 this->restore();
660
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000661 if (NULL != ds) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000662 SkASSERT(NULL == fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000663 fSavedTarget = ds->getRenderTarget();
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000664 SkSafeRef(fSavedTarget);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000665 ds->setRenderTarget(newTarget);
robertphillips@google.com9ec07532012-06-22 12:01:30 +0000666 fDrawState = ds;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000667 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000668 }
669 private:
670 GrDrawState* fDrawState;
671 GrRenderTarget* fSavedTarget;
672 };
673
674 /// @}
675
676 ///////////////////////////////////////////////////////////////////////////
677 /// @name Stencil
678 ////
679
680 /**
681 * Sets the stencil settings to use for the next draw.
682 * Changing the clip has the side-effect of possibly zeroing
683 * out the client settable stencil bits. So multipass algorithms
684 * using stencil should not change the clip between passes.
685 * @param settings the stencil settings to use.
686 */
687 void setStencil(const GrStencilSettings& settings) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700688 fStencilSettings = settings;
egdaniel9514d242014-07-18 06:15:43 -0700689 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000690 }
691
692 /**
693 * Shortcut to disable stencil testing and ops.
694 */
695 void disableStencil() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700696 fStencilSettings.setDisabled();
egdaniel9514d242014-07-18 06:15:43 -0700697 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000698 }
699
bsalomon2ed5ef82014-07-07 08:44:05 -0700700 const GrStencilSettings& getStencil() const { return fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000701
bsalomon2ed5ef82014-07-07 08:44:05 -0700702 GrStencilSettings* stencil() { return &fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000703
704 /// @}
705
706 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000707 /// @name State Flags
708 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000709
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000710 /**
711 * Flags that affect rendering. Controlled using enable/disableState(). All
712 * default to disabled.
713 */
714 enum StateBits {
715 /**
716 * Perform dithering. TODO: Re-evaluate whether we need this bit
717 */
718 kDither_StateBit = 0x01,
719 /**
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000720 * Perform HW anti-aliasing. This means either HW FSAA, if supported by the render target,
721 * or smooth-line rendering if a line primitive is drawn and line smoothing is supported by
722 * the 3D API.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000723 */
724 kHWAntialias_StateBit = 0x02,
725 /**
726 * Draws will respect the clip, otherwise the clip is ignored.
727 */
728 kClip_StateBit = 0x04,
729 /**
730 * Disables writing to the color buffer. Useful when performing stencil
731 * operations.
732 */
733 kNoColorWrites_StateBit = 0x08,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000734
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000735 /**
736 * Usually coverage is applied after color blending. The color is blended using the coeffs
737 * specified by setBlendFunc(). The blended color is then combined with dst using coeffs
738 * of src_coverage, 1-src_coverage. Sometimes we are explicitly drawing a coverage mask. In
739 * this case there is no distinction between coverage and color and the caller needs direct
740 * control over the blend coeffs. When set, there will be a single blend step controlled by
741 * setBlendFunc() which will use coverage*color as the src color.
742 */
743 kCoverageDrawing_StateBit = 0x10,
744
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000745 // Users of the class may add additional bits to the vector
746 kDummyStateBit,
747 kLastPublicStateBit = kDummyStateBit-1,
748 };
749
750 void resetStateFlags() {
bsalomon2ed5ef82014-07-07 08:44:05 -0700751 fFlagBits = 0;
egdaniel9514d242014-07-18 06:15:43 -0700752 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000753 }
754
755 /**
756 * Enable render state settings.
757 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000758 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000759 */
760 void enableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700761 fFlagBits |= stateBits;
egdaniel9514d242014-07-18 06:15:43 -0700762 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000763 }
764
765 /**
766 * Disable render state settings.
767 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000768 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000769 */
770 void disableState(uint32_t stateBits) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700771 fFlagBits &= ~(stateBits);
egdaniel9514d242014-07-18 06:15:43 -0700772 this->invalidateBlendOptFlags();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000773 }
774
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000775 /**
776 * Enable or disable stateBits based on a boolean.
777 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000778 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000779 * @param enable if true enable stateBits, otherwise disable
780 */
781 void setState(uint32_t stateBits, bool enable) {
782 if (enable) {
783 this->enableState(stateBits);
784 } else {
785 this->disableState(stateBits);
786 }
787 }
788
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000789 bool isDitherState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700790 return 0 != (fFlagBits & kDither_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000791 }
792
793 bool isHWAntialiasState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700794 return 0 != (fFlagBits & kHWAntialias_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000795 }
796
797 bool isClipState() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700798 return 0 != (fFlagBits & kClip_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000799 }
800
801 bool isColorWriteDisabled() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700802 return 0 != (fFlagBits & kNoColorWrites_StateBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000803 }
804
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000805 bool isCoverageDrawing() const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700806 return 0 != (fFlagBits & kCoverageDrawing_StateBit);
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000807 }
808
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000809 bool isStateFlagEnabled(uint32_t stateBit) const {
bsalomon2ed5ef82014-07-07 08:44:05 -0700810 return 0 != (stateBit & fFlagBits);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000811 }
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) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000832 SkASSERT(kInvalid_DrawFace != face);
bsalomon2ed5ef82014-07-07 08:44:05 -0700833 fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000834 }
835
836 /**
837 * Gets whether the target is drawing clockwise, counterclockwise,
838 * or both faces.
839 * @return the current draw face(s).
840 */
bsalomon2ed5ef82014-07-07 08:44:05 -0700841 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
bsalomon838f62d2014-08-05 07:15:57 -0700847 /** Return type for CombineIfPossible. */
848 enum CombinedState {
849 /** The GrDrawStates cannot be combined. */
850 kIncompatible_CombinedState,
851 /** Either draw state can be used in place of the other. */
852 kAOrB_CombinedState,
853 /** Use the first draw state. */
854 kA_CombinedState,
855 /** Use the second draw state. */
856 kB_CombinedState,
857 };
858
859 /** This function determines whether the GrDrawStates used for two draws can be combined into
860 a single GrDrawState. This is used to avoid storing redundant GrDrawStates and to determine
861 if draws can be batched. The return value indicates whether combining is possible and, if
862 so, which of the two inputs should be used. */
863 static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b) {
bsalomon72336ed2014-08-05 07:35:56 -0700864 bool usingVertexColors = a.hasColorVertexAttribute();
865 if (!usingVertexColors && a.fColor != b.fColor) {
866 return kIncompatible_CombinedState;
867 }
868
bsalomon838f62d2014-08-05 07:15:57 -0700869 if (a.fRenderTarget.get() != b.fRenderTarget.get() ||
870 a.fColorStages.count() != b.fColorStages.count() ||
871 a.fCoverageStages.count() != b.fCoverageStages.count() ||
bsalomon838f62d2014-08-05 07:15:57 -0700872 !a.fViewMatrix.cheapEqualTo(b.fViewMatrix) ||
873 a.fSrcBlend != b.fSrcBlend ||
874 a.fDstBlend != b.fDstBlend ||
875 a.fBlendConstant != b.fBlendConstant ||
876 a.fFlagBits != b.fFlagBits ||
877 a.fVACount != b.fVACount ||
878 memcmp(a.fVAPtr, b.fVAPtr, a.fVACount * sizeof(GrVertexAttrib)) ||
879 a.fStencilSettings != b.fStencilSettings ||
bsalomon838f62d2014-08-05 07:15:57 -0700880 a.fDrawFace != b.fDrawFace) {
881 return kIncompatible_CombinedState;
bsalomon@google.com8fe84b52012-03-26 15:24:27 +0000882 }
bsalomon06736762014-08-04 10:56:39 -0700883
bsalomon72336ed2014-08-05 07:35:56 -0700884 bool usingVertexCoverage = a.hasCoverageVertexAttribute();
885 if (!usingVertexCoverage && a.fCoverage != b.fCoverage) {
886 return kIncompatible_CombinedState;
887 }
888
bsalomon838f62d2014-08-05 07:15:57 -0700889 bool explicitLocalCoords = a.hasLocalCoordAttribute();
890 for (int i = 0; i < a.fColorStages.count(); i++) {
891 if (!GrEffectStage::AreCompatible(a.fColorStages[i], b.fColorStages[i],
bsalomon06736762014-08-04 10:56:39 -0700892 explicitLocalCoords)) {
bsalomon838f62d2014-08-05 07:15:57 -0700893 return kIncompatible_CombinedState;
bsalomon@google.comf2f8fc32012-07-18 18:25:07 +0000894 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000895 }
bsalomon838f62d2014-08-05 07:15:57 -0700896 for (int i = 0; i < a.fCoverageStages.count(); i++) {
897 if (!GrEffectStage::AreCompatible(a.fCoverageStages[i], b.fCoverageStages[i],
bsalomon06736762014-08-04 10:56:39 -0700898 explicitLocalCoords)) {
bsalomon838f62d2014-08-05 07:15:57 -0700899 return kIncompatible_CombinedState;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000900 }
901 }
bsalomon838f62d2014-08-05 07:15:57 -0700902 SkASSERT(0 == memcmp(a.fFixedFunctionVertexAttribIndices,
903 b.fFixedFunctionVertexAttribIndices,
904 sizeof(a.fFixedFunctionVertexAttribIndices)));
905 return kAOrB_CombinedState;
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000906 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000907
bsalomon2ed5ef82014-07-07 08:44:05 -0700908 GrDrawState& operator= (const GrDrawState& that) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000909 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon2ed5ef82014-07-07 08:44:05 -0700910 this->setRenderTarget(that.fRenderTarget.get());
911 fColor = that.fColor;
912 fViewMatrix = that.fViewMatrix;
913 fSrcBlend = that.fSrcBlend;
914 fDstBlend = that.fDstBlend;
915 fBlendConstant = that.fBlendConstant;
916 fFlagBits = that.fFlagBits;
917 fVACount = that.fVACount;
918 fVAPtr = that.fVAPtr;
919 fStencilSettings = that.fStencilSettings;
920 fCoverage = that.fCoverage;
921 fDrawFace = that.fDrawFace;
922 fColorStages = that.fColorStages;
923 fCoverageStages = that.fCoverageStages;
egdaniel9514d242014-07-18 06:15:43 -0700924 fOptSrcBlend = that.fOptSrcBlend;
925 fOptDstBlend = that.fOptDstBlend;
926 fBlendOptFlags = that.fBlendOptFlags;
bsalomon2ed5ef82014-07-07 08:44:05 -0700927
928 memcpy(fFixedFunctionVertexAttribIndices,
929 that.fFixedFunctionVertexAttribIndices,
930 sizeof(fFixedFunctionVertexAttribIndices));
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000931 return *this;
932 }
933
934private:
bsalomon@google.com2e3d1442012-03-26 20:33:54 +0000935
bsalomon@google.com137f1342013-05-29 21:27:53 +0000936 void onReset(const SkMatrix* initialViewMatrix) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000937 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000938 fColorStages.reset();
939 fCoverageStages.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000940
941 fRenderTarget.reset(NULL);
942
943 this->setDefaultVertexAttribs();
944
bsalomon2ed5ef82014-07-07 08:44:05 -0700945 fColor = 0xffffffff;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000946 if (NULL == initialViewMatrix) {
bsalomon2ed5ef82014-07-07 08:44:05 -0700947 fViewMatrix.reset();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000948 } else {
bsalomon2ed5ef82014-07-07 08:44:05 -0700949 fViewMatrix = *initialViewMatrix;
bsalomon@google.com137f1342013-05-29 21:27:53 +0000950 }
bsalomon2ed5ef82014-07-07 08:44:05 -0700951 fSrcBlend = kOne_GrBlendCoeff;
952 fDstBlend = kZero_GrBlendCoeff;
953 fBlendConstant = 0x0;
954 fFlagBits = 0x0;
955 fStencilSettings.setDisabled();
956 fCoverage = 0xffffffff;
957 fDrawFace = kBoth_DrawFace;
egdaniel9514d242014-07-18 06:15:43 -0700958
959 this->invalidateBlendOptFlags();
bsalomon@google.com137f1342013-05-29 21:27:53 +0000960 }
961
egdaniel9514d242014-07-18 06:15:43 -0700962 BlendOptFlags calcBlendOpts(bool forceCoverage = false,
963 GrBlendCoeff* srcCoeff = NULL,
964 GrBlendCoeff* dstCoeff = NULL) const;
jvanverth@google.com054ae992013-04-01 20:06:51 +0000965
bsalomon2ed5ef82014-07-07 08:44:05 -0700966 // These fields are roughly sorted by decreasing likelihood of being different in op==
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000967 SkAutoTUnref<GrRenderTarget> fRenderTarget;
bsalomon2ed5ef82014-07-07 08:44:05 -0700968 GrColor fColor;
969 SkMatrix fViewMatrix;
970 GrBlendCoeff fSrcBlend;
971 GrBlendCoeff fDstBlend;
972 GrColor fBlendConstant;
973 uint32_t fFlagBits;
974 const GrVertexAttrib* fVAPtr;
975 int fVACount;
976 GrStencilSettings fStencilSettings;
977 GrColor fCoverage;
978 DrawFace fDrawFace;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000979
980 typedef SkSTArray<4, GrEffectStage> EffectStageArray;
981 EffectStageArray fColorStages;
982 EffectStageArray fCoverageStages;
egdaniel9514d242014-07-18 06:15:43 -0700983
984 mutable GrBlendCoeff fOptSrcBlend;
985 mutable GrBlendCoeff fOptDstBlend;
986 mutable BlendOptFlags fBlendOptFlags;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000987
bsalomon2ed5ef82014-07-07 08:44:05 -0700988 // This is simply a different representation of info in fVertexAttribs and thus does
989 // not need to be compared in op==.
990 int fFixedFunctionVertexAttribIndices[kGrFixedFunctionVertexAttribBindingCnt];
991
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000992 // Some of the auto restore objects assume that no effects are removed during their lifetime.
993 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000994 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000995
robertphillips@google.com42903302013-04-20 12:26:07 +0000996 /**
997 * Sets vertex attributes for next draw.
998 *
999 * @param attribs the array of vertex attributes to set.
1000 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
1001 */
1002 void setVertexAttribs(const GrVertexAttrib attribs[], int count);
1003
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +00001004 typedef SkRefCnt INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +00001005};
1006
bsalomon@google.com2b446732013-02-12 16:47:41 +00001007GR_MAKE_BITFIELD_OPS(GrDrawState::BlendOptFlags);
1008
tomhudson@google.com93813632011-10-27 20:21:16 +00001009#endif