blob: 6fdc3a080fd8759a33fe8052e2cae4bf252dee40 [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,
reed@google.com67e7cde2013-03-20 17:47:16 +0000532 const GrRect* srcRect,
533 const SkMatrix* srcMatrix,
534 int stage) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000535 GrAttribBindings bindings = 0;
reed@google.com67e7cde2013-03-20 17:47:16 +0000536 uint32_t explicitCoordMask = 0;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000537 // position + (optional) texture coord
538 static const GrVertexAttrib kAttribs[] = {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000539 {kVec2f_GrVertexAttribType, 0},
540 {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000541 };
542 int attribCount = 1;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000543
reed@google.com67e7cde2013-03-20 17:47:16 +0000544 if (NULL != srcRect) {
545 bindings |= GrDrawState::ExplicitTexCoordAttribBindingsBit(stage);
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000546 attribCount = 2;
reed@google.com67e7cde2013-03-20 17:47:16 +0000547 this->drawState()->setAttribIndex(GrDrawState::kTexCoord_AttribIndex, 1);
548 explicitCoordMask = (1 << stage);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000549 }
550
551 GrDrawState::AutoViewMatrixRestore avmr;
552 if (NULL != matrix) {
reed@google.com67e7cde2013-03-20 17:47:16 +0000553 avmr.set(this->drawState(), *matrix, explicitCoordMask);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000554 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000555
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000556 this->drawState()->setVertexAttribs(kAttribs, attribCount);
557 this->drawState()->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
558 this->drawState()->setAttribBindings(bindings);
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000559 AutoReleaseGeometry geo(this, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000560 if (!geo.succeeded()) {
561 GrPrintf("Failed to get space for vertices!\n");
562 return;
563 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000564
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000565 size_t vsize = this->drawState()->getVertexSize();
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000566 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
reed@google.com67e7cde2013-03-20 17:47:16 +0000567 if (NULL != srcRect) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000568 GrAssert(attribCount == 2);
569 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
570 kAttribs[1].fOffset);
reed@google.com67e7cde2013-03-20 17:47:16 +0000571 coords->setRectFan(srcRect->fLeft, srcRect->fTop,
572 srcRect->fRight, srcRect->fBottom,
573 vsize);
574 if (NULL != srcMatrix) {
575 srcMatrix->mapPointsWithStride(coords, vsize, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000576 }
577 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000578
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000579 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000580}
581
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000582void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
583}
584
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000585////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000586
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000587GrDrawTarget::AutoStateRestore::AutoStateRestore() {
588 fDrawTarget = NULL;
589}
reed@google.comac10a2d2010-12-22 21:39:39 +0000590
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000591GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
592 ASRInit init) {
593 fDrawTarget = NULL;
594 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000595}
596
597GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000598 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000599 fDrawTarget->setDrawState(fSavedState);
600 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000601 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000602}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000603
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000604void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
605 GrAssert(NULL == fDrawTarget);
606 fDrawTarget = target;
607 fSavedState = target->drawState();
608 GrAssert(fSavedState);
609 fSavedState->ref();
610 if (kReset_ASRInit == init) {
611 // calls the default cons
612 fTempState.init();
613 } else {
614 GrAssert(kPreserve_ASRInit == init);
615 // calls the copy cons
616 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000617 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000618 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000619}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000620
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000621////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000622
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000623GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
624 GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000625 int vertexCount,
626 int indexCount) {
627 fTarget = NULL;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000628 this->set(target, vertexCount, indexCount);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000629}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000630
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000631GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
632 fTarget = NULL;
633}
634
635GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
636 this->reset();
637}
638
639bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000640 int vertexCount,
641 int indexCount) {
642 this->reset();
643 fTarget = target;
644 bool success = true;
645 if (NULL != fTarget) {
646 fTarget = target;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000647 success = target->reserveVertexAndIndexSpace(vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000648 indexCount,
649 &fVertices,
650 &fIndices);
651 if (!success) {
652 fTarget = NULL;
653 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000654 }
655 }
656 GrAssert(success == (NULL != fTarget));
657 return success;
658}
659
660void GrDrawTarget::AutoReleaseGeometry::reset() {
661 if (NULL != fTarget) {
662 if (NULL != fVertices) {
663 fTarget->resetVertexSource();
664 }
665 if (NULL != fIndices) {
666 fTarget->resetIndexSource();
667 }
668 fTarget = NULL;
669 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000670 fVertices = NULL;
671 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000672}
673
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000674GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
675 fTarget = target;
676 fClip = fTarget->getClip();
677 fStack.init();
678 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
679 fReplacementClip.fClipStack = fStack.get();
680 target->setClip(&fReplacementClip);
681}
682
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000683void GrDrawTarget::Caps::print() const {
684 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000685 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
686 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
687 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
688 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
689 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
690 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
691 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
692 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
693 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
694 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
695 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
696 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
697 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000698}