blob: 7a84262d20849194eb121c80ee2e044591359588 [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"
12#include "GrGpuVertex.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"
15#include "GrIndexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
junov@google.com6acc9b32011-05-16 18:32:07 +000017namespace {
18
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000019// recursive helper for creating mask with all the tex coord bits set for
20// one stage
21template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000022int stage_mask_recur(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000023 return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024 stage_mask_recur<N+1>(stage);
25}
junov@google.com6acc9b32011-05-16 18:32:07 +000026template<>
tomhudson@google.com93813632011-10-27 20:21:16 +000027int stage_mask_recur<GrDrawState::kNumStages>(int) { return 0; }
reed@google.comac10a2d2010-12-22 21:39:39 +000028
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000029// mask of all tex coord indices for one stage
junov@google.com6acc9b32011-05-16 18:32:07 +000030int stage_tex_coord_mask(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000031 return stage_mask_recur<0>(stage);
reed@google.comac10a2d2010-12-22 21:39:39 +000032}
33
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000034// mask of all bits relevant to one stage
junov@google.com6acc9b32011-05-16 18:32:07 +000035int stage_mask(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000036 return stage_tex_coord_mask(stage) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000037 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage);
38}
39
40// recursive helper for creating mask of with all bits set relevant to one
41// texture coordinate index
42template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000043int tex_coord_mask_recur(int texCoordIdx) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000044 return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000045 tex_coord_mask_recur<N+1>(texCoordIdx);
46}
junov@google.com6acc9b32011-05-16 18:32:07 +000047template<>
tomhudson@google.com93813632011-10-27 20:21:16 +000048int tex_coord_mask_recur<GrDrawState::kMaxTexCoords>(int) { return 0; }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000049
50// mask of all bits relevant to one texture coordinate index
junov@google.com6acc9b32011-05-16 18:32:07 +000051int tex_coord_idx_mask(int texCoordIdx) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000052 return tex_coord_mask_recur<0>(texCoordIdx);
53}
54
55bool check_layout(GrVertexLayout layout) {
56 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000057 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000058 int stageBits = layout & stage_mask(s);
59 if (stageBits && !GrIsPow2(stageBits)) {
60 return false;
61 }
62 }
63 return true;
64}
65
bsalomon@google.comaeb21602011-08-30 18:13:44 +000066int num_tex_coords(GrVertexLayout layout) {
67 int cnt = 0;
68 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +000069 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +000070 if (tex_coord_idx_mask(t) & layout) {
71 ++cnt;
72 }
73 }
74 return cnt;
75}
76
junov@google.com6acc9b32011-05-16 18:32:07 +000077} //unnamed namespace
78
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000079size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
80 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +000081
82 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000083 sizeof(GrGpuTextVertex) :
84 sizeof(GrPoint);
85
86 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +000087 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000088 if (vertexLayout & kColor_VertexLayoutBit) {
89 size += sizeof(GrColor);
90 }
bsalomon@google.coma3108262011-10-10 14:08:47 +000091 if (vertexLayout & kCoverage_VertexLayoutBit) {
92 size += sizeof(GrColor);
93 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +000094 if (vertexLayout & kEdge_VertexLayoutBit) {
95 size += 4 * sizeof(GrScalar);
96 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097 return size;
98}
99
bsalomon@google.coma3108262011-10-10 14:08:47 +0000100////////////////////////////////////////////////////////////////////////////////
101
102/**
103 * Functions for computing offsets of various components from the layout
104 * bitfield.
105 *
106 * Order of vertex components:
107 * Position
108 * Tex Coord 0
109 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000110 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000111 * Color
112 * Coverage
113 */
114
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000115int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
116 GrAssert(check_layout(vertexLayout));
117 if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000118 return 0;
119 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000120 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
121 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000122
123 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000124 sizeof(GrGpuTextVertex) :
125 sizeof(GrPoint);
126 int offset = vecSize; // position
127 // figure out how many tex coordinates are present and precede this one.
128 for (int t = 0; t < tcIdx; ++t) {
129 if (tex_coord_idx_mask(t) & vertexLayout) {
130 offset += vecSize;
131 }
132 }
133 return offset;
134 }
135
reed@google.comac10a2d2010-12-22 21:39:39 +0000136 return -1;
137}
138
139int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000140 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000141
reed@google.comac10a2d2010-12-22 21:39:39 +0000142 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000143 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000144 sizeof(GrGpuTextVertex) :
145 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000146 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
147 }
148 return -1;
149}
150
bsalomon@google.coma3108262011-10-10 14:08:47 +0000151int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
152 GrAssert(check_layout(vertexLayout));
153
154 if (vertexLayout & kCoverage_VertexLayoutBit) {
155 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
156 sizeof(GrGpuTextVertex) :
157 sizeof(GrPoint);
158
159 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
160 if (vertexLayout & kColor_VertexLayoutBit) {
161 offset += sizeof(GrColor);
162 }
163 return offset;
164 }
165 return -1;
166}
167
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000168int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
169 GrAssert(check_layout(vertexLayout));
170
171 // edge pts are after the pos, tex coords, and color
172 if (vertexLayout & kEdge_VertexLayoutBit) {
173 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
174 sizeof(GrGpuTextVertex) :
175 sizeof(GrPoint);
176 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
177 if (vertexLayout & kColor_VertexLayoutBit) {
178 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000180 if (vertexLayout & kCoverage_VertexLayoutBit) {
181 offset += sizeof(GrColor);
182 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000183 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 }
185 return -1;
186}
187
tomhudson@google.com93813632011-10-27 20:21:16 +0000188int GrDrawTarget::VertexSizeAndOffsetsByIdx(
189 GrVertexLayout vertexLayout,
190 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
191 int* colorOffset,
192 int* coverageOffset,
193 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000194 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000195
bsalomon@google.com5782d712011-01-21 21:03:59 +0000196 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000197 sizeof(GrGpuTextVertex) :
198 sizeof(GrPoint);
199 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000200
tomhudson@google.com93813632011-10-27 20:21:16 +0000201 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000202 if (tex_coord_idx_mask(t) & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000203 if (NULL != texCoordOffsetsByIdx) {
204 texCoordOffsetsByIdx[t] = size;
205 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000206 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000207 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000208 if (NULL != texCoordOffsetsByIdx) {
209 texCoordOffsetsByIdx[t] = -1;
210 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000212 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000213 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000214 if (NULL != colorOffset) {
215 *colorOffset = size;
216 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000217 size += sizeof(GrColor);
218 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000219 if (NULL != colorOffset) {
220 *colorOffset = -1;
221 }
222 }
223 if (kCoverage_VertexLayoutBit & vertexLayout) {
224 if (NULL != coverageOffset) {
225 *coverageOffset = size;
226 }
227 size += sizeof(GrColor);
228 } else {
229 if (NULL != coverageOffset) {
230 *coverageOffset = -1;
231 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000232 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000233 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000234 if (NULL != edgeOffset) {
235 *edgeOffset = size;
236 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000237 size += 4 * sizeof(GrScalar);
238 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000239 if (NULL != edgeOffset) {
240 *edgeOffset = -1;
241 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000242 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000243 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000244}
245
tomhudson@google.com93813632011-10-27 20:21:16 +0000246int GrDrawTarget::VertexSizeAndOffsetsByStage(
247 GrVertexLayout vertexLayout,
248 int texCoordOffsetsByStage[GrDrawState::kNumStages],
249 int* colorOffset,
250 int* coverageOffset,
251 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252 GrAssert(check_layout(vertexLayout));
253
tomhudson@google.com93813632011-10-27 20:21:16 +0000254 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000255 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000256 (NULL == texCoordOffsetsByStage) ?
257 NULL :
258 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000259 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000260 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000261 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000262 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000263 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000264 int tcIdx;
265 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
266 texCoordOffsetsByStage[s] = 0;
267 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
268 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
269 } else {
270 texCoordOffsetsByStage[s] = -1;
271 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000272 }
273 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000274 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000275}
276
bsalomon@google.coma3108262011-10-10 14:08:47 +0000277////////////////////////////////////////////////////////////////////////////////
278
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000279bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000280 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000281 GrAssert(check_layout(vertexLayout));
282 return !!(stage_mask(stage) & vertexLayout);
283}
284
bsalomon@google.com5782d712011-01-21 21:03:59 +0000285bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000286 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000287 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000288 GrAssert(check_layout(vertexLayout));
289 return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
290}
291
tomhudson@google.com93813632011-10-27 20:21:16 +0000292int GrDrawTarget::VertexTexCoordsForStage(int stage,
293 GrVertexLayout vertexLayout) {
294 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000295 GrAssert(check_layout(vertexLayout));
296 int bit = vertexLayout & stage_tex_coord_mask(stage);
297 if (bit) {
298 // figure out which set of texture coordates is used
299 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
300 // and start at bit 0.
301 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000302 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303 }
304 return -1;
305}
306
bsalomon@google.coma3108262011-10-10 14:08:47 +0000307////////////////////////////////////////////////////////////////////////////////
308
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000309void GrDrawTarget::VertexLayoutUnitTest() {
310 // not necessarily exhaustive
311 static bool run;
312 if (!run) {
313 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000314 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000315
316 GrAssert(!VertexUsesStage(s, 0));
317 GrAssert(-1 == VertexStageCoordOffset(s, 0));
318 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000319 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000320 stageMask |= StageTexCoordVertexLayoutBit(s,t);
321 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000322 GrAssert(1 == GrDrawState::kMaxTexCoords ||
323 !check_layout(stageMask));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000324 GrAssert(stage_tex_coord_mask(s) == stageMask);
325 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
326 GrAssert(stage_mask(s) == stageMask);
327 GrAssert(!check_layout(stageMask));
328 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000329 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330 GrVertexLayout tcMask = 0;
331 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000332 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000333 tcMask |= StageTexCoordVertexLayoutBit(s,t);
334 GrAssert(VertexUsesStage(s, tcMask));
335 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
336 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
337 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
338 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000339 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000340 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
341 GrAssert(!VertexUsesStage(s2, tcMask));
342 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000343
bsalomon@google.com19628322011-02-03 21:30:17 +0000344 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000345 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000346 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000347 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
348 GrAssert(VertexUsesStage(s2, posAsTex));
349 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
350 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000351 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000353 GrAssert(-1 == VertexEdgeOffset(tcMask));
354 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000355 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000356 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000357 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000358 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000359 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000360 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
361 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000362 #if GR_DEBUG
363 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
364 #endif
365 GrAssert(-1 == VertexColorOffset(withEdge));
366 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
367 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
368 #if GR_DEBUG
369 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
370 #endif
371 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
372 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
373 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000374 #if GR_DEBUG
375 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
376 #endif
377 GrAssert(-1 == VertexColorOffset(withCoverage));
378 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
379 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
380 #if GR_DEBUG
381 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
382 kColor_VertexLayoutBit;
383 #endif
384 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
385 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
386 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000387 }
388 GrAssert(tex_coord_idx_mask(t) == tcMask);
389 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000390
tomhudson@google.com93813632011-10-27 20:21:16 +0000391 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000392 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000393 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000394 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000395 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000396 size = VertexSizeAndOffsetsByStage(tcMask,
397 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000398 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000399 GrAssert(2*sizeof(GrPoint) == size);
400 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000401 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000402 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000403 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000404 GrAssert(VertexUsesStage(s, tcMask));
405 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
406 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
407 }
408 }
409 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000410}
411
412////////////////////////////////////////////////////////////////////////////////
413
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000414#define DEBUG_INVAL_BUFFER 0xdeadcafe
415#define DEBUG_INVAL_START_IDX -1
416
bsalomon@google.com92669012011-09-27 19:10:05 +0000417GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000418#if GR_DEBUG
419 VertexLayoutUnitTest();
420#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000421 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000422#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000423 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
424 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
425 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
426 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000427#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000428 geoSrc.fVertexSrc = kNone_GeometrySrcType;
429 geoSrc.fIndexSrc = kNone_GeometrySrcType;
430}
431
432GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000433 GrAssert(1 == fGeoSrcStateStack.count());
434 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
435 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
436 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
437}
438
439void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000440 int popCnt = fGeoSrcStateStack.count() - 1;
441 while (popCnt) {
442 this->popGeometrySource();
443 --popCnt;
444 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000445 this->resetVertexSource();
446 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000447}
448
449void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000450 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000451 fClip = clip;
452}
453
454const GrClip& GrDrawTarget::getClip() const {
455 return fClip;
456}
457
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000458void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
459 GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
460 fCurrDrawState.fTextures[stage] = tex;
461}
462
463const GrTexture* GrDrawTarget::getTexture(int stage) const {
464 GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
465 return fCurrDrawState.fTextures[stage];
466}
467
468GrTexture* GrDrawTarget::getTexture(int stage) {
469 GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
470 return fCurrDrawState.fTextures[stage];
471}
472
473void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
474 fCurrDrawState.fRenderTarget = target;
475}
476
477const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
478 return fCurrDrawState.fRenderTarget;
479}
480
481GrRenderTarget* GrDrawTarget::getRenderTarget() {
482 return fCurrDrawState.fRenderTarget;
483}
484
485void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
486 fCurrDrawState.fViewMatrix = m;
487}
488
489void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
490 fCurrDrawState.fViewMatrix.preConcat(matrix);
491}
492
493void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
494 fCurrDrawState.fViewMatrix.postConcat(matrix);
495}
496
497const GrMatrix& GrDrawTarget::getViewMatrix() const {
498 return fCurrDrawState.fViewMatrix;
499}
500
501bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
502 // Mike: Can we cache this somewhere?
503 // Brian: Sure, do we use it often?
504
505 GrMatrix inverse;
506 if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
507 if (matrix) {
508 *matrix = inverse;
509 }
510 return true;
511 }
512 return false;
513}
514
515void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
516 GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
517 fCurrDrawState.fSamplerStates[stage] = state;
518}
519
520void GrDrawTarget::enableState(uint32_t bits) {
521 fCurrDrawState.fFlagBits |= bits;
522}
523
524void GrDrawTarget::disableState(uint32_t bits) {
525 fCurrDrawState.fFlagBits &= ~(bits);
526}
527
528void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff,
529 GrBlendCoeff dstCoeff) {
530 fCurrDrawState.fSrcBlend = srcCoeff;
531 fCurrDrawState.fDstBlend = dstCoeff;
532#if GR_DEBUG
533 switch (dstCoeff) {
534 case kDC_BlendCoeff:
535 case kIDC_BlendCoeff:
536 case kDA_BlendCoeff:
537 case kIDA_BlendCoeff:
538 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
539 "coverage stages.\n");
540 break;
541 default:
542 break;
543 }
544 switch (srcCoeff) {
545 case kSC_BlendCoeff:
546 case kISC_BlendCoeff:
547 case kSA_BlendCoeff:
548 case kISA_BlendCoeff:
549 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
550 "coverage stages.\n");
551 break;
552 default:
553 break;
554 }
555#endif
556}
557
558void GrDrawTarget::setColor(GrColor c) {
559 fCurrDrawState.fColor = c;
560}
561
562void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
563 fCurrDrawState.fColorFilterColor = c;
564 fCurrDrawState.fColorFilterXfermode = mode;
565}
566
567void GrDrawTarget::setAlpha(uint8_t a) {
568 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
569}
570
reed@google.comac10a2d2010-12-22 21:39:39 +0000571void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
572 state->fState = fCurrDrawState;
573}
574
575void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
576 fCurrDrawState = state.fState;
577}
578
579void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
580 fCurrDrawState = srcTarget.fCurrDrawState;
581}
582
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000583bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
584 int vertexCount,
585 void** vertices) {
586 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
587 bool acquired = false;
588 if (vertexCount > 0) {
589 GrAssert(NULL != vertices);
590 this->releasePreviousVertexSource();
591 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000592
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000593 acquired = this->onReserveVertexSpace(vertexLayout,
594 vertexCount,
595 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000596 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000597 if (acquired) {
598 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
599 geoSrc.fVertexCount = vertexCount;
600 geoSrc.fVertexLayout = vertexLayout;
601 } else if (NULL != vertices) {
602 *vertices = NULL;
603 }
604 return acquired;
605}
606
607bool GrDrawTarget::reserveIndexSpace(int indexCount,
608 void** indices) {
609 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
610 bool acquired = false;
611 if (indexCount > 0) {
612 GrAssert(NULL != indices);
613 this->releasePreviousIndexSource();
614 geoSrc.fIndexSrc = kNone_GeometrySrcType;
615
616 acquired = this->onReserveIndexSpace(indexCount, indices);
617 }
618 if (acquired) {
619 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
620 geoSrc.fIndexCount = indexCount;
621 } else if (NULL != indices) {
622 *indices = NULL;
623 }
624 return acquired;
625
reed@google.comac10a2d2010-12-22 21:39:39 +0000626}
627
628bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
629 int32_t* vertexCount,
630 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000631 if (NULL != vertexCount) {
632 *vertexCount = -1;
633 }
634 if (NULL != indexCount) {
635 *indexCount = -1;
636 }
637 return false;
638}
639
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000640void GrDrawTarget::releasePreviousVertexSource() {
641 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
642 switch (geoSrc.fVertexSrc) {
643 case kNone_GeometrySrcType:
644 break;
645 case kArray_GeometrySrcType:
646 this->releaseVertexArray();
647 break;
648 case kReserved_GeometrySrcType:
649 this->releaseReservedVertexSpace();
650 break;
651 case kBuffer_GeometrySrcType:
652 geoSrc.fVertexBuffer->unref();
653#if GR_DEBUG
654 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
655#endif
656 break;
657 default:
658 GrCrash("Unknown Vertex Source Type.");
659 break;
660 }
661}
662
663void GrDrawTarget::releasePreviousIndexSource() {
664 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
665 switch (geoSrc.fIndexSrc) {
666 case kNone_GeometrySrcType: // these two don't require
667 break;
668 case kArray_GeometrySrcType:
669 this->releaseIndexArray();
670 break;
671 case kReserved_GeometrySrcType:
672 this->releaseReservedIndexSpace();
673 break;
674 case kBuffer_GeometrySrcType:
675 geoSrc.fIndexBuffer->unref();
676#if GR_DEBUG
677 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
678#endif
679 break;
680 default:
681 GrCrash("Unknown Index Source Type.");
682 break;
683 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000684}
685
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000686void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
687 const void* vertexArray,
688 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000689 this->releasePreviousVertexSource();
690 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
691 geoSrc.fVertexSrc = kArray_GeometrySrcType;
692 geoSrc.fVertexLayout = vertexLayout;
693 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000694 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000695}
696
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000697void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
698 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000699 this->releasePreviousIndexSource();
700 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
701 geoSrc.fIndexSrc = kArray_GeometrySrcType;
702 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000703 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000704}
705
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000706void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
707 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000708 this->releasePreviousVertexSource();
709 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
710 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
711 geoSrc.fVertexBuffer = buffer;
712 buffer->ref();
713 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000714}
715
716void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000717 this->releasePreviousIndexSource();
718 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
719 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
720 geoSrc.fIndexBuffer = buffer;
721 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000722}
723
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000724void GrDrawTarget::resetVertexSource() {
725 this->releasePreviousVertexSource();
726 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
727 geoSrc.fVertexSrc = kNone_GeometrySrcType;
728}
729
730void GrDrawTarget::resetIndexSource() {
731 this->releasePreviousIndexSource();
732 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
733 geoSrc.fIndexSrc = kNone_GeometrySrcType;
734}
735
736void GrDrawTarget::pushGeometrySource() {
737 this->geometrySourceWillPush();
738 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
739 newState.fIndexSrc = kNone_GeometrySrcType;
740 newState.fVertexSrc = kNone_GeometrySrcType;
741#if GR_DEBUG
742 newState.fVertexCount = ~0;
743 newState.fVertexBuffer = (GrVertexBuffer*)~0;
744 newState.fIndexCount = ~0;
745 newState.fIndexBuffer = (GrIndexBuffer*)~0;
746#endif
747}
748
749void GrDrawTarget::popGeometrySource() {
750 const GeometrySrcState& geoSrc = this->getGeomSrc();
751 // if popping last element then pops are unbalanced with pushes
752 GrAssert(fGeoSrcStateStack.count() > 1);
753
754 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
755 this->releasePreviousVertexSource();
756 this->releasePreviousIndexSource();
757 fGeoSrcStateStack.pop_back();
758}
759
760////////////////////////////////////////////////////////////////////////////////
761
bsalomon@google.come8262622011-11-07 02:30:51 +0000762bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
763 int startIndex, int vertexCount,
764 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000765#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000766 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000767 int maxVertex = startVertex + vertexCount;
768 int maxValidVertex;
769 switch (geoSrc.fVertexSrc) {
770 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000771 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000772 case kReserved_GeometrySrcType: // fallthrough
773 case kArray_GeometrySrcType:
774 maxValidVertex = geoSrc.fVertexCount;
775 break;
776 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000777 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000778 VertexSize(geoSrc.fVertexLayout);
779 break;
780 }
781 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000782 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000783 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000784 if (indexCount > 0) {
785 int maxIndex = startIndex + indexCount;
786 int maxValidIndex;
787 switch (geoSrc.fIndexSrc) {
788 case kNone_GeometrySrcType:
789 GrCrash("Attempting to draw indexed geom without index src.");
790 case kReserved_GeometrySrcType: // fallthrough
791 case kArray_GeometrySrcType:
792 maxValidIndex = geoSrc.fIndexCount;
793 break;
794 case kBuffer_GeometrySrcType:
795 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
796 break;
797 }
798 if (maxIndex > maxValidIndex) {
799 GrCrash("Index reads outside valid index range.");
800 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000801 }
802#endif
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000803 if (NULL == this->getRenderTarget()) {
804 return false;
805 }
806 if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000807 if (kOne_BlendCoeff != fCurrDrawState.fSrcBlend ||
808 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000809 return false;
810 }
811 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000812 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com74b98712011-11-11 19:46:16 +0000813 // We don't support using unpremultiplied textures with filters (other
814 // than nearest). Alpha-premulling is not distributive WRT to filtering.
815 // We'd have to filter each texel before filtering. We could do this for
816 // our custom filters but we would also have to disable bilerp and do
817 // a custom bilerp in the shader. Until Skia itself supports unpremul
818 // configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000819 if (this->isStageEnabled(s) &&
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000820 GrPixelConfigIsUnpremultiplied(fCurrDrawState.fTextures[s]->config()) &&
821 GrSamplerState::kNearest_Filter != fCurrDrawState.fSamplerStates[s].getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000822 return false;
823 }
824 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000825 return true;
826}
827
828void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
829 int startIndex, int vertexCount,
830 int indexCount) {
831 if (indexCount > 0 &&
832 this->checkDraw(type, startVertex, startIndex,
833 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000834 this->onDrawIndexed(type, startVertex, startIndex,
835 vertexCount, indexCount);
836 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000837}
838
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000839void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
840 int startVertex,
841 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000842 if (vertexCount > 0 &&
843 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000844 this->onDrawNonIndexed(type, startVertex, vertexCount);
845 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000846}
847
848////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000849
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000850// Some blend modes allow folding a partial coverage value into the color's
851// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000852bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000853 /**
854 * The fractional coverage is f
855 * The src and dst coeffs are Cs and Cd
856 * The dst and src colors are S and D
857 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
858 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
859 * obvious that that first term will always be ok. The second term can be
860 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
861 * for Cd we find that only 1, ISA, and ISC produce the correct depth
862 * coeffecient in terms of S' and D.
863 */
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000864 return kOne_BlendCoeff == fCurrDrawState.fDstBlend||
865 kISA_BlendCoeff == fCurrDrawState.fDstBlend ||
866 kISC_BlendCoeff == fCurrDrawState.fDstBlend;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000867}
868
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000869
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000870bool GrDrawTarget::srcAlphaWillBeOne() const {
871 const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000872
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000873 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000874 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000875 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000876 return false;
877 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000878 // Check if color filter could introduce an alpha
879 // (TODO: Consider being more aggressive with regards to detecting 0xff
880 // final alpha from color filter).
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000881 if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000882 return false;
883 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000884 // Check if a color stage could create a partial alpha
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000885 for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000886 if (StageWillBeUsed(s, layout, fCurrDrawState)) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000887 GrAssert(NULL != fCurrDrawState.fTextures[s]);
888 GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000889 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000890 return false;
891 }
892 }
893 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000894 return true;
895}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000896
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000897GrDrawTarget::BlendOptFlags
898GrDrawTarget::getBlendOpts(bool forceCoverage,
899 GrBlendCoeff* srcCoeff,
900 GrBlendCoeff* dstCoeff) const {
901
902 const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
903
904 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
905 if (NULL == srcCoeff) {
906 srcCoeff = &bogusSrcCoeff;
907 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000908 *srcCoeff = fCurrDrawState.fSrcBlend;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000909
910 if (NULL == dstCoeff) {
911 dstCoeff = &bogusDstCoeff;
912 }
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000913 *dstCoeff = fCurrDrawState.fDstBlend;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000914
915 // We don't ever expect source coeffecients to reference the source
916 GrAssert(kSA_BlendCoeff != *srcCoeff &&
917 kISA_BlendCoeff != *srcCoeff &&
918 kSC_BlendCoeff != *srcCoeff &&
919 kISC_BlendCoeff != *srcCoeff);
920 // same for dst
921 GrAssert(kDA_BlendCoeff != *dstCoeff &&
922 kIDA_BlendCoeff != *dstCoeff &&
923 kDC_BlendCoeff != *dstCoeff &&
924 kIDC_BlendCoeff != *dstCoeff);
925
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000926 if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000927 *srcCoeff = kZero_BlendCoeff;
928 *dstCoeff = kOne_BlendCoeff;
929 }
930
931 bool srcAIsOne = this->srcAlphaWillBeOne();
932 bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff ||
933 (kSA_BlendCoeff == *dstCoeff && srcAIsOne);
934 bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff ||
935 (kISA_BlendCoeff == *dstCoeff && srcAIsOne);
936
937
938 // When coeffs are (0,1) there is no reason to draw at all, unless
939 // stenciling is enabled. Having color writes disabled is effectively
940 // (0,1).
941 if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000942 if (fCurrDrawState.fStencilSettings.doesWrite()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000943 if (fCaps.fShaderSupport) {
944 return kDisableBlend_BlendOptFlag |
945 kEmitTransBlack_BlendOptFlag;
946 } else {
947 return kDisableBlend_BlendOptFlag;
948 }
949 } else {
950 return kSkipDraw_BlendOptFlag;
951 }
952 }
953
954 // check for coverage due to edge aa or coverage texture stage
955 bool hasCoverage = forceCoverage ||
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000956 fCurrDrawState.fEdgeAANumEdges > 0 ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000957 (layout & kCoverage_VertexLayoutBit) ||
958 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com3d0835b2011-12-08 16:12:03 +0000959 for (int s = fCurrDrawState.fFirstCoverageStage;
tomhudson@google.com93813632011-10-27 20:21:16 +0000960 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000961 ++s) {
962 if (StageWillBeUsed(s, layout, fCurrDrawState)) {
963 hasCoverage = true;
964 }
965 }
966
967 // if we don't have coverage we can check whether the dst
968 // has to read at all. If not, we'll disable blending.
969 if (!hasCoverage) {
970 if (dstCoeffIsZero) {
971 if (kOne_BlendCoeff == *srcCoeff) {
972 // if there is no coverage and coeffs are (1,0) then we
973 // won't need to read the dst at all, it gets replaced by src
974 return kDisableBlend_BlendOptFlag;
975 } else if (kZero_BlendCoeff == *srcCoeff &&
976 fCaps.fShaderSupport) {
977 // if the op is "clear" then we don't need to emit a color
978 // or blend, just write transparent black into the dst.
979 *srcCoeff = kOne_BlendCoeff;
980 *dstCoeff = kZero_BlendCoeff;
981 return kDisableBlend_BlendOptFlag |
982 kEmitTransBlack_BlendOptFlag;
983 }
984 }
985 } else {
986 // check whether coverage can be safely rolled into alpha
987 // of if we can skip color computation and just emit coverage
988 if (this->canTweakAlphaForCoverage()) {
989 return kCoverageAsAlpha_BlendOptFlag;
990 }
991 // We haven't implemented support for these optimizations in the
992 // fixed pipe (which is on its deathbed)
993 if (fCaps.fShaderSupport) {
994 if (dstCoeffIsZero) {
995 if (kZero_BlendCoeff == *srcCoeff) {
996 // the source color is not included in the blend
997 // the dst coeff is effectively zero so blend works out to:
998 // (c)(0)D + (1-c)D = (1-c)D.
999 *dstCoeff = kISA_BlendCoeff;
1000 return kEmitCoverage_BlendOptFlag;
1001 } else if (srcAIsOne) {
1002 // the dst coeff is effectively zero so blend works out to:
1003 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
1004 // If Sa is 1 then we can replace Sa with c
1005 // and set dst coeff to 1-Sa.
1006 *dstCoeff = kISA_BlendCoeff;
1007 return kCoverageAsAlpha_BlendOptFlag;
1008 }
1009 } else if (dstCoeffIsOne) {
1010 // the dst coeff is effectively one so blend works out to:
1011 // cS + (c)(1)D + (1-c)D = cS + D.
1012 *dstCoeff = kOne_BlendCoeff;
1013 return kCoverageAsAlpha_BlendOptFlag;
1014 }
1015 }
1016 }
1017 return kNone_BlendOpt;
1018}
1019
1020bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001021 // there is a conflict between using smooth lines and our use of
1022 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1023 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001024 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001025 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001026 !(kHWAntialias_StateBit & fCurrDrawState.fFlagBits)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001027 return false;
1028 }
1029 BlendOptFlags opts = this->getBlendOpts();
1030 return (kDisableBlend_BlendOptFlag & opts) &&
1031 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001032}
1033
1034bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001035 // we can correctly apply coverage if a) we have dual source blending
1036 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001037 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001038 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001039}
1040
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001041bool GrDrawTarget::drawWillReadDst() const {
1042 return SkToBool((kDisableBlend_BlendOptFlag | kSkipDraw_BlendOptFlag) &
1043 this->getBlendOpts());
bsalomon@google.com471d4712011-08-23 15:45:25 +00001044}
1045
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001046///////////////////////////////////////////////////////////////////////////////
1047
1048void GrDrawTarget::setEdgeAAData(const GrDrawState::Edge* edges, int numEdges) {
1049 GrAssert(numEdges <= GrDrawState::kMaxEdges);
1050 memcpy(fCurrDrawState.fEdgeAAEdges, edges,
1051 numEdges * sizeof(GrDrawState::Edge));
1052 fCurrDrawState.fEdgeAANumEdges = numEdges;
1053}
1054
1055
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001056////////////////////////////////////////////////////////////////////////////////
1057
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001058void GrDrawTarget::drawRect(const GrRect& rect,
1059 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001060 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001061 const GrRect* srcRects[],
1062 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001063 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001064
1065 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001066 if (!geo.succeeded()) {
1067 GrPrintf("Failed to get space for vertices!\n");
1068 return;
1069 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001070
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001071 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001072 srcMatrices, layout, geo.vertices());
1073
1074 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
1075}
1076
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001077GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001078 const GrRect* srcRects[]) {
1079 GrVertexLayout layout = 0;
1080
tomhudson@google.com93813632011-10-27 20:21:16 +00001081 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001082 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001083 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001084 if (NULL != srcRects && NULL != srcRects[i]) {
1085 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1086 ++numTC;
1087 } else {
1088 layout |= StagePosAsTexCoordVertexLayoutBit(i);
1089 }
1090 }
1091 }
1092 return layout;
1093}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001094
1095void GrDrawTarget::clipWillBeSet(const GrClip& clip) {
1096}
1097
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001098void GrDrawTarget::SetRectVertices(const GrRect& rect,
1099 const GrMatrix* matrix,
1100 const GrRect* srcRects[],
1101 const GrMatrix* srcMatrices[],
1102 GrVertexLayout layout,
1103 void* vertices) {
1104#if GR_DEBUG
1105 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001106 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001107 if (VertexTexCoordsForStage(i, layout) >= 0) {
1108 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1109 } else {
1110 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1111 }
1112 }
1113#endif
1114
tomhudson@google.com93813632011-10-27 20:21:16 +00001115 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001116 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1117 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001118
bsalomon@google.coma3108262011-10-10 14:08:47 +00001119 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001120 rect.fRight, rect.fBottom,
1121 vsize);
1122 if (NULL != matrix) {
1123 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1124 }
1125
tomhudson@google.com93813632011-10-27 20:21:16 +00001126 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001127 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001128 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001129 stageOffsets[i]);
1130 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001131 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001132 vsize);
1133 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1134 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1135 }
1136 }
1137 }
1138}
1139
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001140////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001141
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001142GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1143 fDrawTarget = NULL;
1144}
reed@google.comac10a2d2010-12-22 21:39:39 +00001145
1146GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
1147 fDrawTarget = target;
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001148 if (NULL != fDrawTarget) {
1149 fDrawTarget->saveCurrentDrawState(&fDrawState);
1150 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001151}
1152
1153GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001154 if (NULL != fDrawTarget) {
1155 fDrawTarget->restoreDrawState(fDrawState);
1156 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001157}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001158
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001159void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
1160 if (target != fDrawTarget) {
1161 if (NULL != fDrawTarget) {
1162 fDrawTarget->restoreDrawState(fDrawState);
1163 }
1164 if (NULL != target) {
bsalomon@google.comd19aa272011-06-22 01:28:17 +00001165 target->saveCurrentDrawState(&fDrawState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001166 }
1167 fDrawTarget = target;
1168 }
1169}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001170
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001171////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001172
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001173GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1174 GrDrawTarget* target,
1175 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001176 GrAssert(NULL != target);
1177
1178 fDrawTarget = target;
1179 fViewMatrix = target->getViewMatrix();
1180 fStageMask = stageMask;
1181 if (fStageMask) {
1182 GrMatrix invVM;
1183 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001184 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001185 if (fStageMask & (1 << s)) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001186 fSamplerMatrices[s] = target->getSamplerMatrix(s);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001187 }
1188 }
1189 target->preConcatSamplerMatrices(fStageMask, invVM);
1190 } else {
1191 // sad trombone sound
1192 fStageMask = 0;
1193 }
1194 }
1195 target->setViewMatrix(GrMatrix::I());
1196}
1197
1198GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
1199 fDrawTarget->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001200 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001201 if (fStageMask & (1 << s)) {
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001202 fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001203 }
1204 }
1205}
1206
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001207////////////////////////////////////////////////////////////////////////////////
1208
1209GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1210 GrDrawTarget* target,
1211 GrVertexLayout vertexLayout,
1212 int vertexCount,
1213 int indexCount) {
1214 fTarget = NULL;
1215 this->set(target, vertexLayout, vertexCount, indexCount);
1216}
1217
1218GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1219 fTarget = NULL;
1220}
1221
1222GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1223 this->reset();
1224}
1225
1226bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1227 GrVertexLayout vertexLayout,
1228 int vertexCount,
1229 int indexCount) {
1230 this->reset();
1231 fTarget = target;
1232 bool success = true;
1233 if (NULL != fTarget) {
1234 fTarget = target;
1235 if (vertexCount > 0) {
1236 success = target->reserveVertexSpace(vertexLayout,
1237 vertexCount,
1238 &fVertices);
1239 if (!success) {
1240 this->reset();
1241 }
1242 }
1243 if (success && indexCount > 0) {
1244 success = target->reserveIndexSpace(indexCount, &fIndices);
1245 if (!success) {
1246 this->reset();
1247 }
1248 }
1249 }
1250 GrAssert(success == (NULL != fTarget));
1251 return success;
1252}
1253
1254void GrDrawTarget::AutoReleaseGeometry::reset() {
1255 if (NULL != fTarget) {
1256 if (NULL != fVertices) {
1257 fTarget->resetVertexSource();
1258 }
1259 if (NULL != fIndices) {
1260 fTarget->resetIndexSource();
1261 }
1262 fTarget = NULL;
1263 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001264 fVertices = NULL;
1265 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001266}
1267
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001268void GrDrawTarget::Caps::print() const {
1269 static const char* gNY[] = {"NO", "YES"};
1270 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001271 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001272 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1273 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1274 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
1275 GrPrintf("Shader Support : %s\n", gNY[fShaderSupport]);
1276 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001277 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001278 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1279 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1280 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001281 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1282 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1283}
1284