1 /*
2 * Copyright 2012 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 #include "GrDrawState.h"
9
10 #include "GrOptDrawState.h"
11 #include "GrPaint.h"
12
13 //////////////////////////////////////////////////////////////////////////////s
14
createOptState(const GrDrawTargetCaps & caps) const15 GrOptDrawState* GrDrawState::createOptState(const GrDrawTargetCaps& caps) const {
16 if (NULL == fCachedOptState || caps.getUniqueID() != fCachedCapsID) {
17 GrBlendCoeff srcCoeff;
18 GrBlendCoeff dstCoeff;
19 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
20 fCachedOptState = SkNEW_ARGS(GrOptDrawState, (*this, blendFlags, srcCoeff, dstCoeff, caps));
21 fCachedCapsID = caps.getUniqueID();
22 } else {
23 #ifdef SK_DEBUG
24 GrBlendCoeff srcCoeff;
25 GrBlendCoeff dstCoeff;
26 BlendOptFlags blendFlags = this->getBlendOpts(false, &srcCoeff, &dstCoeff);
27 SkASSERT(GrOptDrawState(*this, blendFlags, srcCoeff, dstCoeff, caps) == *fCachedOptState);
28 #endif
29 }
30 fCachedOptState->ref();
31 return fCachedOptState;
32 }
33
34 //////////////////////////////////////////////////////////////////////////////s
35
CombineIfPossible(const GrDrawState & a,const GrDrawState & b,const GrDrawTargetCaps & caps)36 GrDrawState::CombinedState GrDrawState::CombineIfPossible(
37 const GrDrawState& a, const GrDrawState& b, const GrDrawTargetCaps& caps) {
38
39 if (!a.isEqual(b)) {
40 return kIncompatible_CombinedState;
41 }
42
43 // If the general draw states are equal (from check above) we know hasColorVertexAttribute()
44 // is equivalent for both a and b
45 if (a.hasColorVertexAttribute()) {
46 // If one is opaque and the other is not then the combined state is not opaque. Moreover,
47 // if the opaqueness affects the ability to get color/coverage blending correct then we
48 // don't combine the draw states.
49 bool aIsOpaque = (kVertexColorsAreOpaque_Hint & a.fHints);
50 bool bIsOpaque = (kVertexColorsAreOpaque_Hint & b.fHints);
51 if (aIsOpaque != bIsOpaque) {
52 const GrDrawState* opaque;
53 const GrDrawState* nonOpaque;
54 if (aIsOpaque) {
55 opaque = &a;
56 nonOpaque = &b;
57 } else {
58 opaque = &b;
59 nonOpaque = &a;
60 }
61 if (!opaque->hasSolidCoverage() && opaque->couldApplyCoverage(caps)) {
62 SkASSERT(!nonOpaque->hasSolidCoverage());
63 if (!nonOpaque->couldApplyCoverage(caps)) {
64 return kIncompatible_CombinedState;
65 }
66 }
67 return aIsOpaque ? kB_CombinedState : kA_CombinedState;
68 }
69 }
70 return kAOrB_CombinedState;
71 }
72
73 //////////////////////////////////////////////////////////////////////////////s
74
GrDrawState(const GrDrawState & state,const SkMatrix & preConcatMatrix)75 GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix)
76 : fCachedOptState(NULL) {
77 SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
78 *this = state;
79 if (!preConcatMatrix.isIdentity()) {
80 if (this->hasGeometryProcessor()) {
81 fGeometryProcessor->localCoordChange(preConcatMatrix);
82 }
83 for (int i = 0; i < this->numColorStages(); ++i) {
84 fColorStages[i].localCoordChange(preConcatMatrix);
85 }
86 for (int i = 0; i < this->numCoverageStages(); ++i) {
87 fCoverageStages[i].localCoordChange(preConcatMatrix);
88 }
89 this->invalidateOptState();
90 }
91 }
92
operator =(const GrDrawState & that)93 GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
94 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
95 SkASSERT(!that.fRenderTarget.ownsPendingIO());
96 SkASSERT(!this->fRenderTarget.ownsPendingIO());
97 this->setRenderTarget(that.getRenderTarget());
98 fColor = that.fColor;
99 fViewMatrix = that.fViewMatrix;
100 fSrcBlend = that.fSrcBlend;
101 fDstBlend = that.fDstBlend;
102 fBlendConstant = that.fBlendConstant;
103 fFlagBits = that.fFlagBits;
104 fVACount = that.fVACount;
105 fVAPtr = that.fVAPtr;
106 fVAStride = that.fVAStride;
107 fStencilSettings = that.fStencilSettings;
108 fCoverage = that.fCoverage;
109 fDrawFace = that.fDrawFace;
110 if (that.hasGeometryProcessor()) {
111 fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get())));
112 } else {
113 fGeometryProcessor.reset(NULL);
114 }
115 fColorStages = that.fColorStages;
116 fCoverageStages = that.fCoverageStages;
117
118 fHints = that.fHints;
119
120 SkRefCnt_SafeAssign(fCachedOptState, that.fCachedOptState);
121
122 memcpy(fFixedFunctionVertexAttribIndices,
123 that.fFixedFunctionVertexAttribIndices,
124 sizeof(fFixedFunctionVertexAttribIndices));
125 return *this;
126 }
127
onReset(const SkMatrix * initialViewMatrix)128 void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
129 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
130 SkASSERT(!fRenderTarget.ownsPendingIO());
131
132 fGeometryProcessor.reset(NULL);
133 fColorStages.reset();
134 fCoverageStages.reset();
135
136 fRenderTarget.reset();
137
138 this->setDefaultVertexAttribs();
139
140 fColor = 0xffffffff;
141 if (NULL == initialViewMatrix) {
142 fViewMatrix.reset();
143 } else {
144 fViewMatrix = *initialViewMatrix;
145 }
146 fSrcBlend = kOne_GrBlendCoeff;
147 fDstBlend = kZero_GrBlendCoeff;
148 fBlendConstant = 0x0;
149 fFlagBits = 0x0;
150 fStencilSettings.setDisabled();
151 fCoverage = 0xff;
152 fDrawFace = kBoth_DrawFace;
153
154 fHints = 0;
155
156 this->invalidateOptState();
157 }
158
setIdentityViewMatrix()159 bool GrDrawState::setIdentityViewMatrix() {
160 if (this->numTotalStages()) {
161 SkMatrix invVM;
162 if (!fViewMatrix.invert(&invVM)) {
163 // sad trombone sound
164 return false;
165 }
166 if (this->hasGeometryProcessor()) {
167 fGeometryProcessor->localCoordChange(invVM);
168 }
169 for (int s = 0; s < this->numColorStages(); ++s) {
170 fColorStages[s].localCoordChange(invVM);
171 }
172 for (int s = 0; s < this->numCoverageStages(); ++s) {
173 fCoverageStages[s].localCoordChange(invVM);
174 }
175 }
176 this->invalidateOptState();
177 fViewMatrix.reset();
178 return true;
179 }
180
setFromPaint(const GrPaint & paint,const SkMatrix & vm,GrRenderTarget * rt)181 void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
182 SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
183
184 fGeometryProcessor.reset(NULL);
185 fColorStages.reset();
186 fCoverageStages.reset();
187
188 for (int i = 0; i < paint.numColorStages(); ++i) {
189 fColorStages.push_back(paint.getColorStage(i));
190 }
191
192 for (int i = 0; i < paint.numCoverageStages(); ++i) {
193 fCoverageStages.push_back(paint.getCoverageStage(i));
194 }
195
196 this->setRenderTarget(rt);
197
198 fViewMatrix = vm;
199
200 // These have no equivalent in GrPaint, set them to defaults
201 fBlendConstant = 0x0;
202 fDrawFace = kBoth_DrawFace;
203 fStencilSettings.setDisabled();
204 this->resetStateFlags();
205 fHints = 0;
206
207 // Enable the clip bit
208 this->enableState(GrDrawState::kClip_StateBit);
209
210 this->setColor(paint.getColor());
211 this->setState(GrDrawState::kDither_StateBit, paint.isDither());
212 this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
213
214 this->setBlendFunc(paint.getSrcBlendCoeff(), paint.getDstBlendCoeff());
215 this->setCoverage(paint.getCoverage());
216 this->invalidateOptState();
217 }
218
219 ////////////////////////////////////////////////////////////////////////////////
220
validate_vertex_attribs(const GrVertexAttrib * attribs,int count,size_t stride)221 static void validate_vertex_attribs(const GrVertexAttrib* attribs, int count, size_t stride) {
222 // this works as long as we're 4 byte-aligned
223 #ifdef SK_DEBUG
224 uint32_t overlapCheck = 0;
225 SkASSERT(count <= GrRODrawState::kMaxVertexAttribCnt);
226 for (int index = 0; index < count; ++index) {
227 size_t attribSize = GrVertexAttribTypeSize(attribs[index].fType);
228 size_t attribOffset = attribs[index].fOffset;
229 SkASSERT(attribOffset + attribSize <= stride);
230 size_t dwordCount = attribSize >> 2;
231 uint32_t mask = (1 << dwordCount)-1;
232 size_t offsetShift = attribOffset >> 2;
233 SkASSERT(!(overlapCheck & (mask << offsetShift)));
234 overlapCheck |= (mask << offsetShift);
235 }
236 #endif
237 }
238
239 ////////////////////////////////////////////////////////////////////////////////
240
internalSetVertexAttribs(const GrVertexAttrib * attribs,int count,size_t stride)241 void GrDrawState::internalSetVertexAttribs(const GrVertexAttrib* attribs, int count,
242 size_t stride) {
243 SkASSERT(count <= kMaxVertexAttribCnt);
244
245 fVAPtr = attribs;
246 fVACount = count;
247 fVAStride = stride;
248 validate_vertex_attribs(fVAPtr, fVACount, fVAStride);
249
250 // Set all the indices to -1
251 memset(fFixedFunctionVertexAttribIndices,
252 0xff,
253 sizeof(fFixedFunctionVertexAttribIndices));
254 #ifdef SK_DEBUG
255 uint32_t overlapCheck = 0;
256 #endif
257 for (int i = 0; i < count; ++i) {
258 if (attribs[i].fBinding < kGrFixedFunctionVertexAttribBindingCnt) {
259 // The fixed function attribs can only be specified once
260 SkASSERT(-1 == fFixedFunctionVertexAttribIndices[attribs[i].fBinding]);
261 SkASSERT(GrFixedFunctionVertexAttribVectorCount(attribs[i].fBinding) ==
262 GrVertexAttribTypeVectorCount(attribs[i].fType));
263 fFixedFunctionVertexAttribIndices[attribs[i].fBinding] = i;
264 }
265 #ifdef SK_DEBUG
266 size_t dwordCount = GrVertexAttribTypeSize(attribs[i].fType) >> 2;
267 uint32_t mask = (1 << dwordCount)-1;
268 size_t offsetShift = attribs[i].fOffset >> 2;
269 SkASSERT(!(overlapCheck & (mask << offsetShift)));
270 overlapCheck |= (mask << offsetShift);
271 #endif
272 }
273 this->invalidateOptState();
274 // Positions must be specified.
275 SkASSERT(-1 != fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding]);
276 }
277
278 ////////////////////////////////////////////////////////////////////////////////
279
setDefaultVertexAttribs()280 void GrDrawState::setDefaultVertexAttribs() {
281 static const GrVertexAttrib kPositionAttrib =
282 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding};
283
284 fVAPtr = &kPositionAttrib;
285 fVACount = 1;
286 fVAStride = GrVertexAttribTypeSize(kVec2f_GrVertexAttribType);
287
288 // set all the fixed function indices to -1 except position.
289 memset(fFixedFunctionVertexAttribIndices,
290 0xff,
291 sizeof(fFixedFunctionVertexAttribIndices));
292 fFixedFunctionVertexAttribIndices[kPosition_GrVertexAttribBinding] = 0;
293 this->invalidateOptState();
294 }
295
296 ////////////////////////////////////////////////////////////////////////////////
297
couldApplyCoverage(const GrDrawTargetCaps & caps) const298 bool GrDrawState::couldApplyCoverage(const GrDrawTargetCaps& caps) const {
299 if (caps.dualSourceBlendingSupport()) {
300 return true;
301 }
302 // we can correctly apply coverage if a) we have dual source blending
303 // or b) one of our blend optimizations applies
304 // or c) the src, dst blend coeffs are 1,0 and we will read Dst Color
305 GrBlendCoeff srcCoeff;
306 GrBlendCoeff dstCoeff;
307 BlendOptFlags flag = this->getBlendOpts(true, &srcCoeff, &dstCoeff);
308 return GrRODrawState::kNone_BlendOpt != flag ||
309 (this->willEffectReadDstColor() &&
310 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff);
311 }
312
313 //////////////////////////////////////////////////////////////////////////////
314
AutoVertexAttribRestore(GrDrawState * drawState)315 GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(GrDrawState* drawState) {
316 SkASSERT(drawState);
317 fDrawState = drawState;
318 fVAPtr = drawState->fVAPtr;
319 fVACount = drawState->fVACount;
320 fVAStride = drawState->fVAStride;
321 fDrawState->setDefaultVertexAttribs();
322 }
323
324 //////////////////////////////////////////////////////////////////////////////s
325
set(GrDrawState * ds)326 void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
327 if (fDrawState) {
328 // See the big comment on the class definition about GPs.
329 if (SK_InvalidUniqueID == fOriginalGPID) {
330 fDrawState->fGeometryProcessor.reset(NULL);
331 } else {
332 SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
333 fOriginalGPID);
334 fOriginalGPID = SK_InvalidUniqueID;
335 }
336
337 int m = fDrawState->numColorStages() - fColorEffectCnt;
338 SkASSERT(m >= 0);
339 fDrawState->fColorStages.pop_back_n(m);
340
341 int n = fDrawState->numCoverageStages() - fCoverageEffectCnt;
342 SkASSERT(n >= 0);
343 fDrawState->fCoverageStages.pop_back_n(n);
344 if (m + n > 0) {
345 fDrawState->invalidateOptState();
346 }
347 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
348 }
349 fDrawState = ds;
350 if (NULL != ds) {
351 SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
352 if (NULL != ds->getGeometryProcessor()) {
353 fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
354 }
355 fColorEffectCnt = ds->numColorStages();
356 fCoverageEffectCnt = ds->numCoverageStages();
357 SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
358 }
359 }
360
361 ////////////////////////////////////////////////////////////////////////////////
362
restore()363 void GrDrawState::AutoViewMatrixRestore::restore() {
364 if (fDrawState) {
365 SkDEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
366 fDrawState->fViewMatrix = fViewMatrix;
367 SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
368 int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
369 SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
370
371 int i = 0;
372 if (fHasGeometryProcessor) {
373 SkASSERT(fDrawState->hasGeometryProcessor());
374 fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
375 }
376 for (int s = 0; s < fNumColorStages; ++s, ++i) {
377 fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
378 }
379 for (int s = 0; s < numCoverageStages; ++s, ++i) {
380 fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
381 }
382 fDrawState->invalidateOptState();
383 fDrawState = NULL;
384 }
385 }
386
set(GrDrawState * drawState,const SkMatrix & preconcatMatrix)387 void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
388 const SkMatrix& preconcatMatrix) {
389 this->restore();
390
391 SkASSERT(NULL == fDrawState);
392 if (NULL == drawState || preconcatMatrix.isIdentity()) {
393 return;
394 }
395 fDrawState = drawState;
396
397 fViewMatrix = drawState->getViewMatrix();
398 drawState->fViewMatrix.preConcat(preconcatMatrix);
399
400 this->doEffectCoordChanges(preconcatMatrix);
401 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
402 drawState->invalidateOptState();
403 }
404
setIdentity(GrDrawState * drawState)405 bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
406 this->restore();
407
408 if (NULL == drawState) {
409 return false;
410 }
411
412 if (drawState->getViewMatrix().isIdentity()) {
413 return true;
414 }
415
416 drawState->invalidateOptState();
417 fViewMatrix = drawState->getViewMatrix();
418 if (0 == drawState->numTotalStages()) {
419 drawState->fViewMatrix.reset();
420 fDrawState = drawState;
421 fHasGeometryProcessor = false;
422 fNumColorStages = 0;
423 fSavedCoordChanges.reset(0);
424 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
425 return true;
426 } else {
427 SkMatrix inv;
428 if (!fViewMatrix.invert(&inv)) {
429 return false;
430 }
431 drawState->fViewMatrix.reset();
432 fDrawState = drawState;
433 this->doEffectCoordChanges(inv);
434 SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
435 return true;
436 }
437 }
438
doEffectCoordChanges(const SkMatrix & coordChangeMatrix)439 void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
440 fSavedCoordChanges.reset(fDrawState->numTotalStages());
441 int i = 0;
442
443 fHasGeometryProcessor = false;
444 if (fDrawState->hasGeometryProcessor()) {
445 fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
446 fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
447 fHasGeometryProcessor = true;
448 }
449
450 fNumColorStages = fDrawState->numColorStages();
451 for (int s = 0; s < fNumColorStages; ++s, ++i) {
452 fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
453 fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
454 }
455
456 int numCoverageStages = fDrawState->numCoverageStages();
457 for (int s = 0; s < numCoverageStages; ++s, ++i) {
458 fDrawState->getCoverageStage(s).saveCoordChange(&fSavedCoordChanges[i]);
459 fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
460 }
461 }
462
463 ////////////////////////////////////////////////////////////////////////////////
464
invalidateOptState() const465 void GrDrawState::invalidateOptState() const {
466 SkSafeSetNull(fCachedOptState);
467 }
468
469 ////////////////////////////////////////////////////////////////////////////////
470
~GrDrawState()471 GrDrawState::~GrDrawState() {
472 SkSafeUnref(fCachedOptState);
473 SkASSERT(0 == fBlockEffectRemovalCnt);
474 }
475
476