1
2 /*
3 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10
11 #include "GrDrawTarget.h"
12 #include "GrRenderTarget.h"
13 #include "GrTexture.h"
14 #include "GrVertexBuffer.h"
15
16 #include "SkStrokeRec.h"
17
SK_DEFINE_INST_COUNT(GrDrawTarget)18 SK_DEFINE_INST_COUNT(GrDrawTarget)
19
20 ////////////////////////////////////////////////////////////////////////////////
21
22 GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
23 fPrimitiveType = di.fPrimitiveType;
24 fStartVertex = di.fStartVertex;
25 fStartIndex = di.fStartIndex;
26 fVertexCount = di.fVertexCount;
27 fIndexCount = di.fIndexCount;
28
29 fInstanceCount = di.fInstanceCount;
30 fVerticesPerInstance = di.fVerticesPerInstance;
31 fIndicesPerInstance = di.fIndicesPerInstance;
32
33 if (NULL != di.fDevBounds) {
34 GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
35 fDevBoundsStorage = di.fDevBoundsStorage;
36 fDevBounds = &fDevBoundsStorage;
37 } else {
38 fDevBounds = NULL;
39 }
40 return *this;
41 }
42
43 #if GR_DEBUG
isInstanced() const44 bool GrDrawTarget::DrawInfo::isInstanced() const {
45 if (fInstanceCount > 0) {
46 GrAssert(0 == fIndexCount % fIndicesPerInstance);
47 GrAssert(0 == fVertexCount % fVerticesPerInstance);
48 GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
49 GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
50 // there is no way to specify a non-zero start index to drawIndexedInstances().
51 GrAssert(0 == fStartIndex);
52 return true;
53 } else {
54 GrAssert(!fVerticesPerInstance);
55 GrAssert(!fIndicesPerInstance);
56 return false;
57 }
58 }
59 #endif
60
adjustInstanceCount(int instanceOffset)61 void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
62 GrAssert(this->isInstanced());
63 GrAssert(instanceOffset + fInstanceCount >= 0);
64 fInstanceCount += instanceOffset;
65 fVertexCount = fVerticesPerInstance * fInstanceCount;
66 fIndexCount = fIndicesPerInstance * fInstanceCount;
67 }
68
adjustStartVertex(int vertexOffset)69 void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
70 fStartVertex += vertexOffset;
71 GrAssert(fStartVertex >= 0);
72 }
73
adjustStartIndex(int indexOffset)74 void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
75 GrAssert(this->isIndexed());
76 fStartIndex += indexOffset;
77 GrAssert(fStartIndex >= 0);
78 }
79
80 ////////////////////////////////////////////////////////////////////////////////
81
82 #define DEBUG_INVAL_BUFFER 0xdeadcafe
83 #define DEBUG_INVAL_START_IDX -1
84
GrDrawTarget()85 GrDrawTarget::GrDrawTarget() : fClip(NULL) {
86 fDrawState = &fDefaultDrawState;
87 // We assume that fDrawState always owns a ref to the object it points at.
88 fDefaultDrawState.ref();
89 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
90 #if GR_DEBUG
91 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
92 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
93 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
94 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
95 #endif
96 geoSrc.fVertexSrc = kNone_GeometrySrcType;
97 geoSrc.fIndexSrc = kNone_GeometrySrcType;
98 }
99
~GrDrawTarget()100 GrDrawTarget::~GrDrawTarget() {
101 GrAssert(1 == fGeoSrcStateStack.count());
102 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
103 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
104 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
105 fDrawState->unref();
106 }
107
releaseGeometry()108 void GrDrawTarget::releaseGeometry() {
109 int popCnt = fGeoSrcStateStack.count() - 1;
110 while (popCnt) {
111 this->popGeometrySource();
112 --popCnt;
113 }
114 this->resetVertexSource();
115 this->resetIndexSource();
116 }
117
setClip(const GrClipData * clip)118 void GrDrawTarget::setClip(const GrClipData* clip) {
119 clipWillBeSet(clip);
120 fClip = clip;
121 }
122
getClip() const123 const GrClipData* GrDrawTarget::getClip() const {
124 return fClip;
125 }
126
setDrawState(GrDrawState * drawState)127 void GrDrawTarget::setDrawState(GrDrawState* drawState) {
128 GrAssert(NULL != fDrawState);
129 if (NULL == drawState) {
130 drawState = &fDefaultDrawState;
131 }
132 if (fDrawState != drawState) {
133 fDrawState->unref();
134 drawState->ref();
135 fDrawState = drawState;
136 }
137 }
138
reserveVertexSpace(GrVertexLayout vertexLayout,int vertexCount,void ** vertices)139 bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
140 int vertexCount,
141 void** vertices) {
142 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
143 bool acquired = false;
144 if (vertexCount > 0) {
145 GrAssert(NULL != vertices);
146 this->releasePreviousVertexSource();
147 geoSrc.fVertexSrc = kNone_GeometrySrcType;
148
149 acquired = this->onReserveVertexSpace(GrDrawState::VertexSize(vertexLayout),
150 vertexCount,
151 vertices);
152 }
153 if (acquired) {
154 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155 geoSrc.fVertexCount = vertexCount;
156 geoSrc.fVertexLayout = vertexLayout;
157 } else if (NULL != vertices) {
158 *vertices = NULL;
159 }
160 return acquired;
161 }
162
reserveIndexSpace(int indexCount,void ** indices)163 bool GrDrawTarget::reserveIndexSpace(int indexCount,
164 void** indices) {
165 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
166 bool acquired = false;
167 if (indexCount > 0) {
168 GrAssert(NULL != indices);
169 this->releasePreviousIndexSource();
170 geoSrc.fIndexSrc = kNone_GeometrySrcType;
171
172 acquired = this->onReserveIndexSpace(indexCount, indices);
173 }
174 if (acquired) {
175 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
176 geoSrc.fIndexCount = indexCount;
177 } else if (NULL != indices) {
178 *indices = NULL;
179 }
180 return acquired;
181
182 }
183
reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,int vertexCount,int indexCount,void ** vertices,void ** indices)184 bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
185 int vertexCount,
186 int indexCount,
187 void** vertices,
188 void** indices) {
189 this->willReserveVertexAndIndexSpace(GrDrawState::VertexSize(vertexLayout), vertexCount, indexCount);
190 if (vertexCount) {
191 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
192 if (indexCount) {
193 this->resetIndexSource();
194 }
195 return false;
196 }
197 }
198 if (indexCount) {
199 if (!this->reserveIndexSpace(indexCount, indices)) {
200 if (vertexCount) {
201 this->resetVertexSource();
202 }
203 return false;
204 }
205 }
206 return true;
207 }
208
geometryHints(size_t vertexSize,int32_t * vertexCount,int32_t * indexCount) const209 bool GrDrawTarget::geometryHints(size_t vertexSize,
210 int32_t* vertexCount,
211 int32_t* indexCount) const {
212 if (NULL != vertexCount) {
213 *vertexCount = -1;
214 }
215 if (NULL != indexCount) {
216 *indexCount = -1;
217 }
218 return false;
219 }
220
releasePreviousVertexSource()221 void GrDrawTarget::releasePreviousVertexSource() {
222 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
223 switch (geoSrc.fVertexSrc) {
224 case kNone_GeometrySrcType:
225 break;
226 case kArray_GeometrySrcType:
227 this->releaseVertexArray();
228 break;
229 case kReserved_GeometrySrcType:
230 this->releaseReservedVertexSpace();
231 break;
232 case kBuffer_GeometrySrcType:
233 geoSrc.fVertexBuffer->unref();
234 #if GR_DEBUG
235 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
236 #endif
237 break;
238 default:
239 GrCrash("Unknown Vertex Source Type.");
240 break;
241 }
242 }
243
releasePreviousIndexSource()244 void GrDrawTarget::releasePreviousIndexSource() {
245 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
246 switch (geoSrc.fIndexSrc) {
247 case kNone_GeometrySrcType: // these two don't require
248 break;
249 case kArray_GeometrySrcType:
250 this->releaseIndexArray();
251 break;
252 case kReserved_GeometrySrcType:
253 this->releaseReservedIndexSpace();
254 break;
255 case kBuffer_GeometrySrcType:
256 geoSrc.fIndexBuffer->unref();
257 #if GR_DEBUG
258 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
259 #endif
260 break;
261 default:
262 GrCrash("Unknown Index Source Type.");
263 break;
264 }
265 }
266
setVertexSourceToArray(GrVertexLayout vertexLayout,const void * vertexArray,int vertexCount)267 void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
268 const void* vertexArray,
269 int vertexCount) {
270 this->releasePreviousVertexSource();
271 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
272 geoSrc.fVertexSrc = kArray_GeometrySrcType;
273 geoSrc.fVertexLayout = vertexLayout;
274 geoSrc.fVertexCount = vertexCount;
275 this->onSetVertexSourceToArray(vertexArray, vertexCount);
276 }
277
setIndexSourceToArray(const void * indexArray,int indexCount)278 void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
279 int indexCount) {
280 this->releasePreviousIndexSource();
281 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
282 geoSrc.fIndexSrc = kArray_GeometrySrcType;
283 geoSrc.fIndexCount = indexCount;
284 this->onSetIndexSourceToArray(indexArray, indexCount);
285 }
286
setVertexSourceToBuffer(GrVertexLayout vertexLayout,const GrVertexBuffer * buffer)287 void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
288 const GrVertexBuffer* buffer) {
289 this->releasePreviousVertexSource();
290 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
291 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
292 geoSrc.fVertexBuffer = buffer;
293 buffer->ref();
294 geoSrc.fVertexLayout = vertexLayout;
295 }
296
setIndexSourceToBuffer(const GrIndexBuffer * buffer)297 void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
298 this->releasePreviousIndexSource();
299 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
300 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
301 geoSrc.fIndexBuffer = buffer;
302 buffer->ref();
303 }
304
resetVertexSource()305 void GrDrawTarget::resetVertexSource() {
306 this->releasePreviousVertexSource();
307 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
308 geoSrc.fVertexSrc = kNone_GeometrySrcType;
309 }
310
resetIndexSource()311 void GrDrawTarget::resetIndexSource() {
312 this->releasePreviousIndexSource();
313 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
314 geoSrc.fIndexSrc = kNone_GeometrySrcType;
315 }
316
pushGeometrySource()317 void GrDrawTarget::pushGeometrySource() {
318 this->geometrySourceWillPush();
319 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
320 newState.fIndexSrc = kNone_GeometrySrcType;
321 newState.fVertexSrc = kNone_GeometrySrcType;
322 #if GR_DEBUG
323 newState.fVertexCount = ~0;
324 newState.fVertexBuffer = (GrVertexBuffer*)~0;
325 newState.fIndexCount = ~0;
326 newState.fIndexBuffer = (GrIndexBuffer*)~0;
327 #endif
328 }
329
popGeometrySource()330 void GrDrawTarget::popGeometrySource() {
331 // if popping last element then pops are unbalanced with pushes
332 GrAssert(fGeoSrcStateStack.count() > 1);
333
334 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
335 this->releasePreviousVertexSource();
336 this->releasePreviousIndexSource();
337 fGeoSrcStateStack.pop_back();
338 }
339
340 ////////////////////////////////////////////////////////////////////////////////
341
checkDraw(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount) const342 bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
343 int startIndex, int vertexCount,
344 int indexCount) const {
345 const GrDrawState& drawState = this->getDrawState();
346 #if GR_DEBUG
347 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
348 int maxVertex = startVertex + vertexCount;
349 int maxValidVertex;
350 switch (geoSrc.fVertexSrc) {
351 case kNone_GeometrySrcType:
352 GrCrash("Attempting to draw without vertex src.");
353 case kReserved_GeometrySrcType: // fallthrough
354 case kArray_GeometrySrcType:
355 maxValidVertex = geoSrc.fVertexCount;
356 break;
357 case kBuffer_GeometrySrcType:
358 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / GrDrawState::VertexSize(geoSrc.fVertexLayout);
359 break;
360 }
361 if (maxVertex > maxValidVertex) {
362 GrCrash("Drawing outside valid vertex range.");
363 }
364 if (indexCount > 0) {
365 int maxIndex = startIndex + indexCount;
366 int maxValidIndex;
367 switch (geoSrc.fIndexSrc) {
368 case kNone_GeometrySrcType:
369 GrCrash("Attempting to draw indexed geom without index src.");
370 case kReserved_GeometrySrcType: // fallthrough
371 case kArray_GeometrySrcType:
372 maxValidIndex = geoSrc.fIndexCount;
373 break;
374 case kBuffer_GeometrySrcType:
375 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
376 break;
377 }
378 if (maxIndex > maxValidIndex) {
379 GrCrash("Index reads outside valid index range.");
380 }
381 }
382
383 GrAssert(NULL != drawState.getRenderTarget());
384 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
385 if (drawState.isStageEnabled(s)) {
386 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
387 int numTextures = effect->numTextures();
388 for (int t = 0; t < numTextures; ++t) {
389 GrTexture* texture = effect->texture(t);
390 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
391 }
392 }
393 }
394 #endif
395 if (NULL == drawState.getRenderTarget()) {
396 return false;
397 }
398 return true;
399 }
400
drawIndexed(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount,const SkRect * devBounds)401 void GrDrawTarget::drawIndexed(GrPrimitiveType type,
402 int startVertex,
403 int startIndex,
404 int vertexCount,
405 int indexCount,
406 const SkRect* devBounds) {
407 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
408 DrawInfo info;
409 info.fPrimitiveType = type;
410 info.fStartVertex = startVertex;
411 info.fStartIndex = startIndex;
412 info.fVertexCount = vertexCount;
413 info.fIndexCount = indexCount;
414
415 info.fInstanceCount = 0;
416 info.fVerticesPerInstance = 0;
417 info.fIndicesPerInstance = 0;
418
419 if (NULL != devBounds) {
420 info.setDevBounds(*devBounds);
421 }
422 this->onDraw(info);
423 }
424 }
425
drawNonIndexed(GrPrimitiveType type,int startVertex,int vertexCount,const SkRect * devBounds)426 void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
427 int startVertex,
428 int vertexCount,
429 const SkRect* devBounds) {
430 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
431 DrawInfo info;
432 info.fPrimitiveType = type;
433 info.fStartVertex = startVertex;
434 info.fStartIndex = 0;
435 info.fVertexCount = vertexCount;
436 info.fIndexCount = 0;
437
438 info.fInstanceCount = 0;
439 info.fVerticesPerInstance = 0;
440 info.fIndicesPerInstance = 0;
441
442 if (NULL != devBounds) {
443 info.setDevBounds(*devBounds);
444 }
445 this->onDraw(info);
446 }
447 }
448
stencilPath(const GrPath * path,const SkStrokeRec & stroke,SkPath::FillType fill)449 void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
450 // TODO: extract portions of checkDraw that are relevant to path stenciling.
451 GrAssert(NULL != path);
452 GrAssert(fCaps.pathStencilingSupport());
453 GrAssert(!stroke.isHairlineStyle());
454 GrAssert(!SkPath::IsInverseFillType(fill));
455 this->onStencilPath(path, stroke, fill);
456 }
457
458 ////////////////////////////////////////////////////////////////////////////////
459
460 // Some blend modes allow folding a partial coverage value into the color's
461 // alpha channel, while others will blend incorrectly.
canTweakAlphaForCoverage() const462 bool GrDrawTarget::canTweakAlphaForCoverage() const {
463 /**
464 * The fractional coverage is f
465 * The src and dst coeffs are Cs and Cd
466 * The dst and src colors are S and D
467 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
468 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
469 * obvious that that first term will always be ok. The second term can be
470 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
471 * for Cd we find that only 1, ISA, and ISC produce the correct depth
472 * coefficient in terms of S' and D.
473 */
474 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
475 return kOne_GrBlendCoeff == dstCoeff ||
476 kISA_GrBlendCoeff == dstCoeff ||
477 kISC_GrBlendCoeff == dstCoeff ||
478 this->getDrawState().isCoverageDrawing();
479 }
480
481 namespace {
default_blend_opts_vertex_layout()482 GrVertexLayout default_blend_opts_vertex_layout() {
483 GrVertexLayout layout = 0;
484 return layout;
485 }
486 }
487
488 GrDrawTarget::BlendOptFlags
getBlendOpts(bool forceCoverage,GrBlendCoeff * srcCoeff,GrBlendCoeff * dstCoeff) const489 GrDrawTarget::getBlendOpts(bool forceCoverage,
490 GrBlendCoeff* srcCoeff,
491 GrBlendCoeff* dstCoeff) const {
492
493 GrVertexLayout layout;
494 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
495 layout = default_blend_opts_vertex_layout();
496 } else {
497 layout = this->getVertexLayout();
498 }
499
500 const GrDrawState& drawState = this->getDrawState();
501
502 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
503 if (NULL == srcCoeff) {
504 srcCoeff = &bogusSrcCoeff;
505 }
506 *srcCoeff = drawState.getSrcBlendCoeff();
507
508 if (NULL == dstCoeff) {
509 dstCoeff = &bogusDstCoeff;
510 }
511 *dstCoeff = drawState.getDstBlendCoeff();
512
513 if (drawState.isColorWriteDisabled()) {
514 *srcCoeff = kZero_GrBlendCoeff;
515 *dstCoeff = kOne_GrBlendCoeff;
516 }
517
518 bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
519 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
520 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
521 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
522 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
523
524 bool covIsZero = !drawState.isCoverageDrawing() &&
525 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
526 0 == drawState.getCoverage();
527 // When coeffs are (0,1) there is no reason to draw at all, unless
528 // stenciling is enabled. Having color writes disabled is effectively
529 // (0,1). The same applies when coverage is known to be 0.
530 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
531 if (drawState.getStencil().doesWrite()) {
532 return kDisableBlend_BlendOptFlag |
533 kEmitTransBlack_BlendOptFlag;
534 } else {
535 return kSkipDraw_BlendOptFlag;
536 }
537 }
538
539 // check for coverage due to constant coverage, per-vertex coverage,
540 // edge aa or coverage stage
541 bool hasCoverage = forceCoverage ||
542 0xffffffff != drawState.getCoverage() ||
543 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
544 (layout & GrDrawState::kEdge_VertexLayoutBit);
545 for (int s = drawState.getFirstCoverageStage();
546 !hasCoverage && s < GrDrawState::kNumStages;
547 ++s) {
548 if (drawState.isStageEnabled(s)) {
549 hasCoverage = true;
550 }
551 }
552
553 // if we don't have coverage we can check whether the dst
554 // has to read at all. If not, we'll disable blending.
555 if (!hasCoverage) {
556 if (dstCoeffIsZero) {
557 if (kOne_GrBlendCoeff == *srcCoeff) {
558 // if there is no coverage and coeffs are (1,0) then we
559 // won't need to read the dst at all, it gets replaced by src
560 return kDisableBlend_BlendOptFlag;
561 } else if (kZero_GrBlendCoeff == *srcCoeff) {
562 // if the op is "clear" then we don't need to emit a color
563 // or blend, just write transparent black into the dst.
564 *srcCoeff = kOne_GrBlendCoeff;
565 *dstCoeff = kZero_GrBlendCoeff;
566 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
567 }
568 }
569 } else if (drawState.isCoverageDrawing()) {
570 // we have coverage but we aren't distinguishing it from alpha by request.
571 return kCoverageAsAlpha_BlendOptFlag;
572 } else {
573 // check whether coverage can be safely rolled into alpha
574 // of if we can skip color computation and just emit coverage
575 if (this->canTweakAlphaForCoverage()) {
576 return kCoverageAsAlpha_BlendOptFlag;
577 }
578 if (dstCoeffIsZero) {
579 if (kZero_GrBlendCoeff == *srcCoeff) {
580 // the source color is not included in the blend
581 // the dst coeff is effectively zero so blend works out to:
582 // (c)(0)D + (1-c)D = (1-c)D.
583 *dstCoeff = kISA_GrBlendCoeff;
584 return kEmitCoverage_BlendOptFlag;
585 } else if (srcAIsOne) {
586 // the dst coeff is effectively zero so blend works out to:
587 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
588 // If Sa is 1 then we can replace Sa with c
589 // and set dst coeff to 1-Sa.
590 *dstCoeff = kISA_GrBlendCoeff;
591 return kCoverageAsAlpha_BlendOptFlag;
592 }
593 } else if (dstCoeffIsOne) {
594 // the dst coeff is effectively one so blend works out to:
595 // cS + (c)(1)D + (1-c)D = cS + D.
596 *dstCoeff = kOne_GrBlendCoeff;
597 return kCoverageAsAlpha_BlendOptFlag;
598 }
599 }
600 return kNone_BlendOpt;
601 }
602
willUseHWAALines() const603 bool GrDrawTarget::willUseHWAALines() const {
604 // there is a conflict between using smooth lines and our use of
605 // premultiplied alpha. Smooth lines tweak the incoming alpha value
606 // but not in a premul-alpha way. So we only use them when our alpha
607 // is 0xff and tweaking the color for partial coverage is OK
608 if (!fCaps.hwAALineSupport() ||
609 !this->getDrawState().isHWAntialiasState()) {
610 return false;
611 }
612 BlendOptFlags opts = this->getBlendOpts();
613 return (kDisableBlend_BlendOptFlag & opts) &&
614 (kCoverageAsAlpha_BlendOptFlag & opts);
615 }
616
canApplyCoverage() const617 bool GrDrawTarget::canApplyCoverage() const {
618 // we can correctly apply coverage if a) we have dual source blending
619 // or b) one of our blend optimizations applies.
620 return this->getCaps().dualSourceBlendingSupport() ||
621 kNone_BlendOpt != this->getBlendOpts(true);
622 }
623
624 ////////////////////////////////////////////////////////////////////////////////
625
drawIndexedInstances(GrPrimitiveType type,int instanceCount,int verticesPerInstance,int indicesPerInstance,const SkRect * devBounds)626 void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
627 int instanceCount,
628 int verticesPerInstance,
629 int indicesPerInstance,
630 const SkRect* devBounds) {
631 if (!verticesPerInstance || !indicesPerInstance) {
632 return;
633 }
634
635 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
636 if (!maxInstancesPerDraw) {
637 return;
638 }
639
640 DrawInfo info;
641 info.fPrimitiveType = type;
642 info.fStartIndex = 0;
643 info.fStartVertex = 0;
644 info.fIndicesPerInstance = indicesPerInstance;
645 info.fVerticesPerInstance = verticesPerInstance;
646
647 // Set the same bounds for all the draws.
648 if (NULL != devBounds) {
649 info.setDevBounds(*devBounds);
650 }
651
652 while (instanceCount) {
653 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
654 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
655 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
656
657 if (this->checkDraw(type,
658 info.fStartVertex,
659 info.fStartIndex,
660 info.fVertexCount,
661 info.fIndexCount)) {
662 this->onDraw(info);
663 }
664 info.fStartVertex += info.fVertexCount;
665 instanceCount -= info.fInstanceCount;
666 }
667 }
668
669 ////////////////////////////////////////////////////////////////////////////////
670
drawRect(const GrRect & rect,const SkMatrix * matrix,const GrRect * srcRects[],const SkMatrix * srcMatrices[])671 void GrDrawTarget::drawRect(const GrRect& rect,
672 const SkMatrix* matrix,
673 const GrRect* srcRects[],
674 const SkMatrix* srcMatrices[]) {
675 GrVertexLayout layout = 0;
676 uint32_t explicitCoordMask = 0;
677
678 if (NULL != srcRects) {
679 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
680 int numTC = 0;
681 if (NULL != srcRects[s]) {
682 layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
683 explicitCoordMask |= (1 << s);
684 ++numTC;
685 }
686 }
687 }
688
689 GrDrawState::AutoViewMatrixRestore avmr;
690 if (NULL != matrix) {
691 avmr.set(this->drawState(), *matrix, explicitCoordMask);
692 }
693
694 AutoReleaseGeometry geo(this, layout, 4, 0);
695 if (!geo.succeeded()) {
696 GrPrintf("Failed to get space for vertices!\n");
697 return;
698 }
699
700 int stageOffsets[GrDrawState::kNumStages];
701 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, NULL, NULL, NULL);
702 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
703
704 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
705 if (explicitCoordMask & (1 << i)) {
706 GrAssert(0 != stageOffsets[i]);
707 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
708 stageOffsets[i]);
709 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
710 srcRects[i]->fRight, srcRects[i]->fBottom,
711 vsize);
712 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
713 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
714 }
715 } else {
716 GrAssert(0 == stageOffsets[i]);
717 }
718 }
719
720 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
721 }
722
clipWillBeSet(const GrClipData * clipData)723 void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
724 }
725
726 ////////////////////////////////////////////////////////////////////////////////
727
AutoStateRestore()728 GrDrawTarget::AutoStateRestore::AutoStateRestore() {
729 fDrawTarget = NULL;
730 }
731
AutoStateRestore(GrDrawTarget * target,ASRInit init)732 GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
733 ASRInit init) {
734 fDrawTarget = NULL;
735 this->set(target, init);
736 }
737
~AutoStateRestore()738 GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
739 if (NULL != fDrawTarget) {
740 fDrawTarget->setDrawState(fSavedState);
741 fSavedState->unref();
742 }
743 }
744
set(GrDrawTarget * target,ASRInit init)745 void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
746 GrAssert(NULL == fDrawTarget);
747 fDrawTarget = target;
748 fSavedState = target->drawState();
749 GrAssert(fSavedState);
750 fSavedState->ref();
751 if (kReset_ASRInit == init) {
752 // calls the default cons
753 fTempState.init();
754 } else {
755 GrAssert(kPreserve_ASRInit == init);
756 // calls the copy cons
757 fTempState.set(*fSavedState);
758 }
759 target->setDrawState(fTempState.get());
760 }
761
762 ////////////////////////////////////////////////////////////////////////////////
763
AutoReleaseGeometry(GrDrawTarget * target,GrVertexLayout vertexLayout,int vertexCount,int indexCount)764 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
765 GrDrawTarget* target,
766 GrVertexLayout vertexLayout,
767 int vertexCount,
768 int indexCount) {
769 fTarget = NULL;
770 this->set(target, vertexLayout, vertexCount, indexCount);
771 }
772
AutoReleaseGeometry()773 GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
774 fTarget = NULL;
775 }
776
~AutoReleaseGeometry()777 GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
778 this->reset();
779 }
780
set(GrDrawTarget * target,GrVertexLayout vertexLayout,int vertexCount,int indexCount)781 bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
782 GrVertexLayout vertexLayout,
783 int vertexCount,
784 int indexCount) {
785 this->reset();
786 fTarget = target;
787 bool success = true;
788 if (NULL != fTarget) {
789 fTarget = target;
790 success = target->reserveVertexAndIndexSpace(vertexLayout,
791 vertexCount,
792 indexCount,
793 &fVertices,
794 &fIndices);
795 if (!success) {
796 fTarget = NULL;
797 this->reset();
798 }
799 }
800 GrAssert(success == (NULL != fTarget));
801 return success;
802 }
803
reset()804 void GrDrawTarget::AutoReleaseGeometry::reset() {
805 if (NULL != fTarget) {
806 if (NULL != fVertices) {
807 fTarget->resetVertexSource();
808 }
809 if (NULL != fIndices) {
810 fTarget->resetIndexSource();
811 }
812 fTarget = NULL;
813 }
814 fVertices = NULL;
815 fIndices = NULL;
816 }
817
AutoClipRestore(GrDrawTarget * target,const SkIRect & newClip)818 GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
819 fTarget = target;
820 fClip = fTarget->getClip();
821 fStack.init();
822 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
823 fReplacementClip.fClipStack = fStack.get();
824 target->setClip(&fReplacementClip);
825 }
826
print() const827 void GrDrawTarget::Caps::print() const {
828 static const char* gNY[] = {"NO", "YES"};
829 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
830 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
831 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
832 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
833 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
834 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
835 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
836 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
837 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
838 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
839 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
840 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
841 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
842 }
843