blob: 0ba7ead07702ffea4c1ef9582b63a607be608a57 [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<>
reed@google.comd728f6e2011-01-13 20:02:47 +000027int stage_mask_recur<GrDrawTarget::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<>
reed@google.comd728f6e2011-01-13 20:02:47 +000048int tex_coord_mask_recur<GrDrawTarget::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.
57 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
58 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
69 for (int t = 0; t < GrDrawTarget::kMaxTexCoords; ++t) {
70 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 * ...
110 * Tex Coord kMaxTexCoords-1
111 * 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
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000188int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000189 int texCoordOffsetsByIdx[kMaxTexCoords],
190 int* colorOffset,
191 int* coverageOffset,
192 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194
bsalomon@google.com5782d712011-01-21 21:03:59 +0000195 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000196 sizeof(GrGpuTextVertex) :
197 sizeof(GrPoint);
198 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000199
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000200 for (int t = 0; t < kMaxTexCoords; ++t) {
201 if (tex_coord_idx_mask(t) & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000202 if (NULL != texCoordOffsetsByIdx) {
203 texCoordOffsetsByIdx[t] = size;
204 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000205 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000207 if (NULL != texCoordOffsetsByIdx) {
208 texCoordOffsetsByIdx[t] = -1;
209 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000212 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000213 if (NULL != colorOffset) {
214 *colorOffset = size;
215 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000216 size += sizeof(GrColor);
217 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000218 if (NULL != colorOffset) {
219 *colorOffset = -1;
220 }
221 }
222 if (kCoverage_VertexLayoutBit & vertexLayout) {
223 if (NULL != coverageOffset) {
224 *coverageOffset = size;
225 }
226 size += sizeof(GrColor);
227 } else {
228 if (NULL != coverageOffset) {
229 *coverageOffset = -1;
230 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000231 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000232 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000233 if (NULL != edgeOffset) {
234 *edgeOffset = size;
235 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000236 size += 4 * sizeof(GrScalar);
237 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000238 if (NULL != edgeOffset) {
239 *edgeOffset = -1;
240 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000241 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000242 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000243}
244
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000245int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
246 int texCoordOffsetsByStage[kNumStages],
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000247 int* colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000248 int* coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000249 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000250 GrAssert(check_layout(vertexLayout));
251
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252 int texCoordOffsetsByIdx[kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000253 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000254 (NULL == texCoordOffsetsByStage) ?
255 NULL :
256 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000257 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000258 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000259 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000260 if (NULL != texCoordOffsetsByStage) {
261 for (int s = 0; s < kNumStages; ++s) {
262 int tcIdx;
263 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
264 texCoordOffsetsByStage[s] = 0;
265 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
266 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
267 } else {
268 texCoordOffsetsByStage[s] = -1;
269 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000270 }
271 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000272 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000273}
274
bsalomon@google.coma3108262011-10-10 14:08:47 +0000275////////////////////////////////////////////////////////////////////////////////
276
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000277bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
278 GrAssert(stage < kNumStages);
279 GrAssert(check_layout(vertexLayout));
280 return !!(stage_mask(stage) & vertexLayout);
281}
282
bsalomon@google.com5782d712011-01-21 21:03:59 +0000283bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000284 GrVertexLayout vertexLayout) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000285 GrAssert(coordIndex < kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000286 GrAssert(check_layout(vertexLayout));
287 return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
288}
289
290int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
291 GrAssert(stage < kNumStages);
292 GrAssert(check_layout(vertexLayout));
293 int bit = vertexLayout & stage_tex_coord_mask(stage);
294 if (bit) {
295 // figure out which set of texture coordates is used
296 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
297 // and start at bit 0.
298 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
299 return (32 - Gr_clz(bit) - 1) / kNumStages;
300 }
301 return -1;
302}
303
bsalomon@google.coma3108262011-10-10 14:08:47 +0000304////////////////////////////////////////////////////////////////////////////////
305
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000306void GrDrawTarget::VertexLayoutUnitTest() {
307 // not necessarily exhaustive
308 static bool run;
309 if (!run) {
310 run = true;
311 for (int s = 0; s < kNumStages; ++s) {
312
313 GrAssert(!VertexUsesStage(s, 0));
314 GrAssert(-1 == VertexStageCoordOffset(s, 0));
315 GrVertexLayout stageMask = 0;
316 for (int t = 0; t < kMaxTexCoords; ++t) {
317 stageMask |= StageTexCoordVertexLayoutBit(s,t);
318 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000319 GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000320 GrAssert(stage_tex_coord_mask(s) == stageMask);
321 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
322 GrAssert(stage_mask(s) == stageMask);
323 GrAssert(!check_layout(stageMask));
324 }
325 for (int t = 0; t < kMaxTexCoords; ++t) {
326 GrVertexLayout tcMask = 0;
327 GrAssert(!VertexUsesTexCoordIdx(t, 0));
328 for (int s = 0; s < kNumStages; ++s) {
329 tcMask |= StageTexCoordVertexLayoutBit(s,t);
330 GrAssert(VertexUsesStage(s, tcMask));
331 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
332 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
333 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
334 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
335 for (int s2 = s + 1; s2 < kNumStages; ++s2) {
336 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
337 GrAssert(!VertexUsesStage(s2, tcMask));
338 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000339
bsalomon@google.com19628322011-02-03 21:30:17 +0000340 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000341 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000342 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000343 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
344 GrAssert(VertexUsesStage(s2, posAsTex));
345 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
346 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000347 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000348 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000349 GrAssert(-1 == VertexEdgeOffset(tcMask));
350 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000351 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000352 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000353 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000354 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000355 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000356 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
357 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000358 #if GR_DEBUG
359 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
360 #endif
361 GrAssert(-1 == VertexColorOffset(withEdge));
362 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
363 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
364 #if GR_DEBUG
365 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
366 #endif
367 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
368 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
369 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000370 #if GR_DEBUG
371 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
372 #endif
373 GrAssert(-1 == VertexColorOffset(withCoverage));
374 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
375 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
376 #if GR_DEBUG
377 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
378 kColor_VertexLayoutBit;
379 #endif
380 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
381 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
382 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000383 }
384 GrAssert(tex_coord_idx_mask(t) == tcMask);
385 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000386
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000387 int stageOffsets[kNumStages];
388 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000389 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000390 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000391 int size;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000392 size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset,
393 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000394 GrAssert(2*sizeof(GrPoint) == size);
395 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000396 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000397 GrAssert(-1 == edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000398 for (int s = 0; s < kNumStages; ++s) {
399 GrAssert(VertexUsesStage(s, tcMask));
400 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
401 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
402 }
403 }
404 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000405}
406
407////////////////////////////////////////////////////////////////////////////////
408
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000409#define DEBUG_INVAL_BUFFER 0xdeadcafe
410#define DEBUG_INVAL_START_IDX -1
411
bsalomon@google.com92669012011-09-27 19:10:05 +0000412GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000413#if GR_DEBUG
414 VertexLayoutUnitTest();
415#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000416 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000417#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000418 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
419 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
420 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
421 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000422#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000423 geoSrc.fVertexSrc = kNone_GeometrySrcType;
424 geoSrc.fIndexSrc = kNone_GeometrySrcType;
425}
426
427GrDrawTarget::~GrDrawTarget() {
428 int popCnt = fGeoSrcStateStack.count() - 1;
429 while (popCnt) {
430 this->popGeometrySource();
431 --popCnt;
432 }
433 this->releasePreviousVertexSource();
434 this->releasePreviousIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000435}
436
437void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000438 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000439 fClip = clip;
440}
441
442const GrClip& GrDrawTarget::getClip() const {
443 return fClip;
444}
445
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000446void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
447 GrAssert(stage >= 0 && stage < kNumStages);
448 fCurrDrawState.fTextures[stage] = tex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000449}
450
bsalomon@google.com5782d712011-01-21 21:03:59 +0000451const GrTexture* GrDrawTarget::getTexture(int stage) const {
452 GrAssert(stage >= 0 && stage < kNumStages);
453 return fCurrDrawState.fTextures[stage];
454}
455
456GrTexture* GrDrawTarget::getTexture(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000457 GrAssert(stage >= 0 && stage < kNumStages);
458 return fCurrDrawState.fTextures[stage];
reed@google.comac10a2d2010-12-22 21:39:39 +0000459}
460
461void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
462 fCurrDrawState.fRenderTarget = target;
463}
464
bsalomon@google.com5782d712011-01-21 21:03:59 +0000465const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
466 return fCurrDrawState.fRenderTarget;
467}
468
469GrRenderTarget* GrDrawTarget::getRenderTarget() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000470 return fCurrDrawState.fRenderTarget;
471}
472
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000473void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
474 fCurrDrawState.fViewMatrix = m;
reed@google.comac10a2d2010-12-22 21:39:39 +0000475}
476
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000477void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000478 fCurrDrawState.fViewMatrix.preConcat(matrix);
479}
480
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000481void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
482 fCurrDrawState.fViewMatrix.postConcat(matrix);
483}
484
bsalomon@google.com5782d712011-01-21 21:03:59 +0000485const GrMatrix& GrDrawTarget::getViewMatrix() const {
486 return fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000487}
488
489bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000490 // Mike: Can we cache this somewhere?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000491 // Brian: Sure, do we use it often?
reed@google.comac10a2d2010-12-22 21:39:39 +0000492
493 GrMatrix inverse;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000494 if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000495 if (matrix) {
496 *matrix = inverse;
497 }
498 return true;
499 }
500 return false;
501}
502
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000503void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
504 GrAssert(stage >= 0 && stage < kNumStages);
505 fCurrDrawState.fSamplerStates[stage] = state;
506}
507
reed@google.comac10a2d2010-12-22 21:39:39 +0000508void GrDrawTarget::enableState(uint32_t bits) {
509 fCurrDrawState.fFlagBits |= bits;
510}
511
512void GrDrawTarget::disableState(uint32_t bits) {
513 fCurrDrawState.fFlagBits &= ~(bits);
514}
515
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000516void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff,
517 GrBlendCoeff dstCoeff) {
518 fCurrDrawState.fSrcBlend = srcCoeff;
519 fCurrDrawState.fDstBlend = dstCoeff;
520#if GR_DEBUG
521 switch (dstCoeff) {
522 case kDC_BlendCoeff:
523 case kIDC_BlendCoeff:
524 case kDA_BlendCoeff:
525 case kIDA_BlendCoeff:
526 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
527 "coverage stages.\n");
528 break;
529 default:
530 break;
531 }
532 switch (srcCoeff) {
533 case kSC_BlendCoeff:
534 case kISC_BlendCoeff:
535 case kSA_BlendCoeff:
536 case kISA_BlendCoeff:
537 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
538 "coverage stages.\n");
539 break;
540 default:
541 break;
542 }
543#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000544}
545
546void GrDrawTarget::setColor(GrColor c) {
547 fCurrDrawState.fColor = c;
548}
549
Scroggo97c88c22011-05-11 14:05:25 +0000550void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
551 fCurrDrawState.fColorFilterColor = c;
552 fCurrDrawState.fColorFilterXfermode = mode;
553}
554
reed@google.comac10a2d2010-12-22 21:39:39 +0000555void GrDrawTarget::setAlpha(uint8_t a) {
556 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
557}
558
559void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
560 state->fState = fCurrDrawState;
561}
562
563void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
564 fCurrDrawState = state.fState;
565}
566
567void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
568 fCurrDrawState = srcTarget.fCurrDrawState;
569}
570
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000571bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
572 int vertexCount,
573 void** vertices) {
574 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
575 bool acquired = false;
576 if (vertexCount > 0) {
577 GrAssert(NULL != vertices);
578 this->releasePreviousVertexSource();
579 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000580
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000581 acquired = this->onReserveVertexSpace(vertexLayout,
582 vertexCount,
583 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000584 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000585 if (acquired) {
586 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
587 geoSrc.fVertexCount = vertexCount;
588 geoSrc.fVertexLayout = vertexLayout;
589 } else if (NULL != vertices) {
590 *vertices = NULL;
591 }
592 return acquired;
593}
594
595bool GrDrawTarget::reserveIndexSpace(int indexCount,
596 void** indices) {
597 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
598 bool acquired = false;
599 if (indexCount > 0) {
600 GrAssert(NULL != indices);
601 this->releasePreviousIndexSource();
602 geoSrc.fIndexSrc = kNone_GeometrySrcType;
603
604 acquired = this->onReserveIndexSpace(indexCount, indices);
605 }
606 if (acquired) {
607 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
608 geoSrc.fIndexCount = indexCount;
609 } else if (NULL != indices) {
610 *indices = NULL;
611 }
612 return acquired;
613
reed@google.comac10a2d2010-12-22 21:39:39 +0000614}
615
616bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
617 int32_t* vertexCount,
618 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000619 if (NULL != vertexCount) {
620 *vertexCount = -1;
621 }
622 if (NULL != indexCount) {
623 *indexCount = -1;
624 }
625 return false;
626}
627
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000628void GrDrawTarget::releasePreviousVertexSource() {
629 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
630 switch (geoSrc.fVertexSrc) {
631 case kNone_GeometrySrcType:
632 break;
633 case kArray_GeometrySrcType:
634 this->releaseVertexArray();
635 break;
636 case kReserved_GeometrySrcType:
637 this->releaseReservedVertexSpace();
638 break;
639 case kBuffer_GeometrySrcType:
640 geoSrc.fVertexBuffer->unref();
641#if GR_DEBUG
642 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
643#endif
644 break;
645 default:
646 GrCrash("Unknown Vertex Source Type.");
647 break;
648 }
649}
650
651void GrDrawTarget::releasePreviousIndexSource() {
652 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
653 switch (geoSrc.fIndexSrc) {
654 case kNone_GeometrySrcType: // these two don't require
655 break;
656 case kArray_GeometrySrcType:
657 this->releaseIndexArray();
658 break;
659 case kReserved_GeometrySrcType:
660 this->releaseReservedIndexSpace();
661 break;
662 case kBuffer_GeometrySrcType:
663 geoSrc.fIndexBuffer->unref();
664#if GR_DEBUG
665 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
666#endif
667 break;
668 default:
669 GrCrash("Unknown Index Source Type.");
670 break;
671 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000672}
673
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000674void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
675 const void* vertexArray,
676 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000677 this->releasePreviousVertexSource();
678 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
679 geoSrc.fVertexSrc = kArray_GeometrySrcType;
680 geoSrc.fVertexLayout = vertexLayout;
681 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000682 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000683}
684
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000685void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
686 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000687 this->releasePreviousIndexSource();
688 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
689 geoSrc.fIndexSrc = kArray_GeometrySrcType;
690 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000691 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000692}
693
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000694void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
695 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000696 this->releasePreviousVertexSource();
697 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
698 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
699 geoSrc.fVertexBuffer = buffer;
700 buffer->ref();
701 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000702}
703
704void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000705 this->releasePreviousIndexSource();
706 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
707 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
708 geoSrc.fIndexBuffer = buffer;
709 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000710}
711
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712void GrDrawTarget::resetVertexSource() {
713 this->releasePreviousVertexSource();
714 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
715 geoSrc.fVertexSrc = kNone_GeometrySrcType;
716}
717
718void GrDrawTarget::resetIndexSource() {
719 this->releasePreviousIndexSource();
720 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
721 geoSrc.fIndexSrc = kNone_GeometrySrcType;
722}
723
724void GrDrawTarget::pushGeometrySource() {
725 this->geometrySourceWillPush();
726 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
727 newState.fIndexSrc = kNone_GeometrySrcType;
728 newState.fVertexSrc = kNone_GeometrySrcType;
729#if GR_DEBUG
730 newState.fVertexCount = ~0;
731 newState.fVertexBuffer = (GrVertexBuffer*)~0;
732 newState.fIndexCount = ~0;
733 newState.fIndexBuffer = (GrIndexBuffer*)~0;
734#endif
735}
736
737void GrDrawTarget::popGeometrySource() {
738 const GeometrySrcState& geoSrc = this->getGeomSrc();
739 // if popping last element then pops are unbalanced with pushes
740 GrAssert(fGeoSrcStateStack.count() > 1);
741
742 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
743 this->releasePreviousVertexSource();
744 this->releasePreviousIndexSource();
745 fGeoSrcStateStack.pop_back();
746}
747
748////////////////////////////////////////////////////////////////////////////////
749
750void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
751 int startIndex, int vertexCount,
752 int indexCount) {
753#if GR_DEBUG
754 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
755 int maxVertex = startVertex + vertexCount;
756 int maxValidVertex;
757 switch (geoSrc.fVertexSrc) {
758 case kNone_GeometrySrcType:
759 GrCrash("Attempting to draw indexed geom without vertex src.");
760 case kReserved_GeometrySrcType: // fallthrough
761 case kArray_GeometrySrcType:
762 maxValidVertex = geoSrc.fVertexCount;
763 break;
764 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000765 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000766 VertexSize(geoSrc.fVertexLayout);
767 break;
768 }
769 if (maxVertex > maxValidVertex) {
770 GrCrash("Indexed drawing outside valid vertex range.");
771 }
772 int maxIndex = startIndex + indexCount;
773 int maxValidIndex;
774 switch (geoSrc.fIndexSrc) {
775 case kNone_GeometrySrcType:
776 GrCrash("Attempting to draw indexed geom without index src.");
777 case kReserved_GeometrySrcType: // fallthrough
778 case kArray_GeometrySrcType:
779 maxValidIndex = geoSrc.fIndexCount;
780 break;
781 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000782 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000783 break;
784 }
785 if (maxIndex > maxValidIndex) {
786 GrCrash("Indexed drawing outside valid index range.");
787 }
788#endif
bsalomon@google.com82145872011-08-23 14:32:40 +0000789 if (indexCount > 0) {
790 this->onDrawIndexed(type, startVertex, startIndex,
791 vertexCount, indexCount);
792 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000793}
794
795
796void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
797 int startVertex,
798 int vertexCount) {
799#if GR_DEBUG
800 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
801 int maxVertex = startVertex + vertexCount;
802 int maxValidVertex;
803 switch (geoSrc.fVertexSrc) {
804 case kNone_GeometrySrcType:
805 GrCrash("Attempting to draw non-indexed geom without vertex src.");
806 case kReserved_GeometrySrcType: // fallthrough
807 case kArray_GeometrySrcType:
808 maxValidVertex = geoSrc.fVertexCount;
809 break;
810 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000811 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000812 VertexSize(geoSrc.fVertexLayout);
813 break;
814 }
815 if (maxVertex > maxValidVertex) {
816 GrCrash("Non-indexed drawing outside valid vertex range.");
817 }
818#endif
bsalomon@google.com82145872011-08-23 14:32:40 +0000819 if (vertexCount > 0) {
820 this->onDrawNonIndexed(type, startVertex, vertexCount);
821 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000822}
823
824////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000825
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000826// Some blend modes allow folding a partial coverage value into the color's
827// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000828bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000829 /**
830 * The fractional coverage is f
831 * The src and dst coeffs are Cs and Cd
832 * The dst and src colors are S and D
833 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
834 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
835 * obvious that that first term will always be ok. The second term can be
836 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
837 * for Cd we find that only 1, ISA, and ISC produce the correct depth
838 * coeffecient in terms of S' and D.
839 */
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000840 return kOne_BlendCoeff == fCurrDrawState.fDstBlend||
841 kISA_BlendCoeff == fCurrDrawState.fDstBlend ||
842 kISC_BlendCoeff == fCurrDrawState.fDstBlend;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000843}
844
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000845
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000846bool GrDrawTarget::srcAlphaWillBeOne() const {
847 const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000848
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000849 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000850 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000851 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000852 return false;
853 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000854 // Check if color filter could introduce an alpha
855 // (TODO: Consider being more aggressive with regards to detecting 0xff
856 // final alpha from color filter).
857 if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000858 return false;
859 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000860 // Check if a color stage could create a partial alpha
861 for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
862 if (StageWillBeUsed(s, layout, fCurrDrawState)) {
863 GrAssert(NULL != fCurrDrawState.fTextures[s]);
864 GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000865 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000866 return false;
867 }
868 }
869 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000870 return true;
871}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000872
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000873GrDrawTarget::BlendOptFlags
874GrDrawTarget::getBlendOpts(bool forceCoverage,
875 GrBlendCoeff* srcCoeff,
876 GrBlendCoeff* dstCoeff) const {
877
878 const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout;
879
880 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
881 if (NULL == srcCoeff) {
882 srcCoeff = &bogusSrcCoeff;
883 }
884 *srcCoeff = fCurrDrawState.fSrcBlend;
885
886 if (NULL == dstCoeff) {
887 dstCoeff = &bogusDstCoeff;
888 }
889 *dstCoeff = fCurrDrawState.fDstBlend;
890
891 // We don't ever expect source coeffecients to reference the source
892 GrAssert(kSA_BlendCoeff != *srcCoeff &&
893 kISA_BlendCoeff != *srcCoeff &&
894 kSC_BlendCoeff != *srcCoeff &&
895 kISC_BlendCoeff != *srcCoeff);
896 // same for dst
897 GrAssert(kDA_BlendCoeff != *dstCoeff &&
898 kIDA_BlendCoeff != *dstCoeff &&
899 kDC_BlendCoeff != *dstCoeff &&
900 kIDC_BlendCoeff != *dstCoeff);
901
902 if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) {
903 *srcCoeff = kZero_BlendCoeff;
904 *dstCoeff = kOne_BlendCoeff;
905 }
906
907 bool srcAIsOne = this->srcAlphaWillBeOne();
908 bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff ||
909 (kSA_BlendCoeff == *dstCoeff && srcAIsOne);
910 bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff ||
911 (kISA_BlendCoeff == *dstCoeff && srcAIsOne);
912
913
914 // When coeffs are (0,1) there is no reason to draw at all, unless
915 // stenciling is enabled. Having color writes disabled is effectively
916 // (0,1).
917 if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) {
918 if (fCurrDrawState.fStencilSettings.doesWrite()) {
919 if (fCaps.fShaderSupport) {
920 return kDisableBlend_BlendOptFlag |
921 kEmitTransBlack_BlendOptFlag;
922 } else {
923 return kDisableBlend_BlendOptFlag;
924 }
925 } else {
926 return kSkipDraw_BlendOptFlag;
927 }
928 }
929
930 // check for coverage due to edge aa or coverage texture stage
931 bool hasCoverage = forceCoverage ||
932 fCurrDrawState.fEdgeAANumEdges > 0 ||
933 (layout & kCoverage_VertexLayoutBit) ||
934 (layout & kEdge_VertexLayoutBit);
935 for (int s = fCurrDrawState.fFirstCoverageStage;
936 !hasCoverage && s < kNumStages;
937 ++s) {
938 if (StageWillBeUsed(s, layout, fCurrDrawState)) {
939 hasCoverage = true;
940 }
941 }
942
943 // if we don't have coverage we can check whether the dst
944 // has to read at all. If not, we'll disable blending.
945 if (!hasCoverage) {
946 if (dstCoeffIsZero) {
947 if (kOne_BlendCoeff == *srcCoeff) {
948 // if there is no coverage and coeffs are (1,0) then we
949 // won't need to read the dst at all, it gets replaced by src
950 return kDisableBlend_BlendOptFlag;
951 } else if (kZero_BlendCoeff == *srcCoeff &&
952 fCaps.fShaderSupport) {
953 // if the op is "clear" then we don't need to emit a color
954 // or blend, just write transparent black into the dst.
955 *srcCoeff = kOne_BlendCoeff;
956 *dstCoeff = kZero_BlendCoeff;
957 return kDisableBlend_BlendOptFlag |
958 kEmitTransBlack_BlendOptFlag;
959 }
960 }
961 } else {
962 // check whether coverage can be safely rolled into alpha
963 // of if we can skip color computation and just emit coverage
964 if (this->canTweakAlphaForCoverage()) {
965 return kCoverageAsAlpha_BlendOptFlag;
966 }
967 // We haven't implemented support for these optimizations in the
968 // fixed pipe (which is on its deathbed)
969 if (fCaps.fShaderSupport) {
970 if (dstCoeffIsZero) {
971 if (kZero_BlendCoeff == *srcCoeff) {
972 // the source color is not included in the blend
973 // the dst coeff is effectively zero so blend works out to:
974 // (c)(0)D + (1-c)D = (1-c)D.
975 *dstCoeff = kISA_BlendCoeff;
976 return kEmitCoverage_BlendOptFlag;
977 } else if (srcAIsOne) {
978 // the dst coeff is effectively zero so blend works out to:
979 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
980 // If Sa is 1 then we can replace Sa with c
981 // and set dst coeff to 1-Sa.
982 *dstCoeff = kISA_BlendCoeff;
983 return kCoverageAsAlpha_BlendOptFlag;
984 }
985 } else if (dstCoeffIsOne) {
986 // the dst coeff is effectively one so blend works out to:
987 // cS + (c)(1)D + (1-c)D = cS + D.
988 *dstCoeff = kOne_BlendCoeff;
989 return kCoverageAsAlpha_BlendOptFlag;
990 }
991 }
992 }
993 return kNone_BlendOpt;
994}
995
996bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000997 // there is a conflict between using smooth lines and our use of
998 // premultiplied alpha. Smooth lines tweak the incoming alpha value
999 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001000 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001001 if (!fCaps.fHWAALineSupport ||
1002 !(kAntialias_StateBit & fCurrDrawState.fFlagBits)) {
1003 return false;
1004 }
1005 BlendOptFlags opts = this->getBlendOpts();
1006 return (kDisableBlend_BlendOptFlag & opts) &&
1007 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001008}
1009
1010bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001011 // we can correctly apply coverage if a) we have dual source blending
1012 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001013 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001014 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001015}
1016
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001017bool GrDrawTarget::drawWillReadDst() const {
1018 return SkToBool((kDisableBlend_BlendOptFlag | kSkipDraw_BlendOptFlag) &
1019 this->getBlendOpts());
bsalomon@google.com471d4712011-08-23 15:45:25 +00001020}
1021
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +00001022///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com471d4712011-08-23 15:45:25 +00001023
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +00001024void GrDrawTarget::setEdgeAAData(const Edge* edges, int numEdges) {
1025 GrAssert(numEdges <= kMaxEdges);
1026 memcpy(fCurrDrawState.fEdgeAAEdges, edges, numEdges * sizeof(Edge));
1027 fCurrDrawState.fEdgeAANumEdges = numEdges;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +00001028}
1029
1030
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001031////////////////////////////////////////////////////////////////////////////////
1032
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001033void GrDrawTarget::drawRect(const GrRect& rect,
1034 const GrMatrix* matrix,
bsalomon@google.comffca4002011-02-22 20:34:01 +00001035 StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001036 const GrRect* srcRects[],
1037 const GrMatrix* srcMatrices[]) {
bsalomon@google.comffca4002011-02-22 20:34:01 +00001038 GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001039
1040 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001041 if (!geo.succeeded()) {
1042 GrPrintf("Failed to get space for vertices!\n");
1043 return;
1044 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001045
1046 SetRectVertices(rect, matrix, srcRects,
1047 srcMatrices, layout, geo.vertices());
1048
1049 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
1050}
1051
bsalomon@google.comffca4002011-02-22 20:34:01 +00001052GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001053 const GrRect* srcRects[]) {
1054 GrVertexLayout layout = 0;
1055
1056 for (int i = 0; i < kNumStages; ++i) {
1057 int numTC = 0;
bsalomon@google.comffca4002011-02-22 20:34:01 +00001058 if (stageEnableBitfield & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001059 if (NULL != srcRects && NULL != srcRects[i]) {
1060 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1061 ++numTC;
1062 } else {
1063 layout |= StagePosAsTexCoordVertexLayoutBit(i);
1064 }
1065 }
1066 }
1067 return layout;
1068}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001069
1070void GrDrawTarget::clipWillBeSet(const GrClip& clip) {
1071}
1072
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001073void GrDrawTarget::SetRectVertices(const GrRect& rect,
1074 const GrMatrix* matrix,
1075 const GrRect* srcRects[],
1076 const GrMatrix* srcMatrices[],
1077 GrVertexLayout layout,
1078 void* vertices) {
1079#if GR_DEBUG
1080 // check that the layout and srcRects agree
1081 for (int i = 0; i < kNumStages; ++i) {
1082 if (VertexTexCoordsForStage(i, layout) >= 0) {
1083 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1084 } else {
1085 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1086 }
1087 }
1088#endif
1089
1090 int stageOffsets[kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001091 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1092 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001093
bsalomon@google.coma3108262011-10-10 14:08:47 +00001094 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001095 rect.fRight, rect.fBottom,
1096 vsize);
1097 if (NULL != matrix) {
1098 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1099 }
1100
1101 for (int i = 0; i < kNumStages; ++i) {
1102 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001103 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001104 stageOffsets[i]);
1105 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001106 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001107 vsize);
1108 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1109 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1110 }
1111 }
1112 }
1113}
1114
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001115////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001116
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001117GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1118 fDrawTarget = NULL;
1119}
reed@google.comac10a2d2010-12-22 21:39:39 +00001120
1121GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
1122 fDrawTarget = target;
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001123 if (NULL != fDrawTarget) {
1124 fDrawTarget->saveCurrentDrawState(&fDrawState);
1125 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001126}
1127
1128GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001129 if (NULL != fDrawTarget) {
1130 fDrawTarget->restoreDrawState(fDrawState);
1131 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001132}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001133
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001134void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
1135 if (target != fDrawTarget) {
1136 if (NULL != fDrawTarget) {
1137 fDrawTarget->restoreDrawState(fDrawState);
1138 }
1139 if (NULL != target) {
bsalomon@google.comd19aa272011-06-22 01:28:17 +00001140 target->saveCurrentDrawState(&fDrawState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001141 }
1142 fDrawTarget = target;
1143 }
1144}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001145
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001146////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001147
1148GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target,
1149 int stageMask) {
1150 GrAssert(NULL != target);
1151
1152 fDrawTarget = target;
1153 fViewMatrix = target->getViewMatrix();
1154 fStageMask = stageMask;
1155 if (fStageMask) {
1156 GrMatrix invVM;
1157 if (fViewMatrix.invert(&invVM)) {
1158 for (int s = 0; s < kNumStages; ++s) {
1159 if (fStageMask & (1 << s)) {
1160 fSamplerMatrices[s] = target->getSamplerMatrix(s);
1161 }
1162 }
1163 target->preConcatSamplerMatrices(fStageMask, invVM);
1164 } else {
1165 // sad trombone sound
1166 fStageMask = 0;
1167 }
1168 }
1169 target->setViewMatrix(GrMatrix::I());
1170}
1171
1172GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
1173 fDrawTarget->setViewMatrix(fViewMatrix);
1174 for (int s = 0; s < kNumStages; ++s) {
1175 if (fStageMask & (1 << s)) {
1176 fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]);
1177 }
1178 }
1179}
1180
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001181////////////////////////////////////////////////////////////////////////////////
1182
1183GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1184 GrDrawTarget* target,
1185 GrVertexLayout vertexLayout,
1186 int vertexCount,
1187 int indexCount) {
1188 fTarget = NULL;
1189 this->set(target, vertexLayout, vertexCount, indexCount);
1190}
1191
1192GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1193 fTarget = NULL;
1194}
1195
1196GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1197 this->reset();
1198}
1199
1200bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1201 GrVertexLayout vertexLayout,
1202 int vertexCount,
1203 int indexCount) {
1204 this->reset();
1205 fTarget = target;
1206 bool success = true;
1207 if (NULL != fTarget) {
1208 fTarget = target;
1209 if (vertexCount > 0) {
1210 success = target->reserveVertexSpace(vertexLayout,
1211 vertexCount,
1212 &fVertices);
1213 if (!success) {
1214 this->reset();
1215 }
1216 }
1217 if (success && indexCount > 0) {
1218 success = target->reserveIndexSpace(indexCount, &fIndices);
1219 if (!success) {
1220 this->reset();
1221 }
1222 }
1223 }
1224 GrAssert(success == (NULL != fTarget));
1225 return success;
1226}
1227
1228void GrDrawTarget::AutoReleaseGeometry::reset() {
1229 if (NULL != fTarget) {
1230 if (NULL != fVertices) {
1231 fTarget->resetVertexSource();
1232 }
1233 if (NULL != fIndices) {
1234 fTarget->resetIndexSource();
1235 }
1236 fTarget = NULL;
1237 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001238 fVertices = NULL;
1239 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001240}
1241
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001242void GrDrawTarget::Caps::print() const {
1243 static const char* gNY[] = {"NO", "YES"};
1244 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
1245 GrPrintf("NPOT Texture Support : %s\n", gNY[fNPOTTextureSupport]);
1246 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
1247 GrPrintf("NPOT Render Target Support : %s\n", gNY[fNPOTRenderTargetSupport]);
1248 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1249 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1250 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
1251 GrPrintf("Shader Support : %s\n", gNY[fShaderSupport]);
1252 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001253 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001254 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1255 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1256 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
1257 GrPrintf("Min Render Target Width : %d\n", fMinRenderTargetWidth);
1258 GrPrintf("Min Render Target Height : %d\n", fMinRenderTargetHeight);
1259 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1260 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1261}
1262