blob: d2d1d8d34713275985a29f5fd730690ec5ae7a73 [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.com25fb21f2011-06-21 18:17:25 +000022#define DEBUG_INVAL_BUFFER 0xdeadcafe
23#define DEBUG_INVAL_START_IDX -1
24
robertphillips@google.combeb1af72012-07-26 18:52:16 +000025GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000026 fDrawState = &fDefaultDrawState;
27 // We assume that fDrawState always owns a ref to the object it points at.
28 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000029 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000030#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000031 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
32 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
33 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
34 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +000035#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000036 geoSrc.fVertexSrc = kNone_GeometrySrcType;
37 geoSrc.fIndexSrc = kNone_GeometrySrcType;
38}
39
40GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000041 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +000042 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000043 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
44 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000045 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000046}
47
48void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000049 int popCnt = fGeoSrcStateStack.count() - 1;
50 while (popCnt) {
51 this->popGeometrySource();
52 --popCnt;
53 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000054 this->resetVertexSource();
55 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +000056}
57
robertphillips@google.combeb1af72012-07-26 18:52:16 +000058void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000059 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +000060 fClip = clip;
61}
62
robertphillips@google.combeb1af72012-07-26 18:52:16 +000063const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000064 return fClip;
65}
66
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000067void GrDrawTarget::setDrawState(GrDrawState* drawState) {
68 GrAssert(NULL != fDrawState);
69 if (NULL == drawState) {
70 drawState = &fDefaultDrawState;
71 }
72 if (fDrawState != drawState) {
73 fDrawState->unref();
74 drawState->ref();
75 fDrawState = drawState;
76 }
77}
78
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000079bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
80 int vertexCount,
81 void** vertices) {
82 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
83 bool acquired = false;
84 if (vertexCount > 0) {
85 GrAssert(NULL != vertices);
86 this->releasePreviousVertexSource();
87 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +000088
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000089 acquired = this->onReserveVertexSpace(vertexLayout,
90 vertexCount,
91 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +000092 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000093 if (acquired) {
94 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
95 geoSrc.fVertexCount = vertexCount;
96 geoSrc.fVertexLayout = vertexLayout;
97 } else if (NULL != vertices) {
98 *vertices = NULL;
99 }
100 return acquired;
101}
102
103bool GrDrawTarget::reserveIndexSpace(int indexCount,
104 void** indices) {
105 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
106 bool acquired = false;
107 if (indexCount > 0) {
108 GrAssert(NULL != indices);
109 this->releasePreviousIndexSource();
110 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000111
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000112 acquired = this->onReserveIndexSpace(indexCount, indices);
113 }
114 if (acquired) {
115 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
116 geoSrc.fIndexCount = indexCount;
117 } else if (NULL != indices) {
118 *indices = NULL;
119 }
120 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000121
reed@google.comac10a2d2010-12-22 21:39:39 +0000122}
123
bsalomon@google.come3d70952012-03-13 12:40:53 +0000124bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
125 int vertexCount,
126 int indexCount,
127 void** vertices,
128 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000129 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000130 if (vertexCount) {
131 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
132 if (indexCount) {
133 this->resetIndexSource();
134 }
135 return false;
136 }
137 }
138 if (indexCount) {
139 if (!this->reserveIndexSpace(indexCount, indices)) {
140 if (vertexCount) {
141 this->resetVertexSource();
142 }
143 return false;
144 }
145 }
146 return true;
147}
148
reed@google.comac10a2d2010-12-22 21:39:39 +0000149bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
150 int32_t* vertexCount,
151 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 if (NULL != vertexCount) {
153 *vertexCount = -1;
154 }
155 if (NULL != indexCount) {
156 *indexCount = -1;
157 }
158 return false;
159}
160
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000161void GrDrawTarget::releasePreviousVertexSource() {
162 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
163 switch (geoSrc.fVertexSrc) {
164 case kNone_GeometrySrcType:
165 break;
166 case kArray_GeometrySrcType:
167 this->releaseVertexArray();
168 break;
169 case kReserved_GeometrySrcType:
170 this->releaseReservedVertexSpace();
171 break;
172 case kBuffer_GeometrySrcType:
173 geoSrc.fVertexBuffer->unref();
174#if GR_DEBUG
175 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
176#endif
177 break;
178 default:
179 GrCrash("Unknown Vertex Source Type.");
180 break;
181 }
182}
183
184void GrDrawTarget::releasePreviousIndexSource() {
185 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
186 switch (geoSrc.fIndexSrc) {
187 case kNone_GeometrySrcType: // these two don't require
188 break;
189 case kArray_GeometrySrcType:
190 this->releaseIndexArray();
191 break;
192 case kReserved_GeometrySrcType:
193 this->releaseReservedIndexSpace();
194 break;
195 case kBuffer_GeometrySrcType:
196 geoSrc.fIndexBuffer->unref();
197#if GR_DEBUG
198 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
199#endif
200 break;
201 default:
202 GrCrash("Unknown Index Source Type.");
203 break;
204 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000205}
206
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000207void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
208 const void* vertexArray,
209 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000210 this->releasePreviousVertexSource();
211 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
212 geoSrc.fVertexSrc = kArray_GeometrySrcType;
213 geoSrc.fVertexLayout = vertexLayout;
214 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000215 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000216}
217
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000218void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
219 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000220 this->releasePreviousIndexSource();
221 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
222 geoSrc.fIndexSrc = kArray_GeometrySrcType;
223 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000224 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000225}
226
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000227void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
228 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000229 this->releasePreviousVertexSource();
230 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
231 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
232 geoSrc.fVertexBuffer = buffer;
233 buffer->ref();
234 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000235}
236
237void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000238 this->releasePreviousIndexSource();
239 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
240 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
241 geoSrc.fIndexBuffer = buffer;
242 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000243}
244
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000245void GrDrawTarget::resetVertexSource() {
246 this->releasePreviousVertexSource();
247 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
248 geoSrc.fVertexSrc = kNone_GeometrySrcType;
249}
250
251void GrDrawTarget::resetIndexSource() {
252 this->releasePreviousIndexSource();
253 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
254 geoSrc.fIndexSrc = kNone_GeometrySrcType;
255}
256
257void GrDrawTarget::pushGeometrySource() {
258 this->geometrySourceWillPush();
259 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
260 newState.fIndexSrc = kNone_GeometrySrcType;
261 newState.fVertexSrc = kNone_GeometrySrcType;
262#if GR_DEBUG
263 newState.fVertexCount = ~0;
264 newState.fVertexBuffer = (GrVertexBuffer*)~0;
265 newState.fIndexCount = ~0;
266 newState.fIndexBuffer = (GrIndexBuffer*)~0;
267#endif
268}
269
270void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000271 // if popping last element then pops are unbalanced with pushes
272 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000273
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000274 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
275 this->releasePreviousVertexSource();
276 this->releasePreviousIndexSource();
277 fGeoSrcStateStack.pop_back();
278}
279
280////////////////////////////////////////////////////////////////////////////////
281
bsalomon@google.come8262622011-11-07 02:30:51 +0000282bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
283 int startIndex, int vertexCount,
284 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000285 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000286#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000287 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000288 int maxVertex = startVertex + vertexCount;
289 int maxValidVertex;
290 switch (geoSrc.fVertexSrc) {
291 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000292 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000293 case kReserved_GeometrySrcType: // fallthrough
294 case kArray_GeometrySrcType:
295 maxValidVertex = geoSrc.fVertexCount;
296 break;
297 case kBuffer_GeometrySrcType:
reed@google.com75847192013-01-28 20:53:22 +0000298 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / GrDrawState::VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000299 break;
300 }
301 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000302 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000303 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000304 if (indexCount > 0) {
305 int maxIndex = startIndex + indexCount;
306 int maxValidIndex;
307 switch (geoSrc.fIndexSrc) {
308 case kNone_GeometrySrcType:
309 GrCrash("Attempting to draw indexed geom without index src.");
310 case kReserved_GeometrySrcType: // fallthrough
311 case kArray_GeometrySrcType:
312 maxValidIndex = geoSrc.fIndexCount;
313 break;
314 case kBuffer_GeometrySrcType:
315 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
316 break;
317 }
318 if (maxIndex > maxValidIndex) {
319 GrCrash("Index reads outside valid index range.");
320 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000321 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000322
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000323 GrAssert(NULL != drawState.getRenderTarget());
324 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
325 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000326 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000327 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000328 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000329 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000330 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
331 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000332 }
333 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000334#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000335 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000336 return false;
337 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000338 return true;
339}
340
341void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
342 int startIndex, int vertexCount,
343 int indexCount) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000344 if (indexCount > 0 && this->checkDraw(type, startVertex, startIndex, vertexCount, indexCount)) {
345 DrawInfo info;
346 info.fPrimitiveType = type;
347 info.fStartVertex = startVertex;
348 info.fStartIndex = startIndex;
349 info.fVertexCount = vertexCount;
350 info.fIndexCount = indexCount;
351 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000352 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000353}
354
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000355void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
356 int startVertex,
357 int vertexCount) {
bsalomon@google.com74749cd2013-01-30 16:12:41 +0000358 if (vertexCount > 0 && this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
359 DrawInfo info;
360 info.fPrimitiveType = type;
361 info.fStartVertex = startVertex;
362 info.fStartIndex = 0;
363 info.fVertexCount = vertexCount;
364 info.fIndexCount = 0;
365 this->onDraw(info);
bsalomon@google.com82145872011-08-23 14:32:40 +0000366 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000367}
368
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000369void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000370 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000371 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000372 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000373 GrAssert(!stroke.isHairlineStyle());
374 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000375 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000376}
377
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000378////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000379
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000380// Some blend modes allow folding a partial coverage value into the color's
381// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000382bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000383 /**
384 * The fractional coverage is f
385 * The src and dst coeffs are Cs and Cd
386 * The dst and src colors are S and D
387 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
388 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
389 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000390 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000391 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000392 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000393 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000394 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000395 return kOne_GrBlendCoeff == dstCoeff ||
396 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000397 kISC_GrBlendCoeff == dstCoeff ||
398 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000399}
400
bsalomon@google.come79c8152012-03-29 19:07:12 +0000401namespace {
402GrVertexLayout default_blend_opts_vertex_layout() {
403 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000404 return layout;
405}
406}
407
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000408GrDrawTarget::BlendOptFlags
409GrDrawTarget::getBlendOpts(bool forceCoverage,
410 GrBlendCoeff* srcCoeff,
411 GrBlendCoeff* dstCoeff) const {
412
bsalomon@google.come79c8152012-03-29 19:07:12 +0000413 GrVertexLayout layout;
414 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
415 layout = default_blend_opts_vertex_layout();
416 } else {
417 layout = this->getVertexLayout();
418 }
419
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000420 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000421
422 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
423 if (NULL == srcCoeff) {
424 srcCoeff = &bogusSrcCoeff;
425 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000426 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000427
428 if (NULL == dstCoeff) {
429 dstCoeff = &bogusDstCoeff;
430 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000431 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000432
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000433 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000434 *srcCoeff = kZero_GrBlendCoeff;
435 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000436 }
437
jvanverth@google.comcc782382013-01-28 20:39:48 +0000438 bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000439 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
440 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
441 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
442 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000443
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000444 bool covIsZero = !drawState.isCoverageDrawing() &&
jvanverth@google.comcc782382013-01-28 20:39:48 +0000445 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000446 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000447 // When coeffs are (0,1) there is no reason to draw at all, unless
448 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000449 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000450 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000451 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000452 return kDisableBlend_BlendOptFlag |
453 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000454 } else {
455 return kSkipDraw_BlendOptFlag;
456 }
457 }
458
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000459 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000460 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000461 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000462 0xffffffff != drawState.getCoverage() ||
jvanverth@google.comcc782382013-01-28 20:39:48 +0000463 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
464 (layout & GrDrawState::kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000465 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000466 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000467 ++s) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000468 if (drawState.isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000469 hasCoverage = true;
470 }
471 }
472
473 // if we don't have coverage we can check whether the dst
474 // has to read at all. If not, we'll disable blending.
475 if (!hasCoverage) {
476 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000477 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000478 // if there is no coverage and coeffs are (1,0) then we
479 // won't need to read the dst at all, it gets replaced by src
480 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000481 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000482 // if the op is "clear" then we don't need to emit a color
483 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000484 *srcCoeff = kOne_GrBlendCoeff;
485 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000486 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000487 }
488 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000489 } else if (drawState.isCoverageDrawing()) {
490 // we have coverage but we aren't distinguishing it from alpha by request.
491 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000492 } else {
493 // check whether coverage can be safely rolled into alpha
494 // of if we can skip color computation and just emit coverage
495 if (this->canTweakAlphaForCoverage()) {
496 return kCoverageAsAlpha_BlendOptFlag;
497 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000498 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000499 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000500 // the source color is not included in the blend
501 // the dst coeff is effectively zero so blend works out to:
502 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000503 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000504 return kEmitCoverage_BlendOptFlag;
505 } else if (srcAIsOne) {
506 // the dst coeff is effectively zero so blend works out to:
507 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000508 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000509 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000510 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000511 return kCoverageAsAlpha_BlendOptFlag;
512 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000513 } else if (dstCoeffIsOne) {
514 // the dst coeff is effectively one so blend works out to:
515 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000516 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000517 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000518 }
519 }
520 return kNone_BlendOpt;
521}
522
523bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000524 // there is a conflict between using smooth lines and our use of
525 // premultiplied alpha. Smooth lines tweak the incoming alpha value
526 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000527 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000528 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000529 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000530 return false;
531 }
532 BlendOptFlags opts = this->getBlendOpts();
533 return (kDisableBlend_BlendOptFlag & opts) &&
534 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000535}
536
537bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000538 // we can correctly apply coverage if a) we have dual source blending
539 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000540 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000541 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000542}
543
bsalomon@google.com934c5702012-03-20 21:17:58 +0000544////////////////////////////////////////////////////////////////////////////////
545
546void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
547 int instanceCount,
548 int verticesPerInstance,
549 int indicesPerInstance) {
550 if (!verticesPerInstance || !indicesPerInstance) {
551 return;
552 }
553
554 int instancesPerDraw = this->indexCountInCurrentSource() /
555 indicesPerInstance;
556 if (!instancesPerDraw) {
557 return;
558 }
559
560 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
561 int startVertex = 0;
562 while (instanceCount) {
563 this->drawIndexed(type,
564 startVertex,
565 0,
566 verticesPerInstance * instancesPerDraw,
567 indicesPerInstance * instancesPerDraw);
568 startVertex += verticesPerInstance;
569 instanceCount -= instancesPerDraw;
570 }
571}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000572
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000573////////////////////////////////////////////////////////////////////////////////
574
rmistry@google.comd6176b02012-08-23 18:14:13 +0000575void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000576 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000577 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000578 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000579 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000580
581 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000582 if (!geo.succeeded()) {
583 GrPrintf("Failed to get space for vertices!\n");
584 return;
585 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000586
rmistry@google.comd6176b02012-08-23 18:14:13 +0000587 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000588 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000589
bsalomon@google.com47059542012-06-06 20:51:20 +0000590 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000591}
592
bsalomon@google.come3d32162012-07-20 13:37:06 +0000593GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
594 if (NULL == srcRects) {
595 return 0;
596 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000597
bsalomon@google.come3d32162012-07-20 13:37:06 +0000598 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000599 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000600 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000601 if (NULL != srcRects[i]) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000602 layout |= GrDrawState::StageTexCoordVertexLayoutBit(i, numTC);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000603 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000604 }
605 }
606 return layout;
607}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +0000608
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000609// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000610// matrix - is applied to each vertex
611// srcRects - provide the uvs for each vertex
612// srcMatrices - are applied to the corresponding 'srcRect'
613// color - vertex color (replicated in each vertex)
614// layout - specifies which uvs and/or color are present
615// vertices - storage for the resulting vertices
616// Note: the color parameter will only be used when kColor_VertexLayoutBit
617// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000618void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000619 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000620 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000621 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000622 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000623 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000624 void* vertices) {
625#if GR_DEBUG
626 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +0000627 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
reed@google.com75847192013-01-28 20:53:22 +0000628 if (GrDrawState::VertexTexCoordsForStage(i, layout) >= 0) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000629 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
630 } else {
631 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
632 }
633 }
634#endif
635
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000636 int stageOffsets[GrDrawState::kNumStages], colorOffset;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000637 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,
638 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000639
bsalomon@google.coma3108262011-10-10 14:08:47 +0000640 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000641 rect.fRight, rect.fBottom,
642 vsize);
643 if (NULL != matrix) {
644 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
645 }
646
tomhudson@google.com93813632011-10-27 20:21:16 +0000647 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000648 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000649 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000650 stageOffsets[i]);
651 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000652 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000653 vsize);
654 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
655 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
656 }
657 }
658 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000659
jvanverth@google.comcc782382013-01-28 20:39:48 +0000660 if (colorOffset >= 0) {
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000661
662 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
663
664 for (int i = 0; i < 4; ++i) {
665 *vertCol = color;
666 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
667 }
668 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000669}
670
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000671void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
672}
673
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000674////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000675
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000676GrDrawTarget::AutoStateRestore::AutoStateRestore() {
677 fDrawTarget = NULL;
678}
reed@google.comac10a2d2010-12-22 21:39:39 +0000679
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000680GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
681 ASRInit init) {
682 fDrawTarget = NULL;
683 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000684}
685
686GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000687 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000688 fDrawTarget->setDrawState(fSavedState);
689 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000690 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000691}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000692
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000693void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
694 GrAssert(NULL == fDrawTarget);
695 fDrawTarget = target;
696 fSavedState = target->drawState();
697 GrAssert(fSavedState);
698 fSavedState->ref();
699 if (kReset_ASRInit == init) {
700 // calls the default cons
701 fTempState.init();
702 } else {
703 GrAssert(kPreserve_ASRInit == init);
704 // calls the copy cons
705 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000706 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000707 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000708}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000709
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000710////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000711
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
713 GrDrawTarget* target,
714 GrVertexLayout vertexLayout,
715 int vertexCount,
716 int indexCount) {
717 fTarget = NULL;
718 this->set(target, vertexLayout, vertexCount, indexCount);
719}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000720
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000721GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
722 fTarget = NULL;
723}
724
725GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
726 this->reset();
727}
728
729bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
730 GrVertexLayout vertexLayout,
731 int vertexCount,
732 int indexCount) {
733 this->reset();
734 fTarget = target;
735 bool success = true;
736 if (NULL != fTarget) {
737 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +0000738 success = target->reserveVertexAndIndexSpace(vertexLayout,
739 vertexCount,
740 indexCount,
741 &fVertices,
742 &fIndices);
743 if (!success) {
744 fTarget = NULL;
745 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000746 }
747 }
748 GrAssert(success == (NULL != fTarget));
749 return success;
750}
751
752void GrDrawTarget::AutoReleaseGeometry::reset() {
753 if (NULL != fTarget) {
754 if (NULL != fVertices) {
755 fTarget->resetVertexSource();
756 }
757 if (NULL != fIndices) {
758 fTarget->resetIndexSource();
759 }
760 fTarget = NULL;
761 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000762 fVertices = NULL;
763 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000764}
765
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000766GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
767 fTarget = target;
768 fClip = fTarget->getClip();
769 fStack.init();
770 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
771 fReplacementClip.fClipStack = fStack.get();
772 target->setClip(&fReplacementClip);
773}
774
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000775void GrDrawTarget::Caps::print() const {
776 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000777 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
778 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
779 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
780 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
781 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
782 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
783 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
784 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
785 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
786 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
787 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
788 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
789 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000790}