blob: 3898426af092b08babac313403a7fe9c3ffb9fc4 [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) {
344 if (indexCount > 0 &&
345 this->checkDraw(type, startVertex, startIndex,
346 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000347 this->onDrawIndexed(type, startVertex, startIndex,
348 vertexCount, indexCount);
349 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000350}
351
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000352void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
353 int startVertex,
354 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000355 if (vertexCount > 0 &&
356 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000357 this->onDrawNonIndexed(type, startVertex, vertexCount);
358 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000359}
360
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000361void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000362 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000363 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000364 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000365 GrAssert(!stroke.isHairlineStyle());
366 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000367 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000368}
369
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000370////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000371
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000372// Some blend modes allow folding a partial coverage value into the color's
373// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000374bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000375 /**
376 * The fractional coverage is f
377 * The src and dst coeffs are Cs and Cd
378 * The dst and src colors are S and D
379 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
380 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
381 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000382 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000383 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000384 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000385 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000386 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000387 return kOne_GrBlendCoeff == dstCoeff ||
388 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000389 kISC_GrBlendCoeff == dstCoeff ||
390 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000391}
392
bsalomon@google.come79c8152012-03-29 19:07:12 +0000393namespace {
394GrVertexLayout default_blend_opts_vertex_layout() {
395 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000396 return layout;
397}
398}
399
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000400GrDrawTarget::BlendOptFlags
401GrDrawTarget::getBlendOpts(bool forceCoverage,
402 GrBlendCoeff* srcCoeff,
403 GrBlendCoeff* dstCoeff) const {
404
bsalomon@google.come79c8152012-03-29 19:07:12 +0000405 GrVertexLayout layout;
406 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
407 layout = default_blend_opts_vertex_layout();
408 } else {
409 layout = this->getVertexLayout();
410 }
411
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000412 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000413
414 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
415 if (NULL == srcCoeff) {
416 srcCoeff = &bogusSrcCoeff;
417 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000418 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000419
420 if (NULL == dstCoeff) {
421 dstCoeff = &bogusDstCoeff;
422 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000423 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000424
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000425 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000426 *srcCoeff = kZero_GrBlendCoeff;
427 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000428 }
429
jvanverth@google.comcc782382013-01-28 20:39:48 +0000430 bool srcAIsOne = drawState.srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000431 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
432 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
433 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
434 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000435
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000436 bool covIsZero = !drawState.isCoverageDrawing() &&
jvanverth@google.comcc782382013-01-28 20:39:48 +0000437 !(layout & GrDrawState::kCoverage_VertexLayoutBit) &&
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000438 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000439 // When coeffs are (0,1) there is no reason to draw at all, unless
440 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000441 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000442 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000443 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000444 return kDisableBlend_BlendOptFlag |
445 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000446 } else {
447 return kSkipDraw_BlendOptFlag;
448 }
449 }
450
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000451 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000452 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000453 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000454 0xffffffff != drawState.getCoverage() ||
jvanverth@google.comcc782382013-01-28 20:39:48 +0000455 (layout & GrDrawState::kCoverage_VertexLayoutBit) ||
456 (layout & GrDrawState::kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000457 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000458 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000459 ++s) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000460 if (drawState.isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000461 hasCoverage = true;
462 }
463 }
464
465 // if we don't have coverage we can check whether the dst
466 // has to read at all. If not, we'll disable blending.
467 if (!hasCoverage) {
468 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000469 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000470 // if there is no coverage and coeffs are (1,0) then we
471 // won't need to read the dst at all, it gets replaced by src
472 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000473 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000474 // if the op is "clear" then we don't need to emit a color
475 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000476 *srcCoeff = kOne_GrBlendCoeff;
477 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000478 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000479 }
480 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000481 } else if (drawState.isCoverageDrawing()) {
482 // we have coverage but we aren't distinguishing it from alpha by request.
483 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000484 } else {
485 // check whether coverage can be safely rolled into alpha
486 // of if we can skip color computation and just emit coverage
487 if (this->canTweakAlphaForCoverage()) {
488 return kCoverageAsAlpha_BlendOptFlag;
489 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000490 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000491 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000492 // the source color is not included in the blend
493 // the dst coeff is effectively zero so blend works out to:
494 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000495 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000496 return kEmitCoverage_BlendOptFlag;
497 } else if (srcAIsOne) {
498 // the dst coeff is effectively zero so blend works out to:
499 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000500 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000501 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000502 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000503 return kCoverageAsAlpha_BlendOptFlag;
504 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000505 } else if (dstCoeffIsOne) {
506 // the dst coeff is effectively one so blend works out to:
507 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000508 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000509 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000510 }
511 }
512 return kNone_BlendOpt;
513}
514
515bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000516 // there is a conflict between using smooth lines and our use of
517 // premultiplied alpha. Smooth lines tweak the incoming alpha value
518 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000519 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000520 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000521 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000522 return false;
523 }
524 BlendOptFlags opts = this->getBlendOpts();
525 return (kDisableBlend_BlendOptFlag & opts) &&
526 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000527}
528
529bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000530 // we can correctly apply coverage if a) we have dual source blending
531 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000532 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000533 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000534}
535
bsalomon@google.com934c5702012-03-20 21:17:58 +0000536////////////////////////////////////////////////////////////////////////////////
537
538void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
539 int instanceCount,
540 int verticesPerInstance,
541 int indicesPerInstance) {
542 if (!verticesPerInstance || !indicesPerInstance) {
543 return;
544 }
545
546 int instancesPerDraw = this->indexCountInCurrentSource() /
547 indicesPerInstance;
548 if (!instancesPerDraw) {
549 return;
550 }
551
552 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
553 int startVertex = 0;
554 while (instanceCount) {
555 this->drawIndexed(type,
556 startVertex,
557 0,
558 verticesPerInstance * instancesPerDraw,
559 indicesPerInstance * instancesPerDraw);
560 startVertex += verticesPerInstance;
561 instanceCount -= instancesPerDraw;
562 }
563}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000564
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000565////////////////////////////////////////////////////////////////////////////////
566
rmistry@google.comd6176b02012-08-23 18:14:13 +0000567void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000568 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000569 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000570 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +0000571 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000572
573 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +0000574 if (!geo.succeeded()) {
575 GrPrintf("Failed to get space for vertices!\n");
576 return;
577 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000578
rmistry@google.comd6176b02012-08-23 18:14:13 +0000579 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000580 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000581
bsalomon@google.com47059542012-06-06 20:51:20 +0000582 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000583}
584
bsalomon@google.come3d32162012-07-20 13:37:06 +0000585GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
586 if (NULL == srcRects) {
587 return 0;
588 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000589
bsalomon@google.come3d32162012-07-20 13:37:06 +0000590 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000591 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000592 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +0000593 if (NULL != srcRects[i]) {
jvanverth@google.comcc782382013-01-28 20:39:48 +0000594 layout |= GrDrawState::StageTexCoordVertexLayoutBit(i, numTC);
bsalomon@google.come3d32162012-07-20 13:37:06 +0000595 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000596 }
597 }
598 return layout;
599}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +0000600
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +0000601// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000602// matrix - is applied to each vertex
603// srcRects - provide the uvs for each vertex
604// srcMatrices - are applied to the corresponding 'srcRect'
605// color - vertex color (replicated in each vertex)
606// layout - specifies which uvs and/or color are present
607// vertices - storage for the resulting vertices
608// Note: the color parameter will only be used when kColor_VertexLayoutBit
609// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000610void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000611 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000612 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000613 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000614 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000615 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000616 void* vertices) {
617#if GR_DEBUG
618 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +0000619 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
reed@google.com75847192013-01-28 20:53:22 +0000620 if (GrDrawState::VertexTexCoordsForStage(i, layout) >= 0) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000621 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
622 } else {
623 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
624 }
625 }
626#endif
627
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000628 int stageOffsets[GrDrawState::kNumStages], colorOffset;
jvanverth@google.comcc782382013-01-28 20:39:48 +0000629 int vsize = GrDrawState::VertexSizeAndOffsetsByStage(layout, stageOffsets,
630 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000631
bsalomon@google.coma3108262011-10-10 14:08:47 +0000632 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000633 rect.fRight, rect.fBottom,
634 vsize);
635 if (NULL != matrix) {
636 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
637 }
638
tomhudson@google.com93813632011-10-27 20:21:16 +0000639 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000640 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000641 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000642 stageOffsets[i]);
643 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000644 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000645 vsize);
646 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
647 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
648 }
649 }
650 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000651
jvanverth@google.comcc782382013-01-28 20:39:48 +0000652 if (colorOffset >= 0) {
robertphillips@google.com8b129aa2012-10-05 15:37:00 +0000653
654 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
655
656 for (int i = 0; i < 4; ++i) {
657 *vertCol = color;
658 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
659 }
660 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000661}
662
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000663void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
664}
665
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000666////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000667
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000668GrDrawTarget::AutoStateRestore::AutoStateRestore() {
669 fDrawTarget = NULL;
670}
reed@google.comac10a2d2010-12-22 21:39:39 +0000671
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000672GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
673 ASRInit init) {
674 fDrawTarget = NULL;
675 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +0000676}
677
678GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000679 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000680 fDrawTarget->setDrawState(fSavedState);
681 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000682 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000683}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000684
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000685void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
686 GrAssert(NULL == fDrawTarget);
687 fDrawTarget = target;
688 fSavedState = target->drawState();
689 GrAssert(fSavedState);
690 fSavedState->ref();
691 if (kReset_ASRInit == init) {
692 // calls the default cons
693 fTempState.init();
694 } else {
695 GrAssert(kPreserve_ASRInit == init);
696 // calls the copy cons
697 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000698 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +0000699 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000700}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000701
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000702////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000703
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000704GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
705 GrDrawTarget* target,
706 GrVertexLayout vertexLayout,
707 int vertexCount,
708 int indexCount) {
709 fTarget = NULL;
710 this->set(target, vertexLayout, vertexCount, indexCount);
711}
rmistry@google.comd6176b02012-08-23 18:14:13 +0000712
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
714 fTarget = NULL;
715}
716
717GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
718 this->reset();
719}
720
721bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
722 GrVertexLayout vertexLayout,
723 int vertexCount,
724 int indexCount) {
725 this->reset();
726 fTarget = target;
727 bool success = true;
728 if (NULL != fTarget) {
729 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +0000730 success = target->reserveVertexAndIndexSpace(vertexLayout,
731 vertexCount,
732 indexCount,
733 &fVertices,
734 &fIndices);
735 if (!success) {
736 fTarget = NULL;
737 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000738 }
739 }
740 GrAssert(success == (NULL != fTarget));
741 return success;
742}
743
744void GrDrawTarget::AutoReleaseGeometry::reset() {
745 if (NULL != fTarget) {
746 if (NULL != fVertices) {
747 fTarget->resetVertexSource();
748 }
749 if (NULL != fIndices) {
750 fTarget->resetIndexSource();
751 }
752 fTarget = NULL;
753 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +0000754 fVertices = NULL;
755 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000756}
757
bsalomon@google.com8d67c072012-12-13 20:38:14 +0000758GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
759 fTarget = target;
760 fClip = fTarget->getClip();
761 fStack.init();
762 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
763 fReplacementClip.fClipStack = fStack.get();
764 target->setClip(&fReplacementClip);
765}
766
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000767void GrDrawTarget::Caps::print() const {
768 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +0000769 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
770 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
771 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
772 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
773 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
774 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
775 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
776 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
777 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
778 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
779 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
780 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
781 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +0000782}