blob: cd4d4d2007f853d33b8ac1c681ce63d18fd4da75 [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 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000395
396 GrAssert(drawState.validateVertexAttribs());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000397#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000398 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000399 return false;
400 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000401 return true;
402}
403
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000404void GrDrawTarget::drawIndexed(GrPrimitiveType type,
405 int startVertex,
406 int startIndex,
407 int vertexCount,
408 int indexCount,
409 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000410 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
411 DrawInfo info;
412 info.fPrimitiveType = type;
413 info.fStartVertex = startVertex;
414 info.fStartIndex = startIndex;
415 info.fVertexCount = vertexCount;
416 info.fIndexCount = indexCount;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000417
418 info.fInstanceCount = 0;
419 info.fVerticesPerInstance = 0;
420 info.fIndicesPerInstance = 0;
421
422 if (NULL != devBounds) {
423 info.setDevBounds(*devBounds);
424 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000425 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000426 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000427}
428
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000429void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
430 int startVertex,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000431 int vertexCount,
432 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000433 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
434 DrawInfo info;
435 info.fPrimitiveType = type;
436 info.fStartVertex = startVertex;
437 info.fStartIndex = 0;
438 info.fVertexCount = vertexCount;
439 info.fIndexCount = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000440
441 info.fInstanceCount = 0;
442 info.fVerticesPerInstance = 0;
443 info.fIndicesPerInstance = 0;
444
445 if (NULL != devBounds) {
446 info.setDevBounds(*devBounds);
447 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000448 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000449 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000450}
451
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000452void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000453 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000454 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000455 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000456 GrAssert(!stroke.isHairlineStyle());
457 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000458 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000459}
460
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000461////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000462
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000463bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000464 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
465 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
466 // our alpha is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000467 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000468 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000469 return false;
470 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000471 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
472 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
473 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000474}
475
476bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000477 // we can correctly apply coverage if a) we have dual source blending
478 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000479 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000480 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000481}
482
bsalomon@google.com934c5702012-03-20 21:17:58 +0000483////////////////////////////////////////////////////////////////////////////////
484
485void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
486 int instanceCount,
487 int verticesPerInstance,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000488 int indicesPerInstance,
489 const SkRect* devBounds) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000490 if (!verticesPerInstance || !indicesPerInstance) {
491 return;
492 }
493
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000494 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
495 if (!maxInstancesPerDraw) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000496 return;
497 }
498
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000499 DrawInfo info;
500 info.fPrimitiveType = type;
501 info.fStartIndex = 0;
502 info.fStartVertex = 0;
503 info.fIndicesPerInstance = indicesPerInstance;
504 info.fVerticesPerInstance = verticesPerInstance;
505
506 // Set the same bounds for all the draws.
507 if (NULL != devBounds) {
508 info.setDevBounds(*devBounds);
509 }
510
bsalomon@google.com934c5702012-03-20 21:17:58 +0000511 while (instanceCount) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000512 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
513 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
514 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
515
516 if (this->checkDraw(type,
517 info.fStartVertex,
518 info.fStartIndex,
519 info.fVertexCount,
520 info.fIndexCount)) {
521 this->onDraw(info);
522 }
523 info.fStartVertex += info.fVertexCount;
524 instanceCount -= info.fInstanceCount;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000525 }
526}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000527
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000528////////////////////////////////////////////////////////////////////////////////
529
rmistry@google.comd6176b02012-08-23 18:14:13 +0000530void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000531 const SkMatrix* matrix,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000532 const GrRect* localRect,
533 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000534 GrAttribBindings bindings = 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
bsalomon@google.comc7818882013-03-20 19:19:53 +0000542 if (NULL != localRect) {
543 bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000544 attribCount = 2;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000545 this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000546 }
547
548 GrDrawState::AutoViewMatrixRestore avmr;
549 if (NULL != matrix) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000550 avmr.set(this->drawState(), *matrix);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000551 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000552
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000553 this->drawState()->setVertexAttribs(kAttribs, attribCount);
554 this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
555 this->drawState()->setAttribBindings(bindings);
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000556 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000557 if (!geo.succeeded()) {
558 GrPrintf("Failed to get space for vertices!\n");
559 return;
560 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000561
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000562 size_t vsize = this->drawState()->getVertexSize();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000563 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000564 if (NULL != localRect) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000565 GrAssert(attribCount == 2);
566 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
567 kAttribs[1].fOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000568 coords->setRectFan(localRect->fLeft, localRect->fTop,
569 localRect->fRight, localRect->fBottom,
570 vsize);
571 if (NULL != localMatrix) {
572 localMatrix->mapPointsWithStride(coords, vsize, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000573 }
574 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000575
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000576 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000577}
578
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000579void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
580}
581
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000582////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000583
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000584GrDrawTarget::AutoStateRestore::AutoStateRestore() {
585 fDrawTarget = NULL;
586}
reed@google.comac10a2d2010-12-22 21:39:39 +0000587
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000588GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
589 ASRInit init) {
590 fDrawTarget = NULL;
591 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000592}
593
594GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000595 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000596 fDrawTarget->setDrawState(fSavedState);
597 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000598 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000599}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000600
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000601void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
602 GrAssert(NULL == fDrawTarget);
603 fDrawTarget = target;
604 fSavedState = target->drawState();
605 GrAssert(fSavedState);
606 fSavedState->ref();
607 if (kReset_ASRInit == init) {
608 // calls the default cons
609 fTempState.init();
610 } else {
611 GrAssert(kPreserve_ASRInit == init);
612 // calls the copy cons
613 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000614 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000615 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000616}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000617
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000618////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000619
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000620GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
621 GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000622 int vertexCount,
623 int indexCount) {
624 fTarget = NULL;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000625 this->set(target, vertexCount, indexCount);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000626}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000627
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000628GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
629 fTarget = NULL;
630}
631
632GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
633 this->reset();
634}
635
636bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000637 int vertexCount,
638 int indexCount) {
639 this->reset();
640 fTarget = target;
641 bool success = true;
642 if (NULL != fTarget) {
643 fTarget = target;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000644 success = target->reserveVertexAndIndexSpace(vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000645 indexCount,
646 &fVertices,
647 &fIndices);
648 if (!success) {
649 fTarget = NULL;
650 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651 }
652 }
653 GrAssert(success == (NULL != fTarget));
654 return success;
655}
656
657void GrDrawTarget::AutoReleaseGeometry::reset() {
658 if (NULL != fTarget) {
659 if (NULL != fVertices) {
660 fTarget->resetVertexSource();
661 }
662 if (NULL != fIndices) {
663 fTarget->resetIndexSource();
664 }
665 fTarget = NULL;
666 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000667 fVertices = NULL;
668 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000669}
670
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000671GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
672 fTarget = target;
673 fClip = fTarget->getClip();
674 fStack.init();
675 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
676 fReplacementClip.fClipStack = fStack.get();
677 target->setClip(&fReplacementClip);
678}
679
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000680void GrDrawTarget::Caps::print() const {
681 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000682 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
683 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
684 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
685 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
686 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
687 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
688 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
689 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
690 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
691 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
692 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
693 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
694 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000695}