blob: 6a1e38056bbcad8da3a29498cf3b5f1d0f0ac85b [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
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +000011#include "GrBlend.h"
egdaniel3658f382014-09-15 07:01:59 -070012#include "GrOptDrawState.h"
bsalomon2a9ca782014-09-05 14:27:43 -070013#include "GrProgramResource.h"
14#include "GrRODrawState.h"
bsalomon@google.com68b58c92013-01-17 16:50:08 +000015#include "effects/GrSimpleTextureEffect.h"
tomhudson@google.com93813632011-10-27 20:21:16 +000016
egdaniel21aed572014-08-26 12:24:06 -070017/**
18 * Modifiable subclass derived from GrRODrawState. The majority of the data that represents a draw
19 * state is stored in the parent class. GrDrawState contains methods for setting, adding to, etc.
20 * various data members of the draw state. This class is used to configure the state used when
21 * issuing draws via GrDrawTarget.
22 */
23class GrDrawState : public GrRODrawState {
bsalomon@google.com2e3d1442012-03-26 20:33:54 +000024public:
reed@google.comfa35e3d2012-06-26 20:16:17 +000025 SK_DECLARE_INST_COUNT(GrDrawState)
rmistry@google.comd6176b02012-08-23 18:14:13 +000026
egdaniel3658f382014-09-15 07:01:59 -070027 GrDrawState() : fCachedOptState(NULL) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000028 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000029 this->reset();
30 }
tomhudson@google.com93813632011-10-27 20:21:16 +000031
egdaniel3658f382014-09-15 07:01:59 -070032 GrDrawState(const SkMatrix& initialViewMatrix) : fCachedOptState(NULL) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000033 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.comeb6879f2013-06-13 19:34:18 +000034 this->reset(initialViewMatrix);
35 }
bsalomon@google.com137f1342013-05-29 21:27:53 +000036
37 /**
38 * Copies another draw state.
39 **/
egdaniel3658f382014-09-15 07:01:59 -070040 GrDrawState(const GrDrawState& state) : INHERITED(), fCachedOptState(NULL) {
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000041 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
bsalomon@google.com46f7afb2012-01-18 19:51:55 +000042 *this = state;
43 }
44
bsalomon@google.com137f1342013-05-29 21:27:53 +000045 /**
46 * Copies another draw state with a preconcat to the view matrix.
47 **/
bsalomon8f727332014-08-05 07:50:06 -070048 GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix);
robertphillips@google.com9ec07532012-06-22 12:01:30 +000049
egdaniel3658f382014-09-15 07:01:59 -070050 virtual ~GrDrawState() {
51 SkSafeUnref(fCachedOptState);
52 SkASSERT(0 == fBlockEffectRemovalCnt);
53 }
bsalomon@google.com137f1342013-05-29 21:27:53 +000054
bsalomon@google.com52a5dcb2012-01-17 16:01:37 +000055 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +000056 * Resets to the default state. GrEffects will be removed from all stages.
rmistry@google.comd6176b02012-08-23 18:14:13 +000057 */
bsalomon@google.com137f1342013-05-29 21:27:53 +000058 void reset() { this->onReset(NULL); }
robertphillips@google.com9ec07532012-06-22 12:01:30 +000059
bsalomon@google.com137f1342013-05-29 21:27:53 +000060 void reset(const SkMatrix& initialViewMatrix) { this->onReset(&initialViewMatrix); }
bsalomon@google.comaf84e742012-10-05 13:23:24 +000061
62 /**
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000063 * Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
64 * GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
bsalomon9c0822a2014-08-11 11:07:48 -070065 * equivalents are set to default values with the exception of vertex attribute state which
66 * is unmodified by this function and clipping which will be enabled.
bsalomon@google.comaf84e742012-10-05 13:23:24 +000067 */
commit-bot@chromium.orgbb6a3172013-05-28 17:25:49 +000068 void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000069
70 ///////////////////////////////////////////////////////////////////////////
jvanverth@google.com9b855c72013-03-01 18:21:22 +000071 /// @name Vertex Attributes
jvanverth@google.comcc782382013-01-28 20:39:48 +000072 ////
73
jvanverth@google.com9b855c72013-03-01 18:21:22 +000074 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +000075 * The format of vertices is represented as an array of GrVertexAttribs, with each representing
76 * the type of the attribute, its offset, and semantic binding (see GrVertexAttrib in
77 * GrTypesPriv.h).
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000078 *
jvanverth@google.com054ae992013-04-01 20:06:51 +000079 * The mapping of attributes with kEffect bindings to GrEffect inputs is specified when
80 * setEffect is called.
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000081 */
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000082
jvanverth@google.com9b855c72013-03-01 18:21:22 +000083 /**
robertphillips@google.com42903302013-04-20 12:26:07 +000084 * Sets vertex attributes for next draw. The object driving the templatization
85 * should be a global GrVertexAttrib array that is never changed.
egdaniel7b3d5ee2014-08-28 05:41:14 -070086 *
87 * @param count the number of attributes being set, limited to kMaxVertexAttribCnt.
88 * @param stride the number of bytes between successive vertex data.
jvanverth@google.com9b855c72013-03-01 18:21:22 +000089 */
egdaniel7b3d5ee2014-08-28 05:41:14 -070090 template <const GrVertexAttrib A[]> void setVertexAttribs(int count, size_t stride) {
91 this->internalSetVertexAttribs(A, count, stride);
robertphillips@google.com42903302013-04-20 12:26:07 +000092 }
jvanverth@google.comb8b705b2013-02-28 16:28:34 +000093
jvanverth@google.com9b855c72013-03-01 18:21:22 +000094 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +000095 * Sets default vertex attributes for next draw. The default is a single attribute:
96 * {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribType}
jvanverth@google.com9b855c72013-03-01 18:21:22 +000097 */
98 void setDefaultVertexAttribs();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +000099
jvanverth@google.com054ae992013-04-01 20:06:51 +0000100 /**
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000101 * Helper to save/restore vertex attribs
102 */
103 class AutoVertexAttribRestore {
104 public:
bsalomon8f727332014-08-05 07:50:06 -0700105 AutoVertexAttribRestore(GrDrawState* drawState);
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000106
egdaniel3658f382014-09-15 07:01:59 -0700107 ~AutoVertexAttribRestore() { fDrawState->internalSetVertexAttribs(fVAPtr, fVACount,
108 fVAStride); }
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000109
110 private:
robertphillips@google.com42903302013-04-20 12:26:07 +0000111 GrDrawState* fDrawState;
112 const GrVertexAttrib* fVAPtr;
113 int fVACount;
egdaniel7b3d5ee2014-08-28 05:41:14 -0700114 size_t fVAStride;
bsalomon@google.com0406b9e2013-04-02 21:00:15 +0000115 };
116
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000117 /// @}
118
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000119 /**
bsalomon62c447d2014-08-08 08:08:50 -0700120 * Depending on features available in the underlying 3D API and the color blend mode requested
121 * it may or may not be possible to correctly blend with fractional pixel coverage generated by
122 * the fragment shader.
123 *
124 * This function considers the current draw state and the draw target's capabilities to
125 * determine whether coverage can be handled correctly. This function assumes that the caller
126 * intends to specify fractional pixel coverage (via setCoverage(), through a coverage vertex
127 * attribute, or a coverage effect) but may not have specified it yet.
128 */
129 bool couldApplyCoverage(const GrDrawTargetCaps& caps) const;
130
jvanverth@google.comcc782382013-01-28 20:39:48 +0000131 /// @}
132
133 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000134 /// @name Color
135 ////
136
137 /**
138 * Sets color for next draw to a premultiplied-alpha color.
139 *
140 * @param color the color to set.
141 */
egdaniel9514d242014-07-18 06:15:43 -0700142 void setColor(GrColor color) {
egdaniel3658f382014-09-15 07:01:59 -0700143 if (color != fColor) {
144 fColor = color;
145 this->invalidateOptState();
146 }
egdaniel9514d242014-07-18 06:15:43 -0700147 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000148
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000149 /**
150 * Sets the color to be used for the next draw to be
151 * (r,g,b,a) = (alpha, alpha, alpha, alpha).
152 *
153 * @param alpha The alpha value to set as the color.
154 */
bsalomon62c447d2014-08-08 08:08:50 -0700155 void setAlpha(uint8_t a) { this->setColor((a << 24) | (a << 16) | (a << 8) | a); }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000156
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000157 /// @}
158
159 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000160 /// @name Coverage
161 ////
162
163 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 * Sets a constant fractional coverage to be applied to the draw. The
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000165 * initial value (after construction or reset()) is 0xff. The constant
166 * coverage is ignored when per-vertex coverage is provided.
167 */
168 void setCoverage(uint8_t coverage) {
egdaniel3658f382014-09-15 07:01:59 -0700169 if (coverage != fCoverage) {
170 fCoverage = coverage;
171 this->invalidateOptState();
172 }
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000173 }
174
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000175 /// @}
176
joshualittbd769d02014-09-04 08:56:46 -0700177 /**
178 * The geometry processor is the sole element of the skia pipeline which can use the vertex,
179 * geometry, and tesselation shaders. The GP may also compute a coverage in its fragment shader
180 * but is never put in the color processing pipeline.
181 */
182
joshualitt249af152014-09-15 11:41:13 -0700183 const GrEffect* setGeometryProcessor(const GrEffect* effect) {
bsalomon49f085d2014-09-05 13:34:00 -0700184 SkASSERT(effect);
joshualitt249af152014-09-15 11:41:13 -0700185 SkASSERT(effect->requiresVertexShader());
joshualittbd769d02014-09-04 08:56:46 -0700186 SkASSERT(!this->hasGeometryProcessor());
joshualitt249af152014-09-15 11:41:13 -0700187 fGeometryProcessor.reset(new GrEffectStage(effect));
egdaniel3658f382014-09-15 07:01:59 -0700188 this->invalidateOptState();
joshualittbd769d02014-09-04 08:56:46 -0700189 return effect;
190 }
191
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000192 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.comadc65362013-01-28 14:26:09 +0000193 /// @name Effect Stages
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000194 /// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
195 /// shader. Its inputs are the output from the previous stage as well as some variables
196 /// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
197 /// the fragment position, local coordinates).
198 ///
199 /// The stages are divided into two sets, color-computing and coverage-computing. The final
200 /// color stage produces the final pixel color. The coverage-computing stages function exactly
201 /// as the color-computing but the output of the final coverage stage is treated as a fractional
202 /// pixel coverage rather than as input to the src/dst color blend step.
203 ///
204 /// The input color to the first color-stage is either the constant color or interpolated
205 /// per-vertex colors. The input to the first coverage stage is either a constant coverage
206 /// (usually full-coverage) or interpolated per-vertex coverage.
207 ///
208 /// See the documentation of kCoverageDrawing_StateBit for information about disabling the
209 /// the color / coverage distinction.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000210 ////
211
joshualitt249af152014-09-15 11:41:13 -0700212 const GrEffect* addColorEffect(const GrEffect* effect) {
bsalomon49f085d2014-09-05 13:34:00 -0700213 SkASSERT(effect);
joshualitt249af152014-09-15 11:41:13 -0700214 SkASSERT(!effect->requiresVertexShader());
215 SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect));
egdaniel3658f382014-09-15 07:01:59 -0700216 this->invalidateOptState();
jvanverth@google.com65eb4d52013-03-19 18:51:02 +0000217 return effect;
218 }
skia.committer@gmail.com01c34ee2013-03-20 07:01:02 +0000219
joshualitt249af152014-09-15 11:41:13 -0700220 const GrEffect* addCoverageEffect(const GrEffect* effect) {
bsalomon49f085d2014-09-05 13:34:00 -0700221 SkASSERT(effect);
joshualitt249af152014-09-15 11:41:13 -0700222 SkASSERT(!effect->requiresVertexShader());
223 SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect));
egdaniel3658f382014-09-15 07:01:59 -0700224 this->invalidateOptState();
bsalomon@google.comadc65362013-01-28 14:26:09 +0000225 return effect;
226 }
227
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000228 /**
bsalomon@google.comc7818882013-03-20 19:19:53 +0000229 * Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
tomhudson@google.com1e8f0162012-07-20 16:25:18 +0000230 */
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000231 void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700232 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comdfdb7e52012-10-16 15:19:45 +0000233 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000234
235 void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
bsalomon97b9ab72014-07-08 06:52:35 -0700236 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix))->unref();
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000237 }
238
239 void addColorTextureEffect(GrTexture* texture,
240 const SkMatrix& matrix,
241 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700242 this->addColorEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
bsalomon@google.com1ce49fc2012-09-18 14:14:49 +0000243 }
244
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000245 void addCoverageTextureEffect(GrTexture* texture,
246 const SkMatrix& matrix,
247 const GrTextureParams& params) {
bsalomon97b9ab72014-07-08 06:52:35 -0700248 this->addCoverageEffect(GrSimpleTextureEffect::Create(texture, matrix, params))->unref();
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000249 }
tomhudson@google.com676e6602012-07-10 17:21:48 +0000250
robertphillips@google.com972265d2012-06-13 18:49:30 +0000251 /**
bsalomon9b536522014-09-05 09:18:51 -0700252 * When this object is destroyed it will remove any color/coverage effects from the draw state
253 * that were added after its constructor.
254 *
255 * This class has strange behavior around geometry processor. If there is a GP on the draw state
256 * it will assert that the GP is not modified until after the destructor of the ARE. If the
257 * draw state has a NULL GP when the ARE is constructed then it will reset it to null in the
258 * destructor.
259 *
260 * TODO: We'd prefer for the ARE to just save and restore the GP. However, this would add
261 * significant complexity to the multi-ref architecture for deferred drawing. Once GrDrawState
262 * and GrOptDrawState are fully separated then GrDrawState will never be in the deferred
263 * execution state and GrOptDrawState always will be (and will be immutable and therefore
264 * unable to have an ARE). At this point we can restore sanity and have the ARE save and restore
265 * the GP.
robertphillips@google.com972265d2012-06-13 18:49:30 +0000266 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000267 class AutoRestoreEffects : public ::SkNoncopyable {
robertphillips@google.com972265d2012-06-13 18:49:30 +0000268 public:
bsalomon9b536522014-09-05 09:18:51 -0700269 AutoRestoreEffects()
270 : fDrawState(NULL)
bsalomon52e9d632014-09-05 12:23:12 -0700271 , fOriginalGPID(SK_InvalidUniqueID)
bsalomon9b536522014-09-05 09:18:51 -0700272 , fColorEffectCnt(0)
273 , fCoverageEffectCnt(0) {}
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000274
bsalomon9b536522014-09-05 09:18:51 -0700275 AutoRestoreEffects(GrDrawState* ds)
276 : fDrawState(NULL)
bsalomon52e9d632014-09-05 12:23:12 -0700277 , fOriginalGPID(SK_InvalidUniqueID)
bsalomon9b536522014-09-05 09:18:51 -0700278 , fColorEffectCnt(0)
279 , fCoverageEffectCnt(0) {
skia.committer@gmail.com5c493d52013-06-14 07:00:49 +0000280 this->set(ds);
robertphillips@google.comf09b87d2013-06-13 20:06:44 +0000281 }
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000282
283 ~AutoRestoreEffects() { this->set(NULL); }
284
bsalomon8f727332014-08-05 07:50:06 -0700285 void set(GrDrawState* ds);
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000286
bsalomon49f085d2014-09-05 13:34:00 -0700287 bool isSet() const { return SkToBool(fDrawState); }
bsalomon8af05232014-06-03 06:34:58 -0700288
robertphillips@google.com972265d2012-06-13 18:49:30 +0000289 private:
bsalomon9b536522014-09-05 09:18:51 -0700290 GrDrawState* fDrawState;
bsalomon52e9d632014-09-05 12:23:12 -0700291 uint32_t fOriginalGPID;
bsalomon9b536522014-09-05 09:18:51 -0700292 int fColorEffectCnt;
293 int fCoverageEffectCnt;
robertphillips@google.com972265d2012-06-13 18:49:30 +0000294 };
295
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000296 /// @}
297
298 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000299 /// @name Blending
300 ////
301
302 /**
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000303 * Sets the blending function coefficients.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000304 *
305 * The blend function will be:
306 * D' = sat(S*srcCoef + D*dstCoef)
307 *
308 * where D is the existing destination color, S is the incoming source
309 * color, and D' is the new destination color that will be written. sat()
310 * is the saturation function.
311 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000312 * @param srcCoef coefficient applied to the src color.
313 * @param dstCoef coefficient applied to the dst color.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000314 */
315 void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
egdaniel3658f382014-09-15 07:01:59 -0700316 if (srcCoeff != fSrcBlend || dstCoeff != fDstBlend) {
317 fSrcBlend = srcCoeff;
318 fDstBlend = dstCoeff;
319 this->invalidateOptState();
320 }
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000321 #ifdef SK_DEBUG
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000322 if (GrBlendCoeffRefsDst(dstCoeff)) {
323 GrPrintf("Unexpected dst blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000324 }
commit-bot@chromium.org24ab3b02013-08-14 21:56:37 +0000325 if (GrBlendCoeffRefsSrc(srcCoeff)) {
326 GrPrintf("Unexpected src blend coeff. Won't work correctly with coverage stages.\n");
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000327 }
328 #endif
329 }
330
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000331 /**
332 * Sets the blending function constant referenced by the following blending
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000333 * coefficients:
bsalomon@google.com47059542012-06-06 20:51:20 +0000334 * kConstC_GrBlendCoeff
335 * kIConstC_GrBlendCoeff
336 * kConstA_GrBlendCoeff
337 * kIConstA_GrBlendCoeff
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000338 *
339 * @param constant the constant to set
340 */
egdaniel9514d242014-07-18 06:15:43 -0700341 void setBlendConstant(GrColor constant) {
egdaniel3658f382014-09-15 07:01:59 -0700342 if (constant != fBlendConstant) {
343 fBlendConstant = constant;
344 this->invalidateOptState();
345 }
egdaniel9514d242014-07-18 06:15:43 -0700346 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000347
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000348 /// @}
349
350 ///////////////////////////////////////////////////////////////////////////
351 /// @name View Matrix
352 ////
353
354 /**
bsalomon@google.com137f1342013-05-29 21:27:53 +0000355 * Sets the view matrix to identity and updates any installed effects to compensate for the
356 * coord system change.
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000357 */
bsalomon@google.com137f1342013-05-29 21:27:53 +0000358 bool setIdentityViewMatrix();
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000359
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000360 ////////////////////////////////////////////////////////////////////////////
361
362 /**
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000363 * Preconcats the current view matrix and restores the previous view matrix in the destructor.
bsalomon@google.com137f1342013-05-29 21:27:53 +0000364 * Effect matrices are automatically adjusted to compensate and adjusted back in the destructor.
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000365 */
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000366 class AutoViewMatrixRestore : public ::SkNoncopyable {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000367 public:
368 AutoViewMatrixRestore() : fDrawState(NULL) {}
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000369
bsalomon@google.comc7818882013-03-20 19:19:53 +0000370 AutoViewMatrixRestore(GrDrawState* ds, const SkMatrix& preconcatMatrix) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000371 fDrawState = NULL;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000372 this->set(ds, preconcatMatrix);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000373 }
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000374
375 ~AutoViewMatrixRestore() { this->restore(); }
376
bsalomon@google.coma8347462012-10-08 18:59:39 +0000377 /**
378 * Can be called prior to destructor to restore the original matrix.
379 */
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000380 void restore();
skia.committer@gmail.comf467ce72012-10-09 02:01:37 +0000381
bsalomon@google.comc7818882013-03-20 19:19:53 +0000382 void set(GrDrawState* drawState, const SkMatrix& preconcatMatrix);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000383
bsalomon@google.com137f1342013-05-29 21:27:53 +0000384 /** Sets the draw state's matrix to identity. This can fail because the current view matrix
385 is not invertible. */
386 bool setIdentity(GrDrawState* drawState);
bsalomon@google.com2fdcdeb2012-10-08 17:15:55 +0000387
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000388 private:
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000389 void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
390
391 GrDrawState* fDrawState;
392 SkMatrix fViewMatrix;
393 int fNumColorStages;
joshualittbd769d02014-09-04 08:56:46 -0700394 bool fHasGeometryProcessor;
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000395 SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
bsalomon@google.com5b3e8902012-10-05 20:13:28 +0000396 };
397
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000398 /// @}
399
400 ///////////////////////////////////////////////////////////////////////////
401 /// @name Render Target
402 ////
403
404 /**
bsalomon@google.comca432082013-01-23 19:53:46 +0000405 * Sets the render-target used at the next drawing call
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000406 *
407 * @param target The render target to set.
408 */
bsalomon2a9ca782014-09-05 14:27:43 -0700409 void setRenderTarget(GrRenderTarget* target) {
410 fRenderTarget.setResource(SkSafeRef(target), GrProgramResource::kWrite_IOType);
egdaniel3658f382014-09-15 07:01:59 -0700411 this->invalidateOptState();
bsalomon2a9ca782014-09-05 14:27:43 -0700412 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000413
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000414 /// @}
415
416 ///////////////////////////////////////////////////////////////////////////
417 /// @name Stencil
418 ////
419
420 /**
421 * Sets the stencil settings to use for the next draw.
422 * Changing the clip has the side-effect of possibly zeroing
423 * out the client settable stencil bits. So multipass algorithms
424 * using stencil should not change the clip between passes.
425 * @param settings the stencil settings to use.
426 */
427 void setStencil(const GrStencilSettings& settings) {
egdaniel3658f382014-09-15 07:01:59 -0700428 if (settings != fStencilSettings) {
429 fStencilSettings = settings;
430 this->invalidateOptState();
431 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000432 }
433
434 /**
435 * Shortcut to disable stencil testing and ops.
436 */
437 void disableStencil() {
egdaniel3658f382014-09-15 07:01:59 -0700438 if (!fStencilSettings.isDisabled()) {
439 fStencilSettings.setDisabled();
440 this->invalidateOptState();
441 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000442 }
443
bsalomon2ed5ef82014-07-07 08:44:05 -0700444 GrStencilSettings* stencil() { return &fStencilSettings; }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000445
446 /// @}
447
448 ///////////////////////////////////////////////////////////////////////////
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000449 /// @name State Flags
450 ////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000451
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000452 void resetStateFlags() {
egdaniel3658f382014-09-15 07:01:59 -0700453 if (0 != fFlagBits) {
454 fFlagBits = 0;
455 this->invalidateOptState();
456 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000457 }
458
459 /**
460 * Enable render state settings.
461 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000462 * @param stateBits bitfield of StateBits specifying the states to enable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000463 */
464 void enableState(uint32_t stateBits) {
egdaniel3658f382014-09-15 07:01:59 -0700465 if (stateBits & ~fFlagBits) {
466 fFlagBits |= stateBits;
467 this->invalidateOptState();
468 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000469 }
470
471 /**
472 * Disable render state settings.
473 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000474 * @param stateBits bitfield of StateBits specifying the states to disable
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000475 */
476 void disableState(uint32_t stateBits) {
egdaniel3658f382014-09-15 07:01:59 -0700477 if (stateBits & fFlagBits) {
478 fFlagBits &= ~(stateBits);
479 this->invalidateOptState();
480 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000481 }
482
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000483 /**
484 * Enable or disable stateBits based on a boolean.
485 *
bsalomon@google.com1e269b52012-10-15 14:25:31 +0000486 * @param stateBits bitfield of StateBits to enable or disable
bsalomon@google.comd5d69ff2012-10-04 19:42:00 +0000487 * @param enable if true enable stateBits, otherwise disable
488 */
489 void setState(uint32_t stateBits, bool enable) {
490 if (enable) {
491 this->enableState(stateBits);
492 } else {
493 this->disableState(stateBits);
494 }
495 }
496
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000497 /// @}
498
499 ///////////////////////////////////////////////////////////////////////////
500 /// @name Face Culling
501 ////
502
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000503 /**
504 * Controls whether clockwise, counterclockwise, or both faces are drawn.
505 * @param face the face(s) to draw.
506 */
507 void setDrawFace(DrawFace face) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000508 SkASSERT(kInvalid_DrawFace != face);
bsalomon2ed5ef82014-07-07 08:44:05 -0700509 fDrawFace = face;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000510 }
511
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000512 /// @}
513
514 ///////////////////////////////////////////////////////////////////////////
bsalomon62c447d2014-08-08 08:08:50 -0700515 /// @name Hints
516 /// Hints that when provided can enable optimizations.
517 ////
518
bsalomon62c447d2014-08-08 08:08:50 -0700519 void setHint(Hints hint, bool value) { fHints = value ? (fHints | hint) : (fHints & ~hint); }
520
521 /// @}
522
523 ///////////////////////////////////////////////////////////////////////////
tomhudson@google.com62b09682011-11-09 16:39:17 +0000524
bsalomon838f62d2014-08-05 07:15:57 -0700525 /** Return type for CombineIfPossible. */
526 enum CombinedState {
527 /** The GrDrawStates cannot be combined. */
528 kIncompatible_CombinedState,
529 /** Either draw state can be used in place of the other. */
530 kAOrB_CombinedState,
531 /** Use the first draw state. */
532 kA_CombinedState,
533 /** Use the second draw state. */
534 kB_CombinedState,
535 };
536
537 /** This function determines whether the GrDrawStates used for two draws can be combined into
538 a single GrDrawState. This is used to avoid storing redundant GrDrawStates and to determine
539 if draws can be batched. The return value indicates whether combining is possible and, if
540 so, which of the two inputs should be used. */
bsalomon62c447d2014-08-08 08:08:50 -0700541 static CombinedState CombineIfPossible(const GrDrawState& a, const GrDrawState& b,
542 const GrDrawTargetCaps& caps);
bsalomon72336ed2014-08-05 07:35:56 -0700543
bsalomon8f727332014-08-05 07:50:06 -0700544 GrDrawState& operator= (const GrDrawState& that);
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000545
egdaniel3658f382014-09-15 07:01:59 -0700546 /**
547 * Returns a snapshot of the current optimized state. If the current drawState has a valid
548 * cached optimiezed state it will simply return a pointer to it otherwise it will create a new
549 * GrOptDrawState. In all cases the GrOptDrawState is reffed and ownership is given to the
550 * caller.
551 */
552 GrOptDrawState* createOptState() const;
553
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000554private:
egdaniel3658f382014-09-15 07:01:59 -0700555 void invalidateOptState() const {
556 SkSafeSetNull(fCachedOptState);
557 fBlendOptFlags = kInvalid_BlendOptFlag;
558 }
559
bsalomon8f727332014-08-05 07:50:06 -0700560 void onReset(const SkMatrix* initialViewMatrix);
bsalomon@google.com137f1342013-05-29 21:27:53 +0000561
egdaniel21aed572014-08-26 12:24:06 -0700562 void invalidateBlendOptFlags() {
563 fBlendOptFlags = kInvalid_BlendOptFlag;
564 }
bsalomon62c447d2014-08-08 08:08:50 -0700565
bsalomon@google.comeb6879f2013-06-13 19:34:18 +0000566 // Some of the auto restore objects assume that no effects are removed during their lifetime.
567 // This is used to assert that this condition holds.
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +0000568 SkDEBUGCODE(int fBlockEffectRemovalCnt;)
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000569
egdaniel7b3d5ee2014-08-28 05:41:14 -0700570 void internalSetVertexAttribs(const GrVertexAttrib attribs[], int count, size_t stride);
robertphillips@google.com42903302013-04-20 12:26:07 +0000571
egdaniel3658f382014-09-15 07:01:59 -0700572 mutable GrOptDrawState* fCachedOptState;
573
egdaniel21aed572014-08-26 12:24:06 -0700574 typedef GrRODrawState INHERITED;
tomhudson@google.com93813632011-10-27 20:21:16 +0000575};
576
577#endif