blob: 954a4e7687de0339abcf6c317fb643ee0654f4af [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
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000085GrDrawTarget::GrDrawTarget(GrContext* context)
86 : fClip(NULL)
87 , fContext(context) {
88 GrAssert(NULL != context);
89
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000090 fDrawState = &fDefaultDrawState;
91 // We assume that fDrawState always owns a ref to the object it points at.
92 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000093 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000094#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000095 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
96 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
97 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
98 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +000099#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000100 geoSrc.fVertexSrc = kNone_GeometrySrcType;
101 geoSrc.fIndexSrc = kNone_GeometrySrcType;
102}
103
104GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000105 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +0000106 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000107 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
108 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000109 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000110}
111
112void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000113 int popCnt = fGeoSrcStateStack.count() - 1;
114 while (popCnt) {
115 this->popGeometrySource();
116 --popCnt;
117 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000118 this->resetVertexSource();
119 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000120}
121
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000122void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000123 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 fClip = clip;
125}
126
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000127const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000128 return fClip;
129}
130
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000131void GrDrawTarget::setDrawState(GrDrawState* drawState) {
132 GrAssert(NULL != fDrawState);
133 if (NULL == drawState) {
134 drawState = &fDefaultDrawState;
135 }
136 if (fDrawState != drawState) {
137 fDrawState->unref();
138 drawState->ref();
139 fDrawState = drawState;
140 }
141}
142
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000143bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000144 int vertexCount,
145 void** vertices) {
146 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
147 bool acquired = false;
148 if (vertexCount > 0) {
149 GrAssert(NULL != vertices);
150 this->releasePreviousVertexSource();
151 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000152
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000153 acquired = this->onReserveVertexSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000154 vertexCount,
155 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000156 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000157 if (acquired) {
158 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
159 geoSrc.fVertexCount = vertexCount;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000160 geoSrc.fVertexSize = vertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000161 } else if (NULL != vertices) {
162 *vertices = NULL;
163 }
164 return acquired;
165}
166
167bool GrDrawTarget::reserveIndexSpace(int indexCount,
168 void** indices) {
169 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
170 bool acquired = false;
171 if (indexCount > 0) {
172 GrAssert(NULL != indices);
173 this->releasePreviousIndexSource();
174 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000175
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000176 acquired = this->onReserveIndexSpace(indexCount, indices);
177 }
178 if (acquired) {
179 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
180 geoSrc.fIndexCount = indexCount;
181 } else if (NULL != indices) {
182 *indices = NULL;
183 }
184 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000185
reed@google.comac10a2d2010-12-22 21:39:39 +0000186}
187
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000188bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000189 int indexCount,
190 void** vertices,
191 void** indices) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000192 size_t vertexSize = this->drawState()->getVertexSize();
193 this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000194 if (vertexCount) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000195 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
bsalomon@google.come3d70952012-03-13 12:40:53 +0000196 if (indexCount) {
197 this->resetIndexSource();
198 }
199 return false;
200 }
201 }
202 if (indexCount) {
203 if (!this->reserveIndexSpace(indexCount, indices)) {
204 if (vertexCount) {
205 this->resetVertexSource();
206 }
207 return false;
208 }
209 }
210 return true;
211}
212
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000213bool GrDrawTarget::geometryHints(int32_t* vertexCount,
reed@google.comac10a2d2010-12-22 21:39:39 +0000214 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 if (NULL != vertexCount) {
216 *vertexCount = -1;
217 }
218 if (NULL != indexCount) {
219 *indexCount = -1;
220 }
221 return false;
222}
223
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000224void GrDrawTarget::releasePreviousVertexSource() {
225 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
226 switch (geoSrc.fVertexSrc) {
227 case kNone_GeometrySrcType:
228 break;
229 case kArray_GeometrySrcType:
230 this->releaseVertexArray();
231 break;
232 case kReserved_GeometrySrcType:
233 this->releaseReservedVertexSpace();
234 break;
235 case kBuffer_GeometrySrcType:
236 geoSrc.fVertexBuffer->unref();
237#if GR_DEBUG
238 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
239#endif
240 break;
241 default:
242 GrCrash("Unknown Vertex Source Type.");
243 break;
244 }
245}
246
247void GrDrawTarget::releasePreviousIndexSource() {
248 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
249 switch (geoSrc.fIndexSrc) {
250 case kNone_GeometrySrcType: // these two don't require
251 break;
252 case kArray_GeometrySrcType:
253 this->releaseIndexArray();
254 break;
255 case kReserved_GeometrySrcType:
256 this->releaseReservedIndexSpace();
257 break;
258 case kBuffer_GeometrySrcType:
259 geoSrc.fIndexBuffer->unref();
260#if GR_DEBUG
261 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
262#endif
263 break;
264 default:
265 GrCrash("Unknown Index Source Type.");
266 break;
267 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000268}
269
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000270void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000271 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000272 this->releasePreviousVertexSource();
273 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
274 geoSrc.fVertexSrc = kArray_GeometrySrcType;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000275 geoSrc.fVertexSize = this->drawState()->getVertexSize();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000276 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000277 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000278}
279
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000280void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
281 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000282 this->releasePreviousIndexSource();
283 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
284 geoSrc.fIndexSrc = kArray_GeometrySrcType;
285 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000286 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000287}
288
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000289void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000290 this->releasePreviousVertexSource();
291 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
292 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
293 geoSrc.fVertexBuffer = buffer;
294 buffer->ref();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000295 geoSrc.fVertexSize = this->drawState()->getVertexSize();
reed@google.comac10a2d2010-12-22 21:39:39 +0000296}
297
298void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000299 this->releasePreviousIndexSource();
300 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
301 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
302 geoSrc.fIndexBuffer = buffer;
303 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000304}
305
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000306void GrDrawTarget::resetVertexSource() {
307 this->releasePreviousVertexSource();
308 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
309 geoSrc.fVertexSrc = kNone_GeometrySrcType;
310}
311
312void GrDrawTarget::resetIndexSource() {
313 this->releasePreviousIndexSource();
314 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
315 geoSrc.fIndexSrc = kNone_GeometrySrcType;
316}
317
318void GrDrawTarget::pushGeometrySource() {
319 this->geometrySourceWillPush();
320 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
321 newState.fIndexSrc = kNone_GeometrySrcType;
322 newState.fVertexSrc = kNone_GeometrySrcType;
323#if GR_DEBUG
324 newState.fVertexCount = ~0;
325 newState.fVertexBuffer = (GrVertexBuffer*)~0;
326 newState.fIndexCount = ~0;
327 newState.fIndexBuffer = (GrIndexBuffer*)~0;
328#endif
329}
330
331void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000332 // if popping last element then pops are unbalanced with pushes
333 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000334
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000335 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
336 this->releasePreviousVertexSource();
337 this->releasePreviousIndexSource();
338 fGeoSrcStateStack.pop_back();
339}
340
341////////////////////////////////////////////////////////////////////////////////
342
bsalomon@google.come8262622011-11-07 02:30:51 +0000343bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
344 int startIndex, int vertexCount,
345 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000346 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000347#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000348 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000349 int maxVertex = startVertex + vertexCount;
350 int maxValidVertex;
351 switch (geoSrc.fVertexSrc) {
352 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000353 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000354 case kReserved_GeometrySrcType: // fallthrough
355 case kArray_GeometrySrcType:
356 maxValidVertex = geoSrc.fVertexCount;
357 break;
358 case kBuffer_GeometrySrcType:
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000359 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000360 break;
361 }
362 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000363 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000364 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000365 if (indexCount > 0) {
366 int maxIndex = startIndex + indexCount;
367 int maxValidIndex;
368 switch (geoSrc.fIndexSrc) {
369 case kNone_GeometrySrcType:
370 GrCrash("Attempting to draw indexed geom without index src.");
371 case kReserved_GeometrySrcType: // fallthrough
372 case kArray_GeometrySrcType:
373 maxValidIndex = geoSrc.fIndexCount;
374 break;
375 case kBuffer_GeometrySrcType:
376 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
377 break;
378 }
379 if (maxIndex > maxValidIndex) {
380 GrCrash("Index reads outside valid index range.");
381 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000382 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000383
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000384 GrAssert(NULL != drawState.getRenderTarget());
385 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
386 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000387 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000388 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000389 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000390 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000391 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
392 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000393 }
394 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000395#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000396 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000397 return false;
398 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000399 return true;
400}
401
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000402void GrDrawTarget::drawIndexed(GrPrimitiveType type,
403 int startVertex,
404 int startIndex,
405 int vertexCount,
406 int indexCount,
407 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000408 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
409 DrawInfo info;
410 info.fPrimitiveType = type;
411 info.fStartVertex = startVertex;
412 info.fStartIndex = startIndex;
413 info.fVertexCount = vertexCount;
414 info.fIndexCount = indexCount;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000415
416 info.fInstanceCount = 0;
417 info.fVerticesPerInstance = 0;
418 info.fIndicesPerInstance = 0;
419
420 if (NULL != devBounds) {
421 info.setDevBounds(*devBounds);
422 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000423 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000424 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000425}
426
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000427void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
428 int startVertex,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000429 int vertexCount,
430 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000431 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
432 DrawInfo info;
433 info.fPrimitiveType = type;
434 info.fStartVertex = startVertex;
435 info.fStartIndex = 0;
436 info.fVertexCount = vertexCount;
437 info.fIndexCount = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000438
439 info.fInstanceCount = 0;
440 info.fVerticesPerInstance = 0;
441 info.fIndicesPerInstance = 0;
442
443 if (NULL != devBounds) {
444 info.setDevBounds(*devBounds);
445 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000446 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000447 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000448}
449
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000450void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000451 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000452 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000453 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000454 GrAssert(!stroke.isHairlineStyle());
455 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000456 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000457}
458
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000459////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000460
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000461bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000462 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
463 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
464 // our alpha is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000465 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000466 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000467 return false;
468 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000469 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
470 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
471 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000472}
473
474bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000475 // we can correctly apply coverage if a) we have dual source blending
476 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000477 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000478 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000479}
480
bsalomon@google.com934c5702012-03-20 21:17:58 +0000481////////////////////////////////////////////////////////////////////////////////
482
483void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
484 int instanceCount,
485 int verticesPerInstance,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000486 int indicesPerInstance,
487 const SkRect* devBounds) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000488 if (!verticesPerInstance || !indicesPerInstance) {
489 return;
490 }
491
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000492 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
493 if (!maxInstancesPerDraw) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000494 return;
495 }
496
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000497 DrawInfo info;
498 info.fPrimitiveType = type;
499 info.fStartIndex = 0;
500 info.fStartVertex = 0;
501 info.fIndicesPerInstance = indicesPerInstance;
502 info.fVerticesPerInstance = verticesPerInstance;
503
504 // Set the same bounds for all the draws.
505 if (NULL != devBounds) {
506 info.setDevBounds(*devBounds);
507 }
508
bsalomon@google.com934c5702012-03-20 21:17:58 +0000509 while (instanceCount) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000510 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
511 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
512 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
513
514 if (this->checkDraw(type,
515 info.fStartVertex,
516 info.fStartIndex,
517 info.fVertexCount,
518 info.fIndexCount)) {
519 this->onDraw(info);
520 }
521 info.fStartVertex += info.fVertexCount;
522 instanceCount -= info.fInstanceCount;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000523 }
524}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000525
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000526////////////////////////////////////////////////////////////////////////////////
527
rmistry@google.comd6176b02012-08-23 18:14:13 +0000528void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000529 const SkMatrix* matrix,
jvanverth@google.com39768252013-02-14 15:25:44 +0000530 const GrRect* srcRect,
531 const SkMatrix* srcMatrix,
532 int stage) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000533 GrAttribBindings bindings = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000534 uint32_t explicitCoordMask = 0;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000535 // position + (optional) texture coord
536 static const GrVertexAttrib kAttribs[] = {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000537 {kVec2f_GrVertexAttribType, 0},
538 {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000539 };
540 int attribCount = 1;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000541
jvanverth@google.com39768252013-02-14 15:25:44 +0000542 if (NULL != srcRect) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000543 bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage);
544 attribCount = 2;
545 this->drawState()->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1);
jvanverth@google.com39768252013-02-14 15:25:44 +0000546 explicitCoordMask = (1 << stage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000547 }
548
549 GrDrawState::AutoViewMatrixRestore avmr;
550 if (NULL != matrix) {
551 avmr.set(this->drawState(), *matrix, explicitCoordMask);
552 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000553
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000554 this->drawState()->setVertexAttribs(kAttribs, attribCount);
555 this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
556 this->drawState()->setAttribBindings(bindings);
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000557 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000558 if (!geo.succeeded()) {
559 GrPrintf("Failed to get space for vertices!\n");
560 return;
561 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000562
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000563 size_t vsize = this->drawState()->getVertexSize();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000564 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000565 if (NULL != srcRect) {
566 GrAssert(attribCount == 2);
567 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
568 kAttribs[1].fOffset);
569 coords->setRectFan(srcRect->fLeft, srcRect->fTop,
570 srcRect->fRight, srcRect->fBottom,
571 vsize);
572 if (NULL != srcMatrix) {
573 srcMatrix->mapPointsWithStride(coords, vsize, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000574 }
575 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000576
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000577 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000578}
579
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000580void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
581}
582
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000583////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000584
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000585GrDrawTarget::AutoStateRestore::AutoStateRestore() {
586 fDrawTarget = NULL;
587}
reed@google.comac10a2d2010-12-22 21:39:39 +0000588
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000589GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
590 ASRInit init) {
591 fDrawTarget = NULL;
592 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000593}
594
595GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000596 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000597 fDrawTarget->setDrawState(fSavedState);
598 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000599 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000600}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000601
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000602void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
603 GrAssert(NULL == fDrawTarget);
604 fDrawTarget = target;
605 fSavedState = target->drawState();
606 GrAssert(fSavedState);
607 fSavedState->ref();
608 if (kReset_ASRInit == init) {
609 // calls the default cons
610 fTempState.init();
611 } else {
612 GrAssert(kPreserve_ASRInit == init);
613 // calls the copy cons
614 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000615 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000616 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000617}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000618
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000619////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000620
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000621GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
622 GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000623 int vertexCount,
624 int indexCount) {
625 fTarget = NULL;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000626 this->set(target, vertexCount, indexCount);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000627}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000628
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000629GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
630 fTarget = NULL;
631}
632
633GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
634 this->reset();
635}
636
637bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000638 int vertexCount,
639 int indexCount) {
640 this->reset();
641 fTarget = target;
642 bool success = true;
643 if (NULL != fTarget) {
644 fTarget = target;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000645 success = target->reserveVertexAndIndexSpace(vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000646 indexCount,
647 &fVertices,
648 &fIndices);
649 if (!success) {
650 fTarget = NULL;
651 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000652 }
653 }
654 GrAssert(success == (NULL != fTarget));
655 return success;
656}
657
658void GrDrawTarget::AutoReleaseGeometry::reset() {
659 if (NULL != fTarget) {
660 if (NULL != fVertices) {
661 fTarget->resetVertexSource();
662 }
663 if (NULL != fIndices) {
664 fTarget->resetIndexSource();
665 }
666 fTarget = NULL;
667 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000668 fVertices = NULL;
669 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000670}
671
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000672GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
673 fTarget = target;
674 fClip = fTarget->getClip();
675 fStack.init();
676 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
677 fReplacementClip.fClipStack = fStack.get();
678 target->setClip(&fReplacementClip);
679}
680
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000681void GrDrawTarget::Caps::print() const {
682 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000683 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
684 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
685 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
686 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
687 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
688 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
689 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
690 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
691 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
692 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
693 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
694 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
695 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000696}