blob: 2cbcf19759dc9bc98343bb5de0b8a30348539205 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrDrawTarget.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000012#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000013#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000014#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000015
sugoi@google.com5f74cf82012-12-17 21:16:45 +000016#include "SkStrokeRec.h"
sugoi@google.com12b4e272012-12-06 20:13:11 +000017
reed@google.comfa35e3d2012-06-26 20:16:17 +000018SK_DEFINE_INST_COUNT(GrDrawTarget)
19
reed@google.comac10a2d2010-12-22 21:39:39 +000020////////////////////////////////////////////////////////////////////////////////
21
bsalomon@google.comd62e88e2013-02-01 14:19:27 +000022GrDrawTarget::DrawInfo& GrDrawTarget::DrawInfo::operator =(const DrawInfo& di) {
23 fPrimitiveType = di.fPrimitiveType;
24 fStartVertex = di.fStartVertex;
25 fStartIndex = di.fStartIndex;
26 fVertexCount = di.fVertexCount;
27 fIndexCount = di.fIndexCount;
28
29 fInstanceCount = di.fInstanceCount;
30 fVerticesPerInstance = di.fVerticesPerInstance;
31 fIndicesPerInstance = di.fIndicesPerInstance;
32
33 if (NULL != di.fDevBounds) {
34 GrAssert(di.fDevBounds == &di.fDevBoundsStorage);
35 fDevBoundsStorage = di.fDevBoundsStorage;
36 fDevBounds = &fDevBoundsStorage;
37 } else {
38 fDevBounds = NULL;
39 }
40 return *this;
41}
42
43#if GR_DEBUG
44bool GrDrawTarget::DrawInfo::isInstanced() const {
45 if (fInstanceCount > 0) {
46 GrAssert(0 == fIndexCount % fIndicesPerInstance);
47 GrAssert(0 == fVertexCount % fVerticesPerInstance);
48 GrAssert(fIndexCount / fIndicesPerInstance == fInstanceCount);
49 GrAssert(fVertexCount / fVerticesPerInstance == fInstanceCount);
50 // there is no way to specify a non-zero start index to drawIndexedInstances().
51 GrAssert(0 == fStartIndex);
52 return true;
53 } else {
54 GrAssert(!fVerticesPerInstance);
55 GrAssert(!fIndicesPerInstance);
56 return false;
57 }
58}
59#endif
60
61void GrDrawTarget::DrawInfo::adjustInstanceCount(int instanceOffset) {
62 GrAssert(this->isInstanced());
63 GrAssert(instanceOffset + fInstanceCount >= 0);
64 fInstanceCount += instanceOffset;
65 fVertexCount = fVerticesPerInstance * fInstanceCount;
66 fIndexCount = fIndicesPerInstance * fInstanceCount;
67}
68
69void GrDrawTarget::DrawInfo::adjustStartVertex(int vertexOffset) {
70 fStartVertex += vertexOffset;
71 GrAssert(fStartVertex >= 0);
72}
73
74void GrDrawTarget::DrawInfo::adjustStartIndex(int indexOffset) {
75 GrAssert(this->isIndexed());
76 fStartIndex += indexOffset;
77 GrAssert(fStartIndex >= 0);
78}
79
80////////////////////////////////////////////////////////////////////////////////
81
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000082#define DEBUG_INVAL_BUFFER 0xdeadcafe
83#define DEBUG_INVAL_START_IDX -1
84
robertphillips@google.combeb1af72012-07-26 18:52:16 +000085GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000086 fDrawState = &fDefaultDrawState;
87 // We assume that fDrawState always owns a ref to the object it points at.
88 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000089 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000090#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000091 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
92 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
93 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
94 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +000095#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000096 geoSrc.fVertexSrc = kNone_GeometrySrcType;
97 geoSrc.fIndexSrc = kNone_GeometrySrcType;
98}
99
100GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000101 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +0000102 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000103 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
104 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000105 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000106}
107
108void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000109 int popCnt = fGeoSrcStateStack.count() - 1;
110 while (popCnt) {
111 this->popGeometrySource();
112 --popCnt;
113 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000114 this->resetVertexSource();
115 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000116}
117
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000118void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000119 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000120 fClip = clip;
121}
122
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000123const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 return fClip;
125}
126
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000127void GrDrawTarget::setDrawState(GrDrawState* drawState) {
128 GrAssert(NULL != fDrawState);
129 if (NULL == drawState) {
130 drawState = &fDefaultDrawState;
131 }
132 if (fDrawState != drawState) {
133 fDrawState->unref();
134 drawState->ref();
135 fDrawState = drawState;
136 }
137}
138
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000139bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
140 int vertexCount,
141 void** vertices) {
142 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
143 bool acquired = false;
144 if (vertexCount > 0) {
145 GrAssert(NULL != vertices);
146 this->releasePreviousVertexSource();
147 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000148
jvanverth@google.coma6338982013-01-31 21:34:25 +0000149 acquired = this->onReserveVertexSpace(GrDrawState::VertexSize(vertexLayout),
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000150 vertexCount,
151 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000153 if (acquired) {
154 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
155 geoSrc.fVertexCount = vertexCount;
156 geoSrc.fVertexLayout = vertexLayout;
157 } else if (NULL != vertices) {
158 *vertices = NULL;
159 }
160 return acquired;
161}
162
163bool GrDrawTarget::reserveIndexSpace(int indexCount,
164 void** indices) {
165 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
166 bool acquired = false;
167 if (indexCount > 0) {
168 GrAssert(NULL != indices);
169 this->releasePreviousIndexSource();
170 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000172 acquired = this->onReserveIndexSpace(indexCount, indices);
173 }
174 if (acquired) {
175 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
176 geoSrc.fIndexCount = indexCount;
177 } else if (NULL != indices) {
178 *indices = NULL;
179 }
180 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181
reed@google.comac10a2d2010-12-22 21:39:39 +0000182}
183
bsalomon@google.come3d70952012-03-13 12:40:53 +0000184bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
185 int vertexCount,
186 int indexCount,
187 void** vertices,
188 void** indices) {
jvanverth@google.coma6338982013-01-31 21:34:25 +0000189 this->willReserveVertexAndIndexSpace(GrDrawState::VertexSize(vertexLayout), vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000190 if (vertexCount) {
191 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
192 if (indexCount) {
193 this->resetIndexSource();
194 }
195 return false;
196 }
197 }
198 if (indexCount) {
199 if (!this->reserveIndexSpace(indexCount, indices)) {
200 if (vertexCount) {
201 this->resetVertexSource();
202 }
203 return false;
204 }
205 }
206 return true;
207}
208
jvanverth@google.coma6338982013-01-31 21:34:25 +0000209bool GrDrawTarget::geometryHints(size_t vertexSize,
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 int32_t* vertexCount,
211 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 if (NULL != vertexCount) {
213 *vertexCount = -1;
214 }
215 if (NULL != indexCount) {
216 *indexCount = -1;
217 }
218 return false;
219}
220
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000221void GrDrawTarget::releasePreviousVertexSource() {
222 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
223 switch (geoSrc.fVertexSrc) {
224 case kNone_GeometrySrcType:
225 break;
226 case kArray_GeometrySrcType:
227 this->releaseVertexArray();
228 break;
229 case kReserved_GeometrySrcType:
230 this->releaseReservedVertexSpace();
231 break;
232 case kBuffer_GeometrySrcType:
233 geoSrc.fVertexBuffer->unref();
234#if GR_DEBUG
235 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
236#endif
237 break;
238 default:
239 GrCrash("Unknown Vertex Source Type.");
240 break;
241 }
242}
243
244void GrDrawTarget::releasePreviousIndexSource() {
245 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
246 switch (geoSrc.fIndexSrc) {
247 case kNone_GeometrySrcType: // these two don't require
248 break;
249 case kArray_GeometrySrcType:
250 this->releaseIndexArray();
251 break;
252 case kReserved_GeometrySrcType:
253 this->releaseReservedIndexSpace();
254 break;
255 case kBuffer_GeometrySrcType:
256 geoSrc.fIndexBuffer->unref();
257#if GR_DEBUG
258 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
259#endif
260 break;
261 default:
262 GrCrash("Unknown Index Source Type.");
263 break;
264 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000265}
266
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000267void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
268 const void* vertexArray,
269 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000270 this->releasePreviousVertexSource();
271 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
272 geoSrc.fVertexSrc = kArray_GeometrySrcType;
273 geoSrc.fVertexLayout = vertexLayout;
274 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000275 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000276}
277
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000278void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
279 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000280 this->releasePreviousIndexSource();
281 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
282 geoSrc.fIndexSrc = kArray_GeometrySrcType;
283 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000284 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000285}
286
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000287void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
288 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000289 this->releasePreviousVertexSource();
290 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
291 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
292 geoSrc.fVertexBuffer = buffer;
293 buffer->ref();
294 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000295}
296
297void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000298 this->releasePreviousIndexSource();
299 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
300 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
301 geoSrc.fIndexBuffer = buffer;
302 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000303}
304
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000305void GrDrawTarget::resetVertexSource() {
306 this->releasePreviousVertexSource();
307 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
308 geoSrc.fVertexSrc = kNone_GeometrySrcType;
309}
310
311void GrDrawTarget::resetIndexSource() {
312 this->releasePreviousIndexSource();
313 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
314 geoSrc.fIndexSrc = kNone_GeometrySrcType;
315}
316
317void GrDrawTarget::pushGeometrySource() {
318 this->geometrySourceWillPush();
319 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
320 newState.fIndexSrc = kNone_GeometrySrcType;
321 newState.fVertexSrc = kNone_GeometrySrcType;
322#if GR_DEBUG
323 newState.fVertexCount = ~0;
324 newState.fVertexBuffer = (GrVertexBuffer*)~0;
325 newState.fIndexCount = ~0;
326 newState.fIndexBuffer = (GrIndexBuffer*)~0;
327#endif
328}
329
330void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000331 // if popping last element then pops are unbalanced with pushes
332 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000333
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000334 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
335 this->releasePreviousVertexSource();
336 this->releasePreviousIndexSource();
337 fGeoSrcStateStack.pop_back();
338}
339
340////////////////////////////////////////////////////////////////////////////////
341
bsalomon@google.come8262622011-11-07 02:30:51 +0000342bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
343 int startIndex, int vertexCount,
344 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000345 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000346#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000347 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000348 int maxVertex = startVertex + vertexCount;
349 int maxValidVertex;
350 switch (geoSrc.fVertexSrc) {
351 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000352 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000353 case kReserved_GeometrySrcType: // fallthrough
354 case kArray_GeometrySrcType:
355 maxValidVertex = geoSrc.fVertexCount;
356 break;
357 case kBuffer_GeometrySrcType:
reed@google.com75847192013-01-28 20:53:22 +0000358 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / GrDrawState::VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000359 break;
360 }
361 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000362 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000363 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000364 if (indexCount > 0) {
365 int maxIndex = startIndex + indexCount;
366 int maxValidIndex;
367 switch (geoSrc.fIndexSrc) {
368 case kNone_GeometrySrcType:
369 GrCrash("Attempting to draw indexed geom without index src.");
370 case kReserved_GeometrySrcType: // fallthrough
371 case kArray_GeometrySrcType:
372 maxValidIndex = geoSrc.fIndexCount;
373 break;
374 case kBuffer_GeometrySrcType:
375 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
376 break;
377 }
378 if (maxIndex > maxValidIndex) {
379 GrCrash("Index reads outside valid index range.");
380 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000381 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000382
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000383 GrAssert(NULL != drawState.getRenderTarget());
384 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
385 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000386 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000387 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000388 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000389 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000390 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
391 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000392 }
393 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000394#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000395 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000396 return false;
397 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000398 return true;
399}
400
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000401void GrDrawTarget::drawIndexed(GrPrimitiveType type,
402 int startVertex,
403 int startIndex,
404 int vertexCount,
405 int indexCount,
406 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000407 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
408 DrawInfo info;
409 info.fPrimitiveType = type;
410 info.fStartVertex = startVertex;
411 info.fStartIndex = startIndex;
412 info.fVertexCount = vertexCount;
413 info.fIndexCount = indexCount;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000414
415 info.fInstanceCount = 0;
416 info.fVerticesPerInstance = 0;
417 info.fIndicesPerInstance = 0;
418
419 if (NULL != devBounds) {
420 info.setDevBounds(*devBounds);
421 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000422 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000423 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000424}
425
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000426void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
427 int startVertex,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000428 int vertexCount,
429 const SkRect* devBounds) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000430 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
431 DrawInfo info;
432 info.fPrimitiveType = type;
433 info.fStartVertex = startVertex;
434 info.fStartIndex = 0;
435 info.fVertexCount = vertexCount;
436 info.fIndexCount = 0;
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000437
438 info.fInstanceCount = 0;
439 info.fVerticesPerInstance = 0;
440 info.fIndicesPerInstance = 0;
441
442 if (NULL != devBounds) {
443 info.setDevBounds(*devBounds);
444 }
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000445 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000446 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000447}
448
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000449void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000450 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000451 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000452 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000453 GrAssert(!stroke.isHairlineStyle());
454 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000455 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000456}
457
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000458////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000459
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000460// Some blend modes allow folding a partial coverage value into the color's
461// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000462bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000463 /**
464 * The fractional coverage is f
465 * The src and dst coeffs are Cs and Cd
466 * The dst and src colors are S and D
467 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
468 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
469 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000470 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000471 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000472 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000473 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000474 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000475 return kOne_GrBlendCoeff == dstCoeff ||
476 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000477 kISC_GrBlendCoeff == dstCoeff ||
478 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000479}
480
bsalomon@google.come79c8152012-03-29 19:07:12 +0000481namespace {
482GrVertexLayout default_blend_opts_vertex_layout() {
483 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000484 return layout;
485}
486}
487
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000488GrDrawTarget::BlendOptFlags
489GrDrawTarget::getBlendOpts(bool forceCoverage,
490 GrBlendCoeff* srcCoeff,
491 GrBlendCoeff* dstCoeff) const {
492
bsalomon@google.come79c8152012-03-29 19:07:12 +0000493 GrVertexLayout layout;
494 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
495 layout = default_blend_opts_vertex_layout();
496 } else {
497 layout = this->getVertexLayout();
498 }
499
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000500 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000501
502 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
503 if (NULL == srcCoeff) {
504 srcCoeff = &bogusSrcCoeff;
505 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000506 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000507
508 if (NULL == dstCoeff) {
509 dstCoeff = &bogusDstCoeff;
510 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000511 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000512
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000513 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000514 *srcCoeff = kZero_GrBlendCoeff;
515 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000516 }
517
jvanverth@google.comcc782382013-01-28 20:39:48 +0000518 bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000519 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
520 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
521 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
522 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000523
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000524 bool covIsZero = !drawState.isCoverageDrawing() &&
jvanverth@google.comcc782382013-01-28 20:39:48 +0000525 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000526 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000527 // When coeffs are (0,1) there is no reason to draw at all, unless
528 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000529 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000530 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000531 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000532 return kDisableBlend_BlendOptFlag |
533 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000534 } else {
535 return kSkipDraw_BlendOptFlag;
536 }
537 }
538
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000539 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000540 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000541 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000542 0xffffffff != drawState.getCoverage() ||
jvanverth@google.comcc782382013-01-28 20:39:48 +0000543 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
544 (layout & GrDrawState::kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000545 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000546 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000547 ++s) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000548 if (drawState.isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000549 hasCoverage = true;
550 }
551 }
552
553 // if we don't have coverage we can check whether the dst
554 // has to read at all. If not, we'll disable blending.
555 if (!hasCoverage) {
556 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000557 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000558 // if there is no coverage and coeffs are (1,0) then we
559 // won't need to read the dst at all, it gets replaced by src
560 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000561 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000562 // if the op is "clear" then we don't need to emit a color
563 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000564 *srcCoeff = kOne_GrBlendCoeff;
565 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000566 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000567 }
568 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000569 } else if (drawState.isCoverageDrawing()) {
570 // we have coverage but we aren't distinguishing it from alpha by request.
571 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000572 } else {
573 // check whether coverage can be safely rolled into alpha
574 // of if we can skip color computation and just emit coverage
575 if (this->canTweakAlphaForCoverage()) {
576 return kCoverageAsAlpha_BlendOptFlag;
577 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000578 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000579 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000580 // the source color is not included in the blend
581 // the dst coeff is effectively zero so blend works out to:
582 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000583 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000584 return kEmitCoverage_BlendOptFlag;
585 } else if (srcAIsOne) {
586 // the dst coeff is effectively zero so blend works out to:
587 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000588 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000589 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000590 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000591 return kCoverageAsAlpha_BlendOptFlag;
592 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000593 } else if (dstCoeffIsOne) {
594 // the dst coeff is effectively one so blend works out to:
595 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000596 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000597 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000598 }
599 }
600 return kNone_BlendOpt;
601}
602
603bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000604 // there is a conflict between using smooth lines and our use of
605 // premultiplied alpha. Smooth lines tweak the incoming alpha value
606 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000607 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000608 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000609 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000610 return false;
611 }
612 BlendOptFlags opts = this->getBlendOpts();
613 return (kDisableBlend_BlendOptFlag & opts) &&
614 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000615}
616
617bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000618 // we can correctly apply coverage if a) we have dual source blending
619 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000620 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000621 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000622}
623
bsalomon@google.com934c5702012-03-20 21:17:58 +0000624////////////////////////////////////////////////////////////////////////////////
625
626void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
627 int instanceCount,
628 int verticesPerInstance,
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000629 int indicesPerInstance,
630 const SkRect* devBounds) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000631 if (!verticesPerInstance || !indicesPerInstance) {
632 return;
633 }
634
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000635 int maxInstancesPerDraw = this->indexCountInCurrentSource() / indicesPerInstance;
636 if (!maxInstancesPerDraw) {
bsalomon@google.com934c5702012-03-20 21:17:58 +0000637 return;
638 }
639
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000640 DrawInfo info;
641 info.fPrimitiveType = type;
642 info.fStartIndex = 0;
643 info.fStartVertex = 0;
644 info.fIndicesPerInstance = indicesPerInstance;
645 info.fVerticesPerInstance = verticesPerInstance;
646
647 // Set the same bounds for all the draws.
648 if (NULL != devBounds) {
649 info.setDevBounds(*devBounds);
650 }
651
bsalomon@google.com934c5702012-03-20 21:17:58 +0000652 while (instanceCount) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000653 info.fInstanceCount = GrMin(instanceCount, maxInstancesPerDraw);
654 info.fVertexCount = info.fInstanceCount * verticesPerInstance;
655 info.fIndexCount = info.fInstanceCount * indicesPerInstance;
656
657 if (this->checkDraw(type,
658 info.fStartVertex,
659 info.fStartIndex,
660 info.fVertexCount,
661 info.fIndexCount)) {
662 this->onDraw(info);
663 }
664 info.fStartVertex += info.fVertexCount;
665 instanceCount -= info.fInstanceCount;
bsalomon@google.com934c5702012-03-20 21:17:58 +0000666 }
667}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000668
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000669////////////////////////////////////////////////////////////////////////////////
670
rmistry@google.comd6176b02012-08-23 18:14:13 +0000671void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000672 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000673 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000674 const SkMatrix* srcMatrices[]) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000675 GrVertexLayout layout = 0;
676 uint32_t explicitCoordMask = 0;
677
678 if (NULL != srcRects) {
679 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
680 int numTC = 0;
681 if (NULL != srcRects[s]) {
682 layout |= GrDrawState::StageTexCoordVertexLayoutBit(s, numTC);
683 explicitCoordMask |= (1 << s);
684 ++numTC;
685 }
686 }
687 }
688
689 GrDrawState::AutoViewMatrixRestore avmr;
690 if (NULL != matrix) {
691 avmr.set(this->drawState(), *matrix, explicitCoordMask);
692 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000693
694 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000695 if (!geo.succeeded()) {
696 GrPrintf("Failed to get space for vertices!\n");
697 return;
698 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000699
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000700 int stageOffsets[GrDrawState::kNumStages];
701 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets, NULL, NULL, NULL);
702 geo.positions()->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, vsize);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000703
tomhudson@google.com93813632011-10-27 20:21:16 +0000704 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000705 if (explicitCoordMask & (1 << i)) {
reed@google.com009dfe22013-02-01 15:05:18 +0000706 GrAssert(0 != stageOffsets[i]);
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000707 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(geo.vertices()) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000708 stageOffsets[i]);
709 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000710 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000711 vsize);
712 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
713 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
714 }
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000715 } else {
reed@google.com009dfe22013-02-01 15:05:18 +0000716 GrAssert(0 == stageOffsets[i]);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000717 }
718 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000719
bsalomon@google.comd62e88e2013-02-01 14:19:27 +0000720 this->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000721}
722
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000723void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
724}
725
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000727
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000728GrDrawTarget::AutoStateRestore::AutoStateRestore() {
729 fDrawTarget = NULL;
730}
reed@google.comac10a2d2010-12-22 21:39:39 +0000731
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000732GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
733 ASRInit init) {
734 fDrawTarget = NULL;
735 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000736}
737
738GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000739 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000740 fDrawTarget->setDrawState(fSavedState);
741 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000742 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000743}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000744
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000745void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
746 GrAssert(NULL == fDrawTarget);
747 fDrawTarget = target;
748 fSavedState = target->drawState();
749 GrAssert(fSavedState);
750 fSavedState->ref();
751 if (kReset_ASRInit == init) {
752 // calls the default cons
753 fTempState.init();
754 } else {
755 GrAssert(kPreserve_ASRInit == init);
756 // calls the copy cons
757 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000758 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000759 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000760}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000761
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000762////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000763
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000764GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
765 GrDrawTarget* target,
766 GrVertexLayout vertexLayout,
767 int vertexCount,
768 int indexCount) {
769 fTarget = NULL;
770 this->set(target, vertexLayout, vertexCount, indexCount);
771}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000772
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000773GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
774 fTarget = NULL;
775}
776
777GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
778 this->reset();
779}
780
781bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
782 GrVertexLayout vertexLayout,
783 int vertexCount,
784 int indexCount) {
785 this->reset();
786 fTarget = target;
787 bool success = true;
788 if (NULL != fTarget) {
789 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +0000790 success = target->reserveVertexAndIndexSpace(vertexLayout,
791 vertexCount,
792 indexCount,
793 &fVertices,
794 &fIndices);
795 if (!success) {
796 fTarget = NULL;
797 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000798 }
799 }
800 GrAssert(success == (NULL != fTarget));
801 return success;
802}
803
804void GrDrawTarget::AutoReleaseGeometry::reset() {
805 if (NULL != fTarget) {
806 if (NULL != fVertices) {
807 fTarget->resetVertexSource();
808 }
809 if (NULL != fIndices) {
810 fTarget->resetIndexSource();
811 }
812 fTarget = NULL;
813 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000814 fVertices = NULL;
815 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000816}
817
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000818GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
819 fTarget = target;
820 fClip = fTarget->getClip();
821 fStack.init();
822 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
823 fReplacementClip.fClipStack = fStack.get();
824 target->setClip(&fReplacementClip);
825}
826
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000827void GrDrawTarget::Caps::print() const {
828 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000829 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
830 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
831 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
832 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
833 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
834 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
835 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
836 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
837 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
838 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
839 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
840 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
841 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000842}