blob: ff8b9daf57ad94eec27848dda8e25c36fa1743de [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.com8531c1c2011-01-13 19:52:45 +000026#if GR_DEBUG
27 VertexLayoutUnitTest();
28#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000029 fDrawState = &fDefaultDrawState;
30 // We assume that fDrawState always owns a ref to the object it points at.
31 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000032 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +000033#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000034 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
35 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
36 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
37 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +000038#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000039 geoSrc.fVertexSrc = kNone_GeometrySrcType;
40 geoSrc.fIndexSrc = kNone_GeometrySrcType;
41}
42
43GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000044 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +000045 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000046 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
47 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000048 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000049}
50
51void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000052 int popCnt = fGeoSrcStateStack.count() - 1;
53 while (popCnt) {
54 this->popGeometrySource();
55 --popCnt;
56 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +000057 this->resetVertexSource();
58 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +000059}
60
robertphillips@google.combeb1af72012-07-26 18:52:16 +000061void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000062 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +000063 fClip = clip;
64}
65
robertphillips@google.combeb1af72012-07-26 18:52:16 +000066const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000067 return fClip;
68}
69
bsalomon@google.coma5d056a2012-03-27 15:59:58 +000070void GrDrawTarget::setDrawState(GrDrawState* drawState) {
71 GrAssert(NULL != fDrawState);
72 if (NULL == drawState) {
73 drawState = &fDefaultDrawState;
74 }
75 if (fDrawState != drawState) {
76 fDrawState->unref();
77 drawState->ref();
78 fDrawState = drawState;
79 }
80}
81
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000082bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
83 int vertexCount,
84 void** vertices) {
85 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
86 bool acquired = false;
87 if (vertexCount > 0) {
88 GrAssert(NULL != vertices);
89 this->releasePreviousVertexSource();
90 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +000091
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000092 acquired = this->onReserveVertexSpace(vertexLayout,
93 vertexCount,
94 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +000095 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000096 if (acquired) {
97 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
98 geoSrc.fVertexCount = vertexCount;
99 geoSrc.fVertexLayout = vertexLayout;
100 } else if (NULL != vertices) {
101 *vertices = NULL;
102 }
103 return acquired;
104}
105
106bool GrDrawTarget::reserveIndexSpace(int indexCount,
107 void** indices) {
108 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
109 bool acquired = false;
110 if (indexCount > 0) {
111 GrAssert(NULL != indices);
112 this->releasePreviousIndexSource();
113 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000114
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000115 acquired = this->onReserveIndexSpace(indexCount, indices);
116 }
117 if (acquired) {
118 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
119 geoSrc.fIndexCount = indexCount;
120 } else if (NULL != indices) {
121 *indices = NULL;
122 }
123 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000124
reed@google.comac10a2d2010-12-22 21:39:39 +0000125}
126
bsalomon@google.come3d70952012-03-13 12:40:53 +0000127bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
128 int vertexCount,
129 int indexCount,
130 void** vertices,
131 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000132 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000133 if (vertexCount) {
134 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
135 if (indexCount) {
136 this->resetIndexSource();
137 }
138 return false;
139 }
140 }
141 if (indexCount) {
142 if (!this->reserveIndexSpace(indexCount, indices)) {
143 if (vertexCount) {
144 this->resetVertexSource();
145 }
146 return false;
147 }
148 }
149 return true;
150}
151
reed@google.comac10a2d2010-12-22 21:39:39 +0000152bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
153 int32_t* vertexCount,
154 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 if (NULL != vertexCount) {
156 *vertexCount = -1;
157 }
158 if (NULL != indexCount) {
159 *indexCount = -1;
160 }
161 return false;
162}
163
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000164void GrDrawTarget::releasePreviousVertexSource() {
165 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
166 switch (geoSrc.fVertexSrc) {
167 case kNone_GeometrySrcType:
168 break;
169 case kArray_GeometrySrcType:
170 this->releaseVertexArray();
171 break;
172 case kReserved_GeometrySrcType:
173 this->releaseReservedVertexSpace();
174 break;
175 case kBuffer_GeometrySrcType:
176 geoSrc.fVertexBuffer->unref();
177#if GR_DEBUG
178 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
179#endif
180 break;
181 default:
182 GrCrash("Unknown Vertex Source Type.");
183 break;
184 }
185}
186
187void GrDrawTarget::releasePreviousIndexSource() {
188 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
189 switch (geoSrc.fIndexSrc) {
190 case kNone_GeometrySrcType: // these two don't require
191 break;
192 case kArray_GeometrySrcType:
193 this->releaseIndexArray();
194 break;
195 case kReserved_GeometrySrcType:
196 this->releaseReservedIndexSpace();
197 break;
198 case kBuffer_GeometrySrcType:
199 geoSrc.fIndexBuffer->unref();
200#if GR_DEBUG
201 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
202#endif
203 break;
204 default:
205 GrCrash("Unknown Index Source Type.");
206 break;
207 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000208}
209
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000210void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
211 const void* vertexArray,
212 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000213 this->releasePreviousVertexSource();
214 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
215 geoSrc.fVertexSrc = kArray_GeometrySrcType;
216 geoSrc.fVertexLayout = vertexLayout;
217 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000218 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000219}
220
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000221void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
222 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000223 this->releasePreviousIndexSource();
224 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
225 geoSrc.fIndexSrc = kArray_GeometrySrcType;
226 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000227 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000228}
229
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000230void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
231 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000232 this->releasePreviousVertexSource();
233 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
234 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
235 geoSrc.fVertexBuffer = buffer;
236 buffer->ref();
237 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000238}
239
240void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000241 this->releasePreviousIndexSource();
242 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
243 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
244 geoSrc.fIndexBuffer = buffer;
245 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000246}
247
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000248void GrDrawTarget::resetVertexSource() {
249 this->releasePreviousVertexSource();
250 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
251 geoSrc.fVertexSrc = kNone_GeometrySrcType;
252}
253
254void GrDrawTarget::resetIndexSource() {
255 this->releasePreviousIndexSource();
256 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
257 geoSrc.fIndexSrc = kNone_GeometrySrcType;
258}
259
260void GrDrawTarget::pushGeometrySource() {
261 this->geometrySourceWillPush();
262 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
263 newState.fIndexSrc = kNone_GeometrySrcType;
264 newState.fVertexSrc = kNone_GeometrySrcType;
265#if GR_DEBUG
266 newState.fVertexCount = ~0;
267 newState.fVertexBuffer = (GrVertexBuffer*)~0;
268 newState.fIndexCount = ~0;
269 newState.fIndexBuffer = (GrIndexBuffer*)~0;
270#endif
271}
272
273void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000274 // if popping last element then pops are unbalanced with pushes
275 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000276
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000277 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
278 this->releasePreviousVertexSource();
279 this->releasePreviousIndexSource();
280 fGeoSrcStateStack.pop_back();
281}
282
283////////////////////////////////////////////////////////////////////////////////
284
bsalomon@google.come8262622011-11-07 02:30:51 +0000285bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
286 int startIndex, int vertexCount,
287 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000288 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000289#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000290 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000291 int maxVertex = startVertex + vertexCount;
292 int maxValidVertex;
293 switch (geoSrc.fVertexSrc) {
294 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000295 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000296 case kReserved_GeometrySrcType: // fallthrough
297 case kArray_GeometrySrcType:
298 maxValidVertex = geoSrc.fVertexCount;
299 break;
300 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000301 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000302 break;
303 }
304 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000305 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000306 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000307 if (indexCount > 0) {
308 int maxIndex = startIndex + indexCount;
309 int maxValidIndex;
310 switch (geoSrc.fIndexSrc) {
311 case kNone_GeometrySrcType:
312 GrCrash("Attempting to draw indexed geom without index src.");
313 case kReserved_GeometrySrcType: // fallthrough
314 case kArray_GeometrySrcType:
315 maxValidIndex = geoSrc.fIndexCount;
316 break;
317 case kBuffer_GeometrySrcType:
318 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
319 break;
320 }
321 if (maxIndex > maxValidIndex) {
322 GrCrash("Index reads outside valid index range.");
323 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000324 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000325
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000326 GrAssert(NULL != drawState.getRenderTarget());
327 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
328 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000329 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000330 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000331 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000332 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000333 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
334 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000335 }
336 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000337#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000338 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000339 return false;
340 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000341 return true;
342}
343
344void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
345 int startIndex, int vertexCount,
346 int indexCount) {
347 if (indexCount > 0 &&
348 this->checkDraw(type, startVertex, startIndex,
349 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000350 this->onDrawIndexed(type, startVertex, startIndex,
351 vertexCount, indexCount);
352 }
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.come8262622011-11-07 02:30:51 +0000358 if (vertexCount > 0 &&
359 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000360 this->onDrawNonIndexed(type, startVertex, vertexCount);
361 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000362}
363
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000364void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000365 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000366 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000367 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000368 GrAssert(!stroke.isHairlineStyle());
369 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000370 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000371}
372
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000373////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000374
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000375// Some blend modes allow folding a partial coverage value into the color's
376// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000377bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000378 /**
379 * The fractional coverage is f
380 * The src and dst coeffs are Cs and Cd
381 * The dst and src colors are S and D
382 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
383 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
384 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000385 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000386 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000387 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000388 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000389 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000390 return kOne_GrBlendCoeff == dstCoeff ||
391 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000392 kISC_GrBlendCoeff == dstCoeff ||
393 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000394}
395
bsalomon@google.come79c8152012-03-29 19:07:12 +0000396namespace {
397GrVertexLayout default_blend_opts_vertex_layout() {
398 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000399 return layout;
400}
401}
402
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000403GrDrawTarget::BlendOptFlags
404GrDrawTarget::getBlendOpts(bool forceCoverage,
405 GrBlendCoeff* srcCoeff,
406 GrBlendCoeff* dstCoeff) const {
407
bsalomon@google.come79c8152012-03-29 19:07:12 +0000408 GrVertexLayout layout;
409 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
410 layout = default_blend_opts_vertex_layout();
411 } else {
412 layout = this->getVertexLayout();
413 }
414
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000415 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000416
417 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
418 if (NULL == srcCoeff) {
419 srcCoeff = &bogusSrcCoeff;
420 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000421 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000422
423 if (NULL == dstCoeff) {
424 dstCoeff = &bogusDstCoeff;
425 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000426 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000427
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000428 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000429 *srcCoeff = kZero_GrBlendCoeff;
430 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000431 }
432
jvanverth@google.comcc782382013-01-28 20:39:48 +0000433 bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000434 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
435 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
436 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
437 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000438
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000439 bool covIsZero = !drawState.isCoverageDrawing() &&
jvanverth@google.comcc782382013-01-28 20:39:48 +0000440 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000441 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000442 // When coeffs are (0,1) there is no reason to draw at all, unless
443 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000444 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000445 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000446 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000447 return kDisableBlend_BlendOptFlag |
448 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000449 } else {
450 return kSkipDraw_BlendOptFlag;
451 }
452 }
453
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000454 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000455 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000456 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000457 0xffffffff != drawState.getCoverage() ||
jvanverth@google.comcc782382013-01-28 20:39:48 +0000458 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
459 (layout & GrDrawState::kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000460 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000461 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000462 ++s) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000463 if (drawState.isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000464 hasCoverage = true;
465 }
466 }
467
468 // if we don't have coverage we can check whether the dst
469 // has to read at all. If not, we'll disable blending.
470 if (!hasCoverage) {
471 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000472 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000473 // if there is no coverage and coeffs are (1,0) then we
474 // won't need to read the dst at all, it gets replaced by src
475 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000476 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000477 // if the op is "clear" then we don't need to emit a color
478 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000479 *srcCoeff = kOne_GrBlendCoeff;
480 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000481 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000482 }
483 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000484 } else if (drawState.isCoverageDrawing()) {
485 // we have coverage but we aren't distinguishing it from alpha by request.
486 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000487 } else {
488 // check whether coverage can be safely rolled into alpha
489 // of if we can skip color computation and just emit coverage
490 if (this->canTweakAlphaForCoverage()) {
491 return kCoverageAsAlpha_BlendOptFlag;
492 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000493 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000494 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000495 // the source color is not included in the blend
496 // the dst coeff is effectively zero so blend works out to:
497 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000498 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000499 return kEmitCoverage_BlendOptFlag;
500 } else if (srcAIsOne) {
501 // the dst coeff is effectively zero so blend works out to:
502 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000503 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000504 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000505 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000506 return kCoverageAsAlpha_BlendOptFlag;
507 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000508 } else if (dstCoeffIsOne) {
509 // the dst coeff is effectively one so blend works out to:
510 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000511 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000512 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000513 }
514 }
515 return kNone_BlendOpt;
516}
517
518bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000519 // there is a conflict between using smooth lines and our use of
520 // premultiplied alpha. Smooth lines tweak the incoming alpha value
521 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000522 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000523 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000524 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000525 return false;
526 }
527 BlendOptFlags opts = this->getBlendOpts();
528 return (kDisableBlend_BlendOptFlag & opts) &&
529 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000530}
531
532bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000533 // we can correctly apply coverage if a) we have dual source blending
534 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000535 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000536 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000537}
538
bsalomon@google.com934c5702012-03-20 21:17:58 +0000539////////////////////////////////////////////////////////////////////////////////
540
541void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
542 int instanceCount,
543 int verticesPerInstance,
544 int indicesPerInstance) {
545 if (!verticesPerInstance || !indicesPerInstance) {
546 return;
547 }
548
549 int instancesPerDraw = this->indexCountInCurrentSource() /
550 indicesPerInstance;
551 if (!instancesPerDraw) {
552 return;
553 }
554
555 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
556 int startVertex = 0;
557 while (instanceCount) {
558 this->drawIndexed(type,
559 startVertex,
560 0,
561 verticesPerInstance * instancesPerDraw,
562 indicesPerInstance * instancesPerDraw);
563 startVertex += verticesPerInstance;
564 instanceCount -= instancesPerDraw;
565 }
566}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000567
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000568////////////////////////////////////////////////////////////////////////////////
569
rmistry@google.comd6176b02012-08-23 18:14:13 +0000570void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000571 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000572 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000573 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000574 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000575
576 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000577 if (!geo.succeeded()) {
578 GrPrintf("Failed to get space for vertices!\n");
579 return;
580 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000581
rmistry@google.comd6176b02012-08-23 18:14:13 +0000582 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000583 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000584
bsalomon@google.com47059542012-06-06 20:51:20 +0000585 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000586}
587
bsalomon@google.come3d32162012-07-20 13:37:06 +0000588GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
589 if (NULL == srcRects) {
590 return 0;
591 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000592
bsalomon@google.come3d32162012-07-20 13:37:06 +0000593 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000594 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000595 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000596 if (NULL != srcRects[i]) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000597 layout |= GrDrawState::StageTexCoordVertexLayoutBit(i, numTC);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000598 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000599 }
600 }
601 return layout;
602}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +0000603
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000604// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000605// matrix - is applied to each vertex
606// srcRects - provide the uvs for each vertex
607// srcMatrices - are applied to the corresponding 'srcRect'
608// color - vertex color (replicated in each vertex)
609// layout - specifies which uvs and/or color are present
610// vertices - storage for the resulting vertices
611// Note: the color parameter will only be used when kColor_VertexLayoutBit
612// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000613void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000614 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000615 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000616 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000617 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000618 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000619 void* vertices) {
620#if GR_DEBUG
621 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +0000622 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000623 if (VertexTexCoordsForStage(i, layout) >= 0) {
624 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
625 } else {
626 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
627 }
628 }
629#endif
630
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000631 int stageOffsets[GrDrawState::kNumStages], colorOffset;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000632 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,
633 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000634
bsalomon@google.coma3108262011-10-10 14:08:47 +0000635 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000636 rect.fRight, rect.fBottom,
637 vsize);
638 if (NULL != matrix) {
639 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
640 }
641
tomhudson@google.com93813632011-10-27 20:21:16 +0000642 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000643 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000644 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000645 stageOffsets[i]);
646 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000647 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000648 vsize);
649 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
650 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
651 }
652 }
653 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000654
jvanverth@google.comcc782382013-01-28 20:39:48 +0000655 if (colorOffset >= 0) {
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000656
657 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
658
659 for (int i = 0; i < 4; ++i) {
660 *vertCol = color;
661 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
662 }
663 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000664}
665
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000666void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
667}
668
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000669////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000670
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000671GrDrawTarget::AutoStateRestore::AutoStateRestore() {
672 fDrawTarget = NULL;
673}
reed@google.comac10a2d2010-12-22 21:39:39 +0000674
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000675GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
676 ASRInit init) {
677 fDrawTarget = NULL;
678 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000679}
680
681GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000682 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000683 fDrawTarget->setDrawState(fSavedState);
684 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000685 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000686}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000687
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000688void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
689 GrAssert(NULL == fDrawTarget);
690 fDrawTarget = target;
691 fSavedState = target->drawState();
692 GrAssert(fSavedState);
693 fSavedState->ref();
694 if (kReset_ASRInit == init) {
695 // calls the default cons
696 fTempState.init();
697 } else {
698 GrAssert(kPreserve_ASRInit == init);
699 // calls the copy cons
700 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000701 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000702 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000703}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000704
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000705////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000706
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000707GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
708 GrDrawTarget* target,
709 GrVertexLayout vertexLayout,
710 int vertexCount,
711 int indexCount) {
712 fTarget = NULL;
713 this->set(target, vertexLayout, vertexCount, indexCount);
714}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000715
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000716GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
717 fTarget = NULL;
718}
719
720GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
721 this->reset();
722}
723
724bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
725 GrVertexLayout vertexLayout,
726 int vertexCount,
727 int indexCount) {
728 this->reset();
729 fTarget = target;
730 bool success = true;
731 if (NULL != fTarget) {
732 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +0000733 success = target->reserveVertexAndIndexSpace(vertexLayout,
734 vertexCount,
735 indexCount,
736 &fVertices,
737 &fIndices);
738 if (!success) {
739 fTarget = NULL;
740 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000741 }
742 }
743 GrAssert(success == (NULL != fTarget));
744 return success;
745}
746
747void GrDrawTarget::AutoReleaseGeometry::reset() {
748 if (NULL != fTarget) {
749 if (NULL != fVertices) {
750 fTarget->resetVertexSource();
751 }
752 if (NULL != fIndices) {
753 fTarget->resetIndexSource();
754 }
755 fTarget = NULL;
756 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000757 fVertices = NULL;
758 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000759}
760
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000761GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
762 fTarget = target;
763 fClip = fTarget->getClip();
764 fStack.init();
765 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
766 fReplacementClip.fClipStack = fStack.get();
767 target->setClip(&fReplacementClip);
768}
769
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000770void GrDrawTarget::Caps::print() const {
771 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000772 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
773 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
774 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
775 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
776 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
777 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
778 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
779 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
780 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
781 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
782 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
783 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
784 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000785}