blob: 64576afb7d50183223d7aad43c814397a9c68939 [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.comc26d94f2013-03-25 18:19:00 +000012#include "GrDrawTargetCaps.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000014#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000015#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
sugoi@google.com5f74cf82012-12-17 21:16:45 +000017#include "SkStrokeRec.h"
sugoi@google.com12b4e272012-12-06 20:13:11 +000018
reed@google.comfa35e3d2012-06-26 20:16:17 +000019SK_DEFINE_INST_COUNT(GrDrawTarget)
20
reed@google.comac10a2d2010-12-22 21:39:39 +000021////////////////////////////////////////////////////////////////////////////////
22
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000023GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
24 fPrimitiveType = di.fPrimitiveType;
25 fStartVertex = di.fStartVertex;
26 fStartIndex = di.fStartIndex;
27 fVertexCount = di.fVertexCount;
28 fIndexCount = di.fIndexCount;
29
30 fInstanceCount = di.fInstanceCount;
31 fVerticesPerInstance = di.fVerticesPerInstance;
32 fIndicesPerInstance = di.fIndicesPerInstance;
33
34 if (NULL != di.fDevBounds) {
35 GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
36 fDevBoundsStorage = di.fDevBoundsStorage;
37 fDevBounds = &fDevBoundsStorage;
38 } else {
39 fDevBounds = NULL;
40 }
41 return *this;
42}
43
44#if GR_DEBUG
45bool GrDrawTarget::DrawInfo::isInstanced() const {
46 if (fInstanceCount > 0) {
47 GrAssert(0 == fIndexCount % fIndicesPerInstance);
48 GrAssert(0 == fVertexCount % fVerticesPerInstance);
49 GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
50 GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
51 // there is no way to specify a non-zero start index to drawIndexedInstances().
52 GrAssert(0 == fStartIndex);
53 return true;
54 } else {
55 GrAssert(!fVerticesPerInstance);
56 GrAssert(!fIndicesPerInstance);
57 return false;
58 }
59}
60#endif
61
62void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
63 GrAssert(this->isInstanced());
64 GrAssert(instanceOffset + fInstanceCount >= 0);
65 fInstanceCount += instanceOffset;
66 fVertexCount = fVerticesPerInstance * fInstanceCount;
67 fIndexCount = fIndicesPerInstance * fInstanceCount;
68}
69
70void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
71 fStartVertex += vertexOffset;
72 GrAssert(fStartVertex >= 0);
73}
74
75void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
76 GrAssert(this->isIndexed());
77 fStartIndex += indexOffset;
78 GrAssert(fStartIndex >= 0);
79}
80
81////////////////////////////////////////////////////////////////////////////////
82
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000083#define DEBUG_INVAL_BUFFER 0xdeadcafe
84#define DEBUG_INVAL_START_IDX -1
85
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000086GrDrawTarget::GrDrawTarget(GrContext* context)
87 : fClip(NULL)
88 , fContext(context) {
89 GrAssert(NULL != context);
90
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000091 fDrawState = &fDefaultDrawState;
92 // We assume that fDrawState always owns a ref to the object it points at.
93 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000094 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000095#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000096 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
97 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
98 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
99 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000100#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000101 geoSrc.fVertexSrc = kNone_GeometrySrcType;
102 geoSrc.fIndexSrc = kNone_GeometrySrcType;
103}
104
105GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000106 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +0000107 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000108 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
109 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000110 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000111}
112
113void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000114 int popCnt = fGeoSrcStateStack.count() - 1;
115 while (popCnt) {
116 this->popGeometrySource();
117 --popCnt;
118 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000119 this->resetVertexSource();
120 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000121}
122
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000123void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000124 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 fClip = clip;
126}
127
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000128const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000129 return fClip;
130}
131
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000132void GrDrawTarget::setDrawState(GrDrawState* drawState) {
133 GrAssert(NULL != fDrawState);
134 if (NULL == drawState) {
135 drawState = &fDefaultDrawState;
136 }
137 if (fDrawState != drawState) {
138 fDrawState->unref();
139 drawState->ref();
140 fDrawState = drawState;
141 }
142}
143
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000144bool GrDrawTarget::reserveVertexSpace(size_t vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000145 int vertexCount,
146 void** vertices) {
147 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
148 bool acquired = false;
149 if (vertexCount > 0) {
150 GrAssert(NULL != vertices);
151 this->releasePreviousVertexSource();
152 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000153
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000154 acquired = this->onReserveVertexSpace(vertexSize,
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000155 vertexCount,
156 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000157 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000158 if (acquired) {
159 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
160 geoSrc.fVertexCount = vertexCount;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000161 geoSrc.fVertexSize = vertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000162 } else if (NULL != vertices) {
163 *vertices = NULL;
164 }
165 return acquired;
166}
167
168bool GrDrawTarget::reserveIndexSpace(int indexCount,
169 void** indices) {
170 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
171 bool acquired = false;
172 if (indexCount > 0) {
173 GrAssert(NULL != indices);
174 this->releasePreviousIndexSource();
175 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000176
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000177 acquired = this->onReserveIndexSpace(indexCount, indices);
178 }
179 if (acquired) {
180 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
181 geoSrc.fIndexCount = indexCount;
182 } else if (NULL != indices) {
183 *indices = NULL;
184 }
185 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000186
reed@google.comac10a2d2010-12-22 21:39:39 +0000187}
188
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000189bool GrDrawTarget::reserveVertexAndIndexSpace(int vertexCount,
bsalomon@google.come3d70952012-03-13 12:40:53 +0000190 int indexCount,
191 void** vertices,
192 void** indices) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000193 size_t vertexSize = this->drawState()->getVertexSize();
194 this->willReserveVertexAndIndexSpace(vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000195 if (vertexCount) {
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000196 if (!this->reserveVertexSpace(vertexSize, vertexCount, vertices)) {
bsalomon@google.come3d70952012-03-13 12:40:53 +0000197 if (indexCount) {
198 this->resetIndexSource();
199 }
200 return false;
201 }
202 }
203 if (indexCount) {
204 if (!this->reserveIndexSpace(indexCount, indices)) {
205 if (vertexCount) {
206 this->resetVertexSource();
207 }
208 return false;
209 }
210 }
211 return true;
212}
213
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000214bool GrDrawTarget::geometryHints(int32_t* vertexCount,
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 if (NULL != vertexCount) {
217 *vertexCount = -1;
218 }
219 if (NULL != indexCount) {
220 *indexCount = -1;
221 }
222 return false;
223}
224
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000225void GrDrawTarget::releasePreviousVertexSource() {
226 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
227 switch (geoSrc.fVertexSrc) {
228 case kNone_GeometrySrcType:
229 break;
230 case kArray_GeometrySrcType:
231 this->releaseVertexArray();
232 break;
233 case kReserved_GeometrySrcType:
234 this->releaseReservedVertexSpace();
235 break;
236 case kBuffer_GeometrySrcType:
237 geoSrc.fVertexBuffer->unref();
238#if GR_DEBUG
239 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
240#endif
241 break;
242 default:
243 GrCrash("Unknown Vertex Source Type.");
244 break;
245 }
246}
247
248void GrDrawTarget::releasePreviousIndexSource() {
249 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
250 switch (geoSrc.fIndexSrc) {
251 case kNone_GeometrySrcType: // these two don't require
252 break;
253 case kArray_GeometrySrcType:
254 this->releaseIndexArray();
255 break;
256 case kReserved_GeometrySrcType:
257 this->releaseReservedIndexSpace();
258 break;
259 case kBuffer_GeometrySrcType:
260 geoSrc.fIndexBuffer->unref();
261#if GR_DEBUG
262 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
263#endif
264 break;
265 default:
266 GrCrash("Unknown Index Source Type.");
267 break;
268 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000269}
270
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000271void GrDrawTarget::setVertexSourceToArray(const void* vertexArray,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000272 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000273 this->releasePreviousVertexSource();
274 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
275 geoSrc.fVertexSrc = kArray_GeometrySrcType;
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000276 geoSrc.fVertexSize = this->drawState()->getVertexSize();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000277 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000278 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000279}
280
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000281void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
282 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000283 this->releasePreviousIndexSource();
284 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
285 geoSrc.fIndexSrc = kArray_GeometrySrcType;
286 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000287 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000288}
289
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000290void GrDrawTarget::setVertexSourceToBuffer(const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000291 this->releasePreviousVertexSource();
292 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
293 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
294 geoSrc.fVertexBuffer = buffer;
295 buffer->ref();
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000296 geoSrc.fVertexSize = this->drawState()->getVertexSize();
reed@google.comac10a2d2010-12-22 21:39:39 +0000297}
298
299void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000300 this->releasePreviousIndexSource();
301 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
302 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
303 geoSrc.fIndexBuffer = buffer;
304 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000305}
306
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000307void GrDrawTarget::resetVertexSource() {
308 this->releasePreviousVertexSource();
309 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
310 geoSrc.fVertexSrc = kNone_GeometrySrcType;
311}
312
313void GrDrawTarget::resetIndexSource() {
314 this->releasePreviousIndexSource();
315 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
316 geoSrc.fIndexSrc = kNone_GeometrySrcType;
317}
318
319void GrDrawTarget::pushGeometrySource() {
320 this->geometrySourceWillPush();
321 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
322 newState.fIndexSrc = kNone_GeometrySrcType;
323 newState.fVertexSrc = kNone_GeometrySrcType;
324#if GR_DEBUG
325 newState.fVertexCount = ~0;
326 newState.fVertexBuffer = (GrVertexBuffer*)~0;
327 newState.fIndexCount = ~0;
328 newState.fIndexBuffer = (GrIndexBuffer*)~0;
329#endif
330}
331
332void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000333 // if popping last element then pops are unbalanced with pushes
334 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000335
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000336 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
337 this->releasePreviousVertexSource();
338 this->releasePreviousIndexSource();
339 fGeoSrcStateStack.pop_back();
340}
341
342////////////////////////////////////////////////////////////////////////////////
343
bsalomon@google.come8262622011-11-07 02:30:51 +0000344bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
345 int startIndex, int vertexCount,
346 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000347 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000348#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000349 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000350 int maxVertex = startVertex + vertexCount;
351 int maxValidVertex;
352 switch (geoSrc.fVertexSrc) {
353 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000354 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000355 case kReserved_GeometrySrcType: // fallthrough
356 case kArray_GeometrySrcType:
357 maxValidVertex = geoSrc.fVertexCount;
358 break;
359 case kBuffer_GeometrySrcType:
jvanverth@google.comb75b0a02013-02-05 20:33:30 +0000360 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / geoSrc.fVertexSize;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000361 break;
362 }
363 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000364 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000365 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000366 if (indexCount > 0) {
367 int maxIndex = startIndex + indexCount;
368 int maxValidIndex;
369 switch (geoSrc.fIndexSrc) {
370 case kNone_GeometrySrcType:
371 GrCrash("Attempting to draw indexed geom without index src.");
372 case kReserved_GeometrySrcType: // fallthrough
373 case kArray_GeometrySrcType:
374 maxValidIndex = geoSrc.fIndexCount;
375 break;
376 case kBuffer_GeometrySrcType:
377 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
378 break;
379 }
380 if (maxIndex > maxValidIndex) {
381 GrCrash("Index reads outside valid index range.");
382 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000383 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000384
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000385 GrAssert(NULL != drawState.getRenderTarget());
386 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
387 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000388 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000389 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000390 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000391 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000392 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
393 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000394 }
395 }
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000396
397 GrAssert(drawState.validateVertexAttribs());
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000398#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000399 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000400 return false;
401 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000402 return true;
403}
404
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000405void GrDrawTarget::drawIndexed(GrPrimitiveType type,
406 int startVertex,
407 int startIndex,
408 int vertexCount,
409 int indexCount,
410 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000411 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
412 DrawInfo info;
413 info.fPrimitiveType = type;
414 info.fStartVertex = startVertex;
415 info.fStartIndex = startIndex;
416 info.fVertexCount = vertexCount;
417 info.fIndexCount = indexCount;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000418
419 info.fInstanceCount = 0;
420 info.fVerticesPerInstance = 0;
421 info.fIndicesPerInstance = 0;
422
423 if (NULL != devBounds) {
424 info.setDevBounds(*devBounds);
425 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000426 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000427 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000428}
429
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000430void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
431 int startVertex,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000432 int vertexCount,
433 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000434 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
435 DrawInfo info;
436 info.fPrimitiveType = type;
437 info.fStartVertex = startVertex;
438 info.fStartIndex = 0;
439 info.fVertexCount = vertexCount;
440 info.fIndexCount = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000441
442 info.fInstanceCount = 0;
443 info.fVerticesPerInstance = 0;
444 info.fIndicesPerInstance = 0;
445
446 if (NULL != devBounds) {
447 info.setDevBounds(*devBounds);
448 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000449 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000450 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000451}
452
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000453void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000454 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000455 GrAssert(NULL != path);
bsalomon@google.combcce8922013-03-25 15:38:39 +0000456 GrAssert(this->caps()->pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000457 GrAssert(!stroke.isHairlineStyle());
458 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000459 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000460}
461
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000462////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000463
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000464bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com2b446732013-02-12 16:47:41 +0000465 // There is a conflict between using smooth lines and our use of premultiplied alpha. Smooth
466 // lines tweak the incoming alpha value but not in a premul-alpha way. So we only use them when
467 // our alpha is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.combcce8922013-03-25 15:38:39 +0000468 if (!this->caps()->hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000469 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000470 return false;
471 }
bsalomon@google.com2b446732013-02-12 16:47:41 +0000472 GrDrawState::BlendOptFlags opts = this->getDrawState().getBlendOpts();
473 return (GrDrawState::kDisableBlend_BlendOptFlag & opts) &&
474 (GrDrawState::kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000475}
476
477bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000478 // we can correctly apply coverage if a) we have dual source blending
479 // or b) one of our blend optimizations applies.
bsalomon@google.combcce8922013-03-25 15:38:39 +0000480 return this->caps()->dualSourceBlendingSupport() ||
bsalomon@google.com2b446732013-02-12 16:47:41 +0000481 GrDrawState::kNone_BlendOpt != this->getDrawState().getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000482}
483
bsalomon@google.com934c5702012-03-20 21:17:58 +0000484////////////////////////////////////////////////////////////////////////////////
485
486void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
487 int instanceCount,
488 int verticesPerInstance,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000489 int indicesPerInstance,
490 const SkRect* devBounds) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000491 if (!verticesPerInstance || !indicesPerInstance) {
492 return;
493 }
494
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000495 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
496 if (!maxInstancesPerDraw) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000497 return;
498 }
499
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000500 DrawInfo info;
501 info.fPrimitiveType = type;
502 info.fStartIndex = 0;
503 info.fStartVertex = 0;
504 info.fIndicesPerInstance = indicesPerInstance;
505 info.fVerticesPerInstance = verticesPerInstance;
506
507 // Set the same bounds for all the draws.
508 if (NULL != devBounds) {
509 info.setDevBounds(*devBounds);
510 }
511
bsalomon@google.com934c5702012-03-20 21:17:58 +0000512 while (instanceCount) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000513 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
514 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
515 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
516
517 if (this->checkDraw(type,
518 info.fStartVertex,
519 info.fStartIndex,
520 info.fVertexCount,
521 info.fIndexCount)) {
522 this->onDraw(info);
523 }
524 info.fStartVertex += info.fVertexCount;
525 instanceCount -= info.fInstanceCount;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000526 }
527}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000528
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000529////////////////////////////////////////////////////////////////////////////////
530
rmistry@google.comd6176b02012-08-23 18:14:13 +0000531void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000532 const SkMatrix* matrix,
bsalomon@google.comc7818882013-03-20 19:19:53 +0000533 const GrRect* localRect,
534 const SkMatrix* localMatrix) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000535 GrAttribBindings bindings = 0;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000536 // position + (optional) texture coord
537 static const GrVertexAttrib kAttribs[] = {
jvanverth@google.com3b0d6312013-03-01 20:30:01 +0000538 {kVec2f_GrVertexAttribType, 0},
539 {kVec2f_GrVertexAttribType, sizeof(GrPoint)}
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000540 };
541 int attribCount = 1;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000542
bsalomon@google.comc7818882013-03-20 19:19:53 +0000543 if (NULL != localRect) {
544 bindings |= GrDrawState::kLocalCoords_AttribBindingsBit;
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000545 attribCount = 2;
bsalomon@google.comc7818882013-03-20 19:19:53 +0000546 this->drawState()->setAttribIndex(GrDrawState::kLocalCoords_AttribIndex, 1);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000547 }
548
549 GrDrawState::AutoViewMatrixRestore avmr;
550 if (NULL != matrix) {
bsalomon@google.comc7818882013-03-20 19:19:53 +0000551 avmr.set(this->drawState(), *matrix);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000552 }
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);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000565 if (NULL != localRect) {
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000566 GrAssert(attribCount == 2);
567 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
568 kAttribs[1].fOffset);
bsalomon@google.comc7818882013-03-20 19:19:53 +0000569 coords->setRectFan(localRect->fLeft, localRect->fTop,
570 localRect->fRight, localRect->fBottom,
571 vsize);
572 if (NULL != localMatrix) {
573 localMatrix->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.combcce8922013-03-25 15:38:39 +0000681///////////////////////////////////////////////////////////////////////////////
682
bsalomon@google.comc26d94f2013-03-25 18:19:00 +0000683SK_DEFINE_INST_COUNT(GrDrawTargetCaps)
bsalomon@google.combcce8922013-03-25 15:38:39 +0000684
bsalomon@google.comc26d94f2013-03-25 18:19:00 +0000685void GrDrawTargetCaps::reset() {
bsalomon@google.combcce8922013-03-25 15:38:39 +0000686 f8BitPaletteSupport = false;
687 fNPOTTextureTileSupport = false;
688 fTwoSidedStencilSupport = false;
689 fStencilWrapOpsSupport = false;
690 fHWAALineSupport = false;
691 fShaderDerivativeSupport = false;
692 fGeometryShaderSupport = false;
skia.committer@gmail.come60ed082013-03-26 07:01:04 +0000693 fDualSourceBlendingSupport = false;
bsalomon@google.combcce8922013-03-25 15:38:39 +0000694 fBufferLockSupport = false;
695 fPathStencilingSupport = false;
696
697 fMaxRenderTargetSize = 0;
698 fMaxTextureSize = 0;
699 fMaxSampleCount = 0;
700}
701
bsalomon@google.comc26d94f2013-03-25 18:19:00 +0000702GrDrawTargetCaps& GrDrawTargetCaps::operator=(const GrDrawTargetCaps& other) {
bsalomon@google.combcce8922013-03-25 15:38:39 +0000703 f8BitPaletteSupport = other.f8BitPaletteSupport;
704 fNPOTTextureTileSupport = other.fNPOTTextureTileSupport;
705 fTwoSidedStencilSupport = other.fTwoSidedStencilSupport;
706 fStencilWrapOpsSupport = other.fStencilWrapOpsSupport;
707 fHWAALineSupport = other.fHWAALineSupport;
708 fShaderDerivativeSupport = other.fShaderDerivativeSupport;
709 fGeometryShaderSupport = other.fGeometryShaderSupport;
710 fDualSourceBlendingSupport = other.fDualSourceBlendingSupport;
711 fBufferLockSupport = other.fBufferLockSupport;
712 fPathStencilingSupport = other.fPathStencilingSupport;
713
714 fMaxRenderTargetSize = other.fMaxRenderTargetSize;
715 fMaxTextureSize = other.fMaxTextureSize;
716 fMaxSampleCount = other.fMaxSampleCount;
717
718 return *this;
719}
720
bsalomon@google.comc26d94f2013-03-25 18:19:00 +0000721void GrDrawTargetCaps::print() const {
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000722 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.combcce8922013-03-25 15:38:39 +0000723 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
724 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
725 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
726 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
727 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
728 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
729 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
730 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
731 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
732 GrPrintf("Path Stenciling Support : %s\n", gNY[fPathStencilingSupport]);
733 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
734 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
735 GrPrintf("Max Sample Count : %d\n", fMaxSampleCount);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000736}