blob: c00a5ce509abb6f994e9fcdcab2d21ade688142e [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrDrawTarget.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000012#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000013#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000014#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000015
sugoi@google.com5f74cf82012-12-17 21:16:45 +000016#include "SkStrokeRec.h"
sugoi@google.com12b4e272012-12-06 20:13:11 +000017
reed@google.comfa35e3d2012-06-26 20:16:17 +000018SK_DEFINE_INST_COUNT(GrDrawTarget)
19
reed@google.comac10a2d2010-12-22 21:39:39 +000020////////////////////////////////////////////////////////////////////////////////
21
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000022GrDrawTarget::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
44bool 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
61void 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
69void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
70 fStartVertex += vertexOffset;
71 GrAssert(fStartVertex >= 0);
72}
73
74void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
75 GrAssert(this->isIndexed());
76 fStartIndex += indexOffset;
77 GrAssert(fStartIndex >= 0);
78}
79
80////////////////////////////////////////////////////////////////////////////////
81
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000082#define DEBUG_INVAL_BUFFER 0xdeadcafe
83#define DEBUG_INVAL_START_IDX -1
84
robertphillips@google.combeb1af72012-07-26 18:52:16 +000085GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000086 fDrawState = &fDefaultDrawState;
87 // We assume that fDrawState always owns a ref to the object it points at.
88 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000089 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000090#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000091 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;
reed@google.comac10a2d2010-12-22 21:39:39 +000095#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000096 geoSrc.fVertexSrc = kNone_GeometrySrcType;
97 geoSrc.fIndexSrc = kNone_GeometrySrcType;
98}
99
100GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000101 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +0000102 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000103 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
104 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000105 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000106}
107
108void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000109 int popCnt = fGeoSrcStateStack.count() - 1;
110 while (popCnt) {
111 this->popGeometrySource();
112 --popCnt;
113 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000114 this->resetVertexSource();
115 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000116}
117
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000118void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000119 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 fClip = clip;
121}
122
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000123const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 return fClip;
125}
126
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000127void 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
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000139bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000140 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;
reed@google.comac10a2d2010-12-22 21:39:39 +0000148
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000149 acquired = this->onReserveVertexSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000150 vertexCount,
151 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000153 if (acquired) {
154 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155 geoSrc.fVertexCount = vertexCount;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000156 geoSrc.fVertexSize = vertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000157 } else if (NULL != vertices) {
158 *vertices = NULL;
159 }
160 return acquired;
161}
162
163bool 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000172 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;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181
reed@google.comac10a2d2010-12-22 21:39:39 +0000182}
183
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000184bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000185 int indexCount,
186 void** vertices,
187 void** indices) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000188 size_t vertexSize = this->drawState()->getVertexSize();
189 this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000190 if (vertexCount) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000191 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
bsalomon@google.come3d70952012-03-13 12:40:53 +0000192 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
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000209bool GrDrawTarget::geometryHints(int32_t* vertexCount,
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 if (NULL != vertexCount) {
212 *vertexCount = -1;
213 }
214 if (NULL != indexCount) {
215 *indexCount = -1;
216 }
217 return false;
218}
219
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000220void GrDrawTarget::releasePreviousVertexSource() {
221 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
222 switch (geoSrc.fVertexSrc) {
223 case kNone_GeometrySrcType:
224 break;
225 case kArray_GeometrySrcType:
226 this->releaseVertexArray();
227 break;
228 case kReserved_GeometrySrcType:
229 this->releaseReservedVertexSpace();
230 break;
231 case kBuffer_GeometrySrcType:
232 geoSrc.fVertexBuffer->unref();
233#if GR_DEBUG
234 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
235#endif
236 break;
237 default:
238 GrCrash("Unknown Vertex Source Type.");
239 break;
240 }
241}
242
243void GrDrawTarget::releasePreviousIndexSource() {
244 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
245 switch (geoSrc.fIndexSrc) {
246 case kNone_GeometrySrcType: // these two don't require
247 break;
248 case kArray_GeometrySrcType:
249 this->releaseIndexArray();
250 break;
251 case kReserved_GeometrySrcType:
252 this->releaseReservedIndexSpace();
253 break;
254 case kBuffer_GeometrySrcType:
255 geoSrc.fIndexBuffer->unref();
256#if GR_DEBUG
257 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
258#endif
259 break;
260 default:
261 GrCrash("Unknown Index Source Type.");
262 break;
263 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000264}
265
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000266void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000267 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000268 this->releasePreviousVertexSource();
269 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
270 geoSrc.fVertexSrc = kArray_GeometrySrcType;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000271 geoSrc.fVertexSize = this->drawState()->getVertexSize();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000272 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000273 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000274}
275
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000276void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
277 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000278 this->releasePreviousIndexSource();
279 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
280 geoSrc.fIndexSrc = kArray_GeometrySrcType;
281 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000282 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000283}
284
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000285void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000286 this->releasePreviousVertexSource();
287 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
288 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
289 geoSrc.fVertexBuffer = buffer;
290 buffer->ref();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000291 geoSrc.fVertexSize = this->drawState()->getVertexSize();
reed@google.comac10a2d2010-12-22 21:39:39 +0000292}
293
294void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000295 this->releasePreviousIndexSource();
296 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
297 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
298 geoSrc.fIndexBuffer = buffer;
299 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000300}
301
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000302void GrDrawTarget::resetVertexSource() {
303 this->releasePreviousVertexSource();
304 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
305 geoSrc.fVertexSrc = kNone_GeometrySrcType;
306}
307
308void GrDrawTarget::resetIndexSource() {
309 this->releasePreviousIndexSource();
310 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
311 geoSrc.fIndexSrc = kNone_GeometrySrcType;
312}
313
314void GrDrawTarget::pushGeometrySource() {
315 this->geometrySourceWillPush();
316 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
317 newState.fIndexSrc = kNone_GeometrySrcType;
318 newState.fVertexSrc = kNone_GeometrySrcType;
319#if GR_DEBUG
320 newState.fVertexCount = ~0;
321 newState.fVertexBuffer = (GrVertexBuffer*)~0;
322 newState.fIndexCount = ~0;
323 newState.fIndexBuffer = (GrIndexBuffer*)~0;
324#endif
325}
326
327void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000328 // if popping last element then pops are unbalanced with pushes
329 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000330
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000331 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
332 this->releasePreviousVertexSource();
333 this->releasePreviousIndexSource();
334 fGeoSrcStateStack.pop_back();
335}
336
337////////////////////////////////////////////////////////////////////////////////
338
bsalomon@google.come8262622011-11-07 02:30:51 +0000339bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
340 int startIndex, int vertexCount,
341 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000342 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000343#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000344 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000345 int maxVertex = startVertex + vertexCount;
346 int maxValidVertex;
347 switch (geoSrc.fVertexSrc) {
348 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000349 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000350 case kReserved_GeometrySrcType: // fallthrough
351 case kArray_GeometrySrcType:
352 maxValidVertex = geoSrc.fVertexCount;
353 break;
354 case kBuffer_GeometrySrcType:
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000355 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000356 break;
357 }
358 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000359 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000360 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000361 if (indexCount > 0) {
362 int maxIndex = startIndex + indexCount;
363 int maxValidIndex;
364 switch (geoSrc.fIndexSrc) {
365 case kNone_GeometrySrcType:
366 GrCrash("Attempting to draw indexed geom without index src.");
367 case kReserved_GeometrySrcType: // fallthrough
368 case kArray_GeometrySrcType:
369 maxValidIndex = geoSrc.fIndexCount;
370 break;
371 case kBuffer_GeometrySrcType:
372 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
373 break;
374 }
375 if (maxIndex > maxValidIndex) {
376 GrCrash("Index reads outside valid index range.");
377 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000378 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000379
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000380 GrAssert(NULL != drawState.getRenderTarget());
381 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
382 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000383 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000384 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000385 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000386 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000387 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
388 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000389 }
390 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000391#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000392 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000393 return false;
394 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000395 return true;
396}
397
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000398void GrDrawTarget::drawIndexed(GrPrimitiveType type,
399 int startVertex,
400 int startIndex,
401 int vertexCount,
402 int indexCount,
403 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000404 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
405 DrawInfo info;
406 info.fPrimitiveType = type;
407 info.fStartVertex = startVertex;
408 info.fStartIndex = startIndex;
409 info.fVertexCount = vertexCount;
410 info.fIndexCount = indexCount;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000411
412 info.fInstanceCount = 0;
413 info.fVerticesPerInstance = 0;
414 info.fIndicesPerInstance = 0;
415
416 if (NULL != devBounds) {
417 info.setDevBounds(*devBounds);
418 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000419 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000420 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000421}
422
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000423void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
424 int startVertex,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000425 int vertexCount,
426 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000427 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
428 DrawInfo info;
429 info.fPrimitiveType = type;
430 info.fStartVertex = startVertex;
431 info.fStartIndex = 0;
432 info.fVertexCount = vertexCount;
433 info.fIndexCount = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000434
435 info.fInstanceCount = 0;
436 info.fVerticesPerInstance = 0;
437 info.fIndicesPerInstance = 0;
438
439 if (NULL != devBounds) {
440 info.setDevBounds(*devBounds);
441 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000442 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000443 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000444}
445
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000446void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000447 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000448 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000449 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000450 GrAssert(!stroke.isHairlineStyle());
451 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000452 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000453}
454
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000455////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000456
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000457bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000458 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
459 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
460 // our alpha is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000461 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000462 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000463 return false;
464 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000465 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
466 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
467 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000468}
469
470bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000471 // we can correctly apply coverage if a) we have dual source blending
472 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000473 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000474 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000475}
476
bsalomon@google.com934c5702012-03-20 21:17:58 +0000477////////////////////////////////////////////////////////////////////////////////
478
479void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
480 int instanceCount,
481 int verticesPerInstance,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000482 int indicesPerInstance,
483 const SkRect* devBounds) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000484 if (!verticesPerInstance || !indicesPerInstance) {
485 return;
486 }
487
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000488 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
489 if (!maxInstancesPerDraw) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000490 return;
491 }
492
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000493 DrawInfo info;
494 info.fPrimitiveType = type;
495 info.fStartIndex = 0;
496 info.fStartVertex = 0;
497 info.fIndicesPerInstance = indicesPerInstance;
498 info.fVerticesPerInstance = verticesPerInstance;
499
500 // Set the same bounds for all the draws.
501 if (NULL != devBounds) {
502 info.setDevBounds(*devBounds);
503 }
504
bsalomon@google.com934c5702012-03-20 21:17:58 +0000505 while (instanceCount) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000506 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
507 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
508 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
509
510 if (this->checkDraw(type,
511 info.fStartVertex,
512 info.fStartIndex,
513 info.fVertexCount,
514 info.fIndexCount)) {
515 this->onDraw(info);
516 }
517 info.fStartVertex += info.fVertexCount;
518 instanceCount -= info.fInstanceCount;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000519 }
520}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000521
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000522////////////////////////////////////////////////////////////////////////////////
523
rmistry@google.comd6176b02012-08-23 18:14:13 +0000524void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000525 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000526 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000527 const SkMatrix* srcMatrices[]) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000528 GrVertexLayout layout = 0;
529 uint32_t explicitCoordMask = 0;
530
531 if (NULL != srcRects) {
532 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
533 int numTC = 0;
534 if (NULL != srcRects[s]) {
535 layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
536 explicitCoordMask |= (1 << s);
537 ++numTC;
538 }
539 }
540 }
541
542 GrDrawState::AutoViewMatrixRestore avmr;
543 if (NULL != matrix) {
544 avmr.set(this->drawState(), *matrix, explicitCoordMask);
545 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000546
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000547 this->drawState()->setVertexLayout(layout);
548 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000549 if (!geo.succeeded()) {
550 GrPrintf("Failed to get space for vertices!\n");
551 return;
552 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000553
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000554 int stageOffsets[GrDrawState::kNumStages];
555 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, NULL, NULL, NULL);
556 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000557
tomhudson@google.com93813632011-10-27 20:21:16 +0000558 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000559 if (explicitCoordMask & (1 << i)) {
reed@google.com009dfe22013-02-01 15:05:18 +0000560 GrAssert(0 != stageOffsets[i]);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000561 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000562 stageOffsets[i]);
563 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000564 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000565 vsize);
566 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
567 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
568 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000569 } else {
reed@google.com009dfe22013-02-01 15:05:18 +0000570 GrAssert(0 == stageOffsets[i]);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000571 }
572 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000573
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000574 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000575}
576
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000577void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
578}
579
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000580////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000581
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000582GrDrawTarget::AutoStateRestore::AutoStateRestore() {
583 fDrawTarget = NULL;
584}
reed@google.comac10a2d2010-12-22 21:39:39 +0000585
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000586GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
587 ASRInit init) {
588 fDrawTarget = NULL;
589 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000590}
591
592GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000593 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000594 fDrawTarget->setDrawState(fSavedState);
595 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000596 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000597}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000598
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000599void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
600 GrAssert(NULL == fDrawTarget);
601 fDrawTarget = target;
602 fSavedState = target->drawState();
603 GrAssert(fSavedState);
604 fSavedState->ref();
605 if (kReset_ASRInit == init) {
606 // calls the default cons
607 fTempState.init();
608 } else {
609 GrAssert(kPreserve_ASRInit == init);
610 // calls the copy cons
611 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000612 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000613 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000614}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000615
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000616////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000617
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000618GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
619 GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000620 int vertexCount,
621 int indexCount) {
622 fTarget = NULL;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000623 this->set(target, vertexCount, indexCount);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000624}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000625
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000626GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
627 fTarget = NULL;
628}
629
630GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
631 this->reset();
632}
633
634bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000635 int vertexCount,
636 int indexCount) {
637 this->reset();
638 fTarget = target;
639 bool success = true;
640 if (NULL != fTarget) {
641 fTarget = target;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000642 success = target->reserveVertexAndIndexSpace(vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000643 indexCount,
644 &fVertices,
645 &fIndices);
646 if (!success) {
647 fTarget = NULL;
648 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000649 }
650 }
651 GrAssert(success == (NULL != fTarget));
652 return success;
653}
654
655void GrDrawTarget::AutoReleaseGeometry::reset() {
656 if (NULL != fTarget) {
657 if (NULL != fVertices) {
658 fTarget->resetVertexSource();
659 }
660 if (NULL != fIndices) {
661 fTarget->resetIndexSource();
662 }
663 fTarget = NULL;
664 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000665 fVertices = NULL;
666 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000667}
668
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000669GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
670 fTarget = target;
671 fClip = fTarget->getClip();
672 fStack.init();
673 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
674 fReplacementClip.fClipStack = fStack.get();
675 target->setClip(&fReplacementClip);
676}
677
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000678void GrDrawTarget::Caps::print() const {
679 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000680 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
681 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
682 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
683 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
684 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
685 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
686 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
687 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
688 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
689 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
690 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
691 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
692 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000693}