blob: 3e3ff51d450e50d413841d7163a2a546898cdd00 [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.com8f9cbd62011-12-09 15:55:34 +000013#include "GrIndexBuffer.h"
14#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000015#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000016#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
junov@google.com6acc9b32011-05-16 18:32:07 +000018namespace {
19
bsalomon@google.com35ff3842011-12-15 16:58:19 +000020/**
21 * This function generates some masks that we like to have known at compile
22 * time. When the number of stages or tex coords is bumped or the way bits
23 * are defined in GrDrawTarget.h changes this funcion should be rerun to
24 * generate the new masks. (We attempted to force the compiler to generate the
25 * masks using recursive templates but always wound up with static initializers
26 * under gcc, even if they were just a series of immediate->memory moves.)
27 *
28 */
29void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
30 GrVertexLayout* stageMasks,
31 GrVertexLayout* texCoordMasks) {
32 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
33 stageTexCoordMasks[s] = 0;
34 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
35 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
36 }
37 stageMasks[s] = stageTexCoordMasks[s] | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
38 }
39 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
40 texCoordMasks[t] = 0;
41 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
42 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
43 }
44 }
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
bsalomon@google.com35ff3842011-12-15 16:58:19 +000047/**
48 * Run this function to generate the code that declares the global masks.
49 */
50void gen_globals() {
51 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
52 GrVertexLayout stageMasks[GrDrawState::kNumStages];
53 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
54 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
55
56 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
57 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
58 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
59 }
60 GrPrintf("};\n");
61 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
62 GrPrintf("const GrVertexLayout gStageMasks[] = {\n");
63 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
64 GrPrintf(" 0x%x,\n", stageMasks[s]);
65 }
66 GrPrintf("};\n");
67 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\n\n");
68 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
69 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
70 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
71 }
72 GrPrintf("};\n");
73 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000074}
75
bsalomon@google.com35ff3842011-12-15 16:58:19 +000076/* These values were generated by the above function */
77const GrVertexLayout gStageTexCoordMasks[] = {
78 0x49,
79 0x92,
80 0x124
81};
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000082
bsalomon@google.com35ff3842011-12-15 16:58:19 +000083GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
84const GrVertexLayout gStageMasks[] = {
85 0x249,
86 0x492,
87 0x924
88};
89
90GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));
91const GrVertexLayout gTexCoordMasks[] = {
92 0x7,
93 0x38,
94 0x1c0,
95};
96GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097
98bool check_layout(GrVertexLayout layout) {
99 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +0000100 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000101 int stageBits = layout & gStageMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000102 if (stageBits && !GrIsPow2(stageBits)) {
103 return false;
104 }
105 }
106 return true;
107}
108
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000109int num_tex_coords(GrVertexLayout layout) {
110 int cnt = 0;
111 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000112 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000113 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000114 ++cnt;
115 }
116 }
117 return cnt;
118}
119
junov@google.com6acc9b32011-05-16 18:32:07 +0000120} //unnamed namespace
121
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000122size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
123 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000124
125 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000126 sizeof(GrGpuTextVertex) :
127 sizeof(GrPoint);
128
129 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000130 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131 if (vertexLayout & kColor_VertexLayoutBit) {
132 size += sizeof(GrColor);
133 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000134 if (vertexLayout & kCoverage_VertexLayoutBit) {
135 size += sizeof(GrColor);
136 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000137 if (vertexLayout & kEdge_VertexLayoutBit) {
138 size += 4 * sizeof(GrScalar);
139 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000140 return size;
141}
142
bsalomon@google.coma3108262011-10-10 14:08:47 +0000143////////////////////////////////////////////////////////////////////////////////
144
145/**
146 * Functions for computing offsets of various components from the layout
147 * bitfield.
148 *
149 * Order of vertex components:
150 * Position
151 * Tex Coord 0
152 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000153 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000154 * Color
155 * Coverage
156 */
157
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000158int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
159 GrAssert(check_layout(vertexLayout));
160 if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000161 return 0;
162 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000163 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
164 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000165
166 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 sizeof(GrGpuTextVertex) :
168 sizeof(GrPoint);
169 int offset = vecSize; // position
170 // figure out how many tex coordinates are present and precede this one.
171 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000172 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000173 offset += vecSize;
174 }
175 }
176 return offset;
177 }
178
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 return -1;
180}
181
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000182int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000183 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000184
reed@google.comac10a2d2010-12-22 21:39:39 +0000185 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000186 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000187 sizeof(GrGpuTextVertex) :
188 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000189 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
190 }
191 return -1;
192}
193
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000194int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000195 GrAssert(check_layout(vertexLayout));
196
197 if (vertexLayout & kCoverage_VertexLayoutBit) {
198 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
199 sizeof(GrGpuTextVertex) :
200 sizeof(GrPoint);
201
202 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
203 if (vertexLayout & kColor_VertexLayoutBit) {
204 offset += sizeof(GrColor);
205 }
206 return offset;
207 }
208 return -1;
209}
210
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000211int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000212 GrAssert(check_layout(vertexLayout));
213
214 // edge pts are after the pos, tex coords, and color
215 if (vertexLayout & kEdge_VertexLayoutBit) {
216 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
217 sizeof(GrGpuTextVertex) :
218 sizeof(GrPoint);
219 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
220 if (vertexLayout & kColor_VertexLayoutBit) {
221 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000222 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000223 if (vertexLayout & kCoverage_VertexLayoutBit) {
224 offset += sizeof(GrColor);
225 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000226 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 }
228 return -1;
229}
230
tomhudson@google.com93813632011-10-27 20:21:16 +0000231int GrDrawTarget::VertexSizeAndOffsetsByIdx(
232 GrVertexLayout vertexLayout,
233 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
234 int* colorOffset,
235 int* coverageOffset,
236 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000237 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000238
bsalomon@google.com5782d712011-01-21 21:03:59 +0000239 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000240 sizeof(GrGpuTextVertex) :
241 sizeof(GrPoint);
242 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000243
tomhudson@google.com93813632011-10-27 20:21:16 +0000244 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000245 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000246 if (NULL != texCoordOffsetsByIdx) {
247 texCoordOffsetsByIdx[t] = size;
248 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000249 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000251 if (NULL != texCoordOffsetsByIdx) {
252 texCoordOffsetsByIdx[t] = -1;
253 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000254 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000256 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000257 if (NULL != colorOffset) {
258 *colorOffset = size;
259 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000260 size += sizeof(GrColor);
261 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000262 if (NULL != colorOffset) {
263 *colorOffset = -1;
264 }
265 }
266 if (kCoverage_VertexLayoutBit & vertexLayout) {
267 if (NULL != coverageOffset) {
268 *coverageOffset = size;
269 }
270 size += sizeof(GrColor);
271 } else {
272 if (NULL != coverageOffset) {
273 *coverageOffset = -1;
274 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000275 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000276 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000277 if (NULL != edgeOffset) {
278 *edgeOffset = size;
279 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000280 size += 4 * sizeof(GrScalar);
281 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000282 if (NULL != edgeOffset) {
283 *edgeOffset = -1;
284 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000285 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000286 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000287}
288
tomhudson@google.com93813632011-10-27 20:21:16 +0000289int GrDrawTarget::VertexSizeAndOffsetsByStage(
290 GrVertexLayout vertexLayout,
291 int texCoordOffsetsByStage[GrDrawState::kNumStages],
292 int* colorOffset,
293 int* coverageOffset,
294 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000295 GrAssert(check_layout(vertexLayout));
296
tomhudson@google.com93813632011-10-27 20:21:16 +0000297 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000298 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000299 (NULL == texCoordOffsetsByStage) ?
300 NULL :
301 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000302 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000303 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000304 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000305 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000306 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000307 int tcIdx;
308 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
309 texCoordOffsetsByStage[s] = 0;
310 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
311 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
312 } else {
313 texCoordOffsetsByStage[s] = -1;
314 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000315 }
316 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000317 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000318}
319
bsalomon@google.coma3108262011-10-10 14:08:47 +0000320////////////////////////////////////////////////////////////////////////////////
321
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000322bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000323 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000324 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000325 return !!(gStageMasks[stage] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000326}
327
bsalomon@google.com5782d712011-01-21 21:03:59 +0000328bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000329 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000330 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000331 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000332 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000333}
334
tomhudson@google.com93813632011-10-27 20:21:16 +0000335int GrDrawTarget::VertexTexCoordsForStage(int stage,
336 GrVertexLayout vertexLayout) {
337 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000338 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000339 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000340 if (bit) {
341 // figure out which set of texture coordates is used
342 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
343 // and start at bit 0.
344 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000345 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000346 }
347 return -1;
348}
349
bsalomon@google.coma3108262011-10-10 14:08:47 +0000350////////////////////////////////////////////////////////////////////////////////
351
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000353 // Ensure that our globals mask arrays are correct
354 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
355 GrVertexLayout stageMasks[GrDrawState::kNumStages];
356 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
357 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
358 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
359 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
360 GrAssert(stageMasks[s] == gStageMasks[s]);
361 }
362 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
363 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
364 }
365
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000366 // not necessarily exhaustive
367 static bool run;
368 if (!run) {
369 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000370 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000371
372 GrAssert(!VertexUsesStage(s, 0));
373 GrAssert(-1 == VertexStageCoordOffset(s, 0));
374 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000375 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000376 stageMask |= StageTexCoordVertexLayoutBit(s,t);
377 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000378 GrAssert(1 == GrDrawState::kMaxTexCoords ||
379 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000380 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000381 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000382 GrAssert(gStageMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000383 GrAssert(!check_layout(stageMask));
384 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000385 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000386 GrVertexLayout tcMask = 0;
387 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000388 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000389 tcMask |= StageTexCoordVertexLayoutBit(s,t);
390 GrAssert(VertexUsesStage(s, tcMask));
391 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
392 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
393 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
394 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000395 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000396 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
397 GrAssert(!VertexUsesStage(s2, tcMask));
398 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000399
bsalomon@google.com19628322011-02-03 21:30:17 +0000400 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000401 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000402 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000403 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
404 GrAssert(VertexUsesStage(s2, posAsTex));
405 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
406 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000407 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000408 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000409 GrAssert(-1 == VertexEdgeOffset(tcMask));
410 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000411 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000412 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000413 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000414 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000415 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000416 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
417 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000418 #if GR_DEBUG
419 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
420 #endif
421 GrAssert(-1 == VertexColorOffset(withEdge));
422 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
423 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
424 #if GR_DEBUG
425 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
426 #endif
427 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
428 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
429 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000430 #if GR_DEBUG
431 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
432 #endif
433 GrAssert(-1 == VertexColorOffset(withCoverage));
434 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
435 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
436 #if GR_DEBUG
437 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
438 kColor_VertexLayoutBit;
439 #endif
440 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
441 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
442 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000443 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000444 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000445 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000446
tomhudson@google.com93813632011-10-27 20:21:16 +0000447 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000448 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000449 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000450 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000451 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000452 size = VertexSizeAndOffsetsByStage(tcMask,
453 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000454 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000455 GrAssert(2*sizeof(GrPoint) == size);
456 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000457 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000458 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000459 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000460 GrAssert(VertexUsesStage(s, tcMask));
461 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
462 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
463 }
464 }
465 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000466}
467
468////////////////////////////////////////////////////////////////////////////////
469
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000470#define DEBUG_INVAL_BUFFER 0xdeadcafe
471#define DEBUG_INVAL_START_IDX -1
472
bsalomon@google.com92669012011-09-27 19:10:05 +0000473GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000474#if GR_DEBUG
475 VertexLayoutUnitTest();
476#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000477 fDrawState = &fDefaultDrawState;
478 // We assume that fDrawState always owns a ref to the object it points at.
479 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000480 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000481#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000482 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
483 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
484 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
485 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000486#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000487 geoSrc.fVertexSrc = kNone_GeometrySrcType;
488 geoSrc.fIndexSrc = kNone_GeometrySrcType;
489}
490
491GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000492 GrAssert(1 == fGeoSrcStateStack.count());
493 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
494 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
495 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000496 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000497}
498
499void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000500 int popCnt = fGeoSrcStateStack.count() - 1;
501 while (popCnt) {
502 this->popGeometrySource();
503 --popCnt;
504 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000505 this->resetVertexSource();
506 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000507}
508
509void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000510 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000511 fClip = clip;
512}
513
514const GrClip& GrDrawTarget::getClip() const {
515 return fClip;
516}
517
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000518void GrDrawTarget::setDrawState(GrDrawState* drawState) {
519 GrAssert(NULL != fDrawState);
520 if (NULL == drawState) {
521 drawState = &fDefaultDrawState;
522 }
523 if (fDrawState != drawState) {
524 fDrawState->unref();
525 drawState->ref();
526 fDrawState = drawState;
527 }
528}
529
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000530bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
531 int vertexCount,
532 void** vertices) {
533 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
534 bool acquired = false;
535 if (vertexCount > 0) {
536 GrAssert(NULL != vertices);
537 this->releasePreviousVertexSource();
538 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000539
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000540 acquired = this->onReserveVertexSpace(vertexLayout,
541 vertexCount,
542 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000543 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000544 if (acquired) {
545 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
546 geoSrc.fVertexCount = vertexCount;
547 geoSrc.fVertexLayout = vertexLayout;
548 } else if (NULL != vertices) {
549 *vertices = NULL;
550 }
551 return acquired;
552}
553
554bool GrDrawTarget::reserveIndexSpace(int indexCount,
555 void** indices) {
556 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
557 bool acquired = false;
558 if (indexCount > 0) {
559 GrAssert(NULL != indices);
560 this->releasePreviousIndexSource();
561 geoSrc.fIndexSrc = kNone_GeometrySrcType;
562
563 acquired = this->onReserveIndexSpace(indexCount, indices);
564 }
565 if (acquired) {
566 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
567 geoSrc.fIndexCount = indexCount;
568 } else if (NULL != indices) {
569 *indices = NULL;
570 }
571 return acquired;
572
reed@google.comac10a2d2010-12-22 21:39:39 +0000573}
574
bsalomon@google.come3d70952012-03-13 12:40:53 +0000575bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
576 int vertexCount,
577 int indexCount,
578 void** vertices,
579 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000580 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000581 if (vertexCount) {
582 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
583 if (indexCount) {
584 this->resetIndexSource();
585 }
586 return false;
587 }
588 }
589 if (indexCount) {
590 if (!this->reserveIndexSpace(indexCount, indices)) {
591 if (vertexCount) {
592 this->resetVertexSource();
593 }
594 return false;
595 }
596 }
597 return true;
598}
599
reed@google.comac10a2d2010-12-22 21:39:39 +0000600bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
601 int32_t* vertexCount,
602 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000603 if (NULL != vertexCount) {
604 *vertexCount = -1;
605 }
606 if (NULL != indexCount) {
607 *indexCount = -1;
608 }
609 return false;
610}
611
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000612void GrDrawTarget::releasePreviousVertexSource() {
613 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
614 switch (geoSrc.fVertexSrc) {
615 case kNone_GeometrySrcType:
616 break;
617 case kArray_GeometrySrcType:
618 this->releaseVertexArray();
619 break;
620 case kReserved_GeometrySrcType:
621 this->releaseReservedVertexSpace();
622 break;
623 case kBuffer_GeometrySrcType:
624 geoSrc.fVertexBuffer->unref();
625#if GR_DEBUG
626 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
627#endif
628 break;
629 default:
630 GrCrash("Unknown Vertex Source Type.");
631 break;
632 }
633}
634
635void GrDrawTarget::releasePreviousIndexSource() {
636 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
637 switch (geoSrc.fIndexSrc) {
638 case kNone_GeometrySrcType: // these two don't require
639 break;
640 case kArray_GeometrySrcType:
641 this->releaseIndexArray();
642 break;
643 case kReserved_GeometrySrcType:
644 this->releaseReservedIndexSpace();
645 break;
646 case kBuffer_GeometrySrcType:
647 geoSrc.fIndexBuffer->unref();
648#if GR_DEBUG
649 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
650#endif
651 break;
652 default:
653 GrCrash("Unknown Index Source Type.");
654 break;
655 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000656}
657
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000658void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
659 const void* vertexArray,
660 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000661 this->releasePreviousVertexSource();
662 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
663 geoSrc.fVertexSrc = kArray_GeometrySrcType;
664 geoSrc.fVertexLayout = vertexLayout;
665 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000666 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000667}
668
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000669void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
670 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000671 this->releasePreviousIndexSource();
672 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
673 geoSrc.fIndexSrc = kArray_GeometrySrcType;
674 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000675 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000676}
677
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000678void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
679 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000680 this->releasePreviousVertexSource();
681 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
682 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
683 geoSrc.fVertexBuffer = buffer;
684 buffer->ref();
685 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000686}
687
688void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000689 this->releasePreviousIndexSource();
690 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
691 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
692 geoSrc.fIndexBuffer = buffer;
693 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000694}
695
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000696void GrDrawTarget::resetVertexSource() {
697 this->releasePreviousVertexSource();
698 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
699 geoSrc.fVertexSrc = kNone_GeometrySrcType;
700}
701
702void GrDrawTarget::resetIndexSource() {
703 this->releasePreviousIndexSource();
704 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
705 geoSrc.fIndexSrc = kNone_GeometrySrcType;
706}
707
708void GrDrawTarget::pushGeometrySource() {
709 this->geometrySourceWillPush();
710 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
711 newState.fIndexSrc = kNone_GeometrySrcType;
712 newState.fVertexSrc = kNone_GeometrySrcType;
713#if GR_DEBUG
714 newState.fVertexCount = ~0;
715 newState.fVertexBuffer = (GrVertexBuffer*)~0;
716 newState.fIndexCount = ~0;
717 newState.fIndexBuffer = (GrIndexBuffer*)~0;
718#endif
719}
720
721void GrDrawTarget::popGeometrySource() {
722 const GeometrySrcState& geoSrc = this->getGeomSrc();
723 // if popping last element then pops are unbalanced with pushes
724 GrAssert(fGeoSrcStateStack.count() > 1);
725
726 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
727 this->releasePreviousVertexSource();
728 this->releasePreviousIndexSource();
729 fGeoSrcStateStack.pop_back();
730}
731
732////////////////////////////////////////////////////////////////////////////////
733
bsalomon@google.come8262622011-11-07 02:30:51 +0000734bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
735 int startIndex, int vertexCount,
736 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000737#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000738 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000739 int maxVertex = startVertex + vertexCount;
740 int maxValidVertex;
741 switch (geoSrc.fVertexSrc) {
742 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000743 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000744 case kReserved_GeometrySrcType: // fallthrough
745 case kArray_GeometrySrcType:
746 maxValidVertex = geoSrc.fVertexCount;
747 break;
748 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000749 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000750 VertexSize(geoSrc.fVertexLayout);
751 break;
752 }
753 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000754 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000755 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000756 if (indexCount > 0) {
757 int maxIndex = startIndex + indexCount;
758 int maxValidIndex;
759 switch (geoSrc.fIndexSrc) {
760 case kNone_GeometrySrcType:
761 GrCrash("Attempting to draw indexed geom without index src.");
762 case kReserved_GeometrySrcType: // fallthrough
763 case kArray_GeometrySrcType:
764 maxValidIndex = geoSrc.fIndexCount;
765 break;
766 case kBuffer_GeometrySrcType:
767 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
768 break;
769 }
770 if (maxIndex > maxValidIndex) {
771 GrCrash("Index reads outside valid index range.");
772 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000773 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000774
775 GrAssert(NULL != this->getDrawState().getRenderTarget());
776 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
777 if (this->getDrawState().getTexture(i)) {
778 GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
779 this->getDrawState().getRenderTarget());
780 }
781 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000782#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000783 const GrDrawState& drawState = this->getDrawState();
784 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000785 return false;
786 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000787 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
788 if (kOne_BlendCoeff != drawState.getSrcBlendCoeff() ||
789 kZero_BlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000790 return false;
791 }
792 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000793 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com74b98712011-11-11 19:46:16 +0000794 // We don't support using unpremultiplied textures with filters (other
795 // than nearest). Alpha-premulling is not distributive WRT to filtering.
796 // We'd have to filter each texel before filtering. We could do this for
797 // our custom filters but we would also have to disable bilerp and do
798 // a custom bilerp in the shader. Until Skia itself supports unpremul
799 // configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000800 if (this->isStageEnabled(s) &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000801 GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
802 GrSamplerState::kNearest_Filter !=
803 drawState.getSampler(s).getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000804 return false;
805 }
806 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000807 return true;
808}
809
810void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
811 int startIndex, int vertexCount,
812 int indexCount) {
813 if (indexCount > 0 &&
814 this->checkDraw(type, startVertex, startIndex,
815 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000816 this->onDrawIndexed(type, startVertex, startIndex,
817 vertexCount, indexCount);
818 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000819}
820
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000821void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
822 int startVertex,
823 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000824 if (vertexCount > 0 &&
825 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000826 this->onDrawNonIndexed(type, startVertex, vertexCount);
827 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000828}
829
830////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000831
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000832// Some blend modes allow folding a partial coverage value into the color's
833// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000834bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000835 /**
836 * The fractional coverage is f
837 * The src and dst coeffs are Cs and Cd
838 * The dst and src colors are S and D
839 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
840 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
841 * obvious that that first term will always be ok. The second term can be
842 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
843 * for Cd we find that only 1, ISA, and ISC produce the correct depth
844 * coeffecient in terms of S' and D.
845 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000846 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
847 return kOne_BlendCoeff == dstCoeff ||
848 kISA_BlendCoeff == dstCoeff ||
849 kISC_BlendCoeff == dstCoeff;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000850}
851
bsalomon@google.come79c8152012-03-29 19:07:12 +0000852bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000853 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000854
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000855 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000856 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000857 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000858 return false;
859 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000860 // Check if color filter could introduce an alpha
861 // (TODO: Consider being more aggressive with regards to detecting 0xff
862 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000863 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000864 return false;
865 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000866 // Check if a color stage could create a partial alpha
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000867 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000868 if (StageWillBeUsed(s, layout, this->getDrawState())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000869 GrAssert(NULL != drawState.getTexture(s));
870 GrPixelConfig config = drawState.getTexture(s)->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000871 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000872 return false;
873 }
874 }
875 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000876 return true;
877}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000878
bsalomon@google.come79c8152012-03-29 19:07:12 +0000879namespace {
880GrVertexLayout default_blend_opts_vertex_layout() {
881 GrVertexLayout layout = 0;
882 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
883 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
884 }
885 return layout;
886}
887}
888
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000889GrDrawTarget::BlendOptFlags
890GrDrawTarget::getBlendOpts(bool forceCoverage,
891 GrBlendCoeff* srcCoeff,
892 GrBlendCoeff* dstCoeff) const {
893
bsalomon@google.come79c8152012-03-29 19:07:12 +0000894 GrVertexLayout layout;
895 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
896 layout = default_blend_opts_vertex_layout();
897 } else {
898 layout = this->getVertexLayout();
899 }
900
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000901 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000902
903 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
904 if (NULL == srcCoeff) {
905 srcCoeff = &bogusSrcCoeff;
906 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000907 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000908
909 if (NULL == dstCoeff) {
910 dstCoeff = &bogusDstCoeff;
911 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000912 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000913
914 // We don't ever expect source coeffecients to reference the source
915 GrAssert(kSA_BlendCoeff != *srcCoeff &&
916 kISA_BlendCoeff != *srcCoeff &&
917 kSC_BlendCoeff != *srcCoeff &&
918 kISC_BlendCoeff != *srcCoeff);
919 // same for dst
920 GrAssert(kDA_BlendCoeff != *dstCoeff &&
921 kIDA_BlendCoeff != *dstCoeff &&
922 kDC_BlendCoeff != *dstCoeff &&
923 kIDC_BlendCoeff != *dstCoeff);
924
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000925 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000926 *srcCoeff = kZero_BlendCoeff;
927 *dstCoeff = kOne_BlendCoeff;
928 }
929
bsalomon@google.come79c8152012-03-29 19:07:12 +0000930 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000931 bool dstCoeffIsOne = kOne_BlendCoeff == *dstCoeff ||
932 (kSA_BlendCoeff == *dstCoeff && srcAIsOne);
933 bool dstCoeffIsZero = kZero_BlendCoeff == *dstCoeff ||
934 (kISA_BlendCoeff == *dstCoeff && srcAIsOne);
935
936
937 // When coeffs are (0,1) there is no reason to draw at all, unless
938 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000939 // (0,1). The same applies when coverage is known to be 0.
940 if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne) ||
941 (!(layout & kCoverage_VertexLayoutBit) &&
942 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000943 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000944 return kDisableBlend_BlendOptFlag |
945 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000946 } else {
947 return kSkipDraw_BlendOptFlag;
948 }
949 }
950
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000951 // check for coverage due to constant coverage, per-vertex coverage,
952 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000953 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000954 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000955 drawState.getNumAAEdges() > 0 ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000956 (layout & kCoverage_VertexLayoutBit) ||
957 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000958 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000959 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000960 ++s) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000961 if (StageWillBeUsed(s, layout, this->getDrawState())) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000962 hasCoverage = true;
963 }
964 }
965
966 // if we don't have coverage we can check whether the dst
967 // has to read at all. If not, we'll disable blending.
968 if (!hasCoverage) {
969 if (dstCoeffIsZero) {
970 if (kOne_BlendCoeff == *srcCoeff) {
971 // if there is no coverage and coeffs are (1,0) then we
972 // won't need to read the dst at all, it gets replaced by src
973 return kDisableBlend_BlendOptFlag;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000974 } else if (kZero_BlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000975 // if the op is "clear" then we don't need to emit a color
976 // or blend, just write transparent black into the dst.
977 *srcCoeff = kOne_BlendCoeff;
978 *dstCoeff = kZero_BlendCoeff;
979 return kDisableBlend_BlendOptFlag |
980 kEmitTransBlack_BlendOptFlag;
981 }
982 }
983 } else {
984 // check whether coverage can be safely rolled into alpha
985 // of if we can skip color computation and just emit coverage
986 if (this->canTweakAlphaForCoverage()) {
987 return kCoverageAsAlpha_BlendOptFlag;
988 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000989 if (dstCoeffIsZero) {
990 if (kZero_BlendCoeff == *srcCoeff) {
991 // the source color is not included in the blend
992 // the dst coeff is effectively zero so blend works out to:
993 // (c)(0)D + (1-c)D = (1-c)D.
994 *dstCoeff = kISA_BlendCoeff;
995 return kEmitCoverage_BlendOptFlag;
996 } else if (srcAIsOne) {
997 // the dst coeff is effectively zero so blend works out to:
998 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
999 // If Sa is 1 then we can replace Sa with c
1000 // and set dst coeff to 1-Sa.
1001 *dstCoeff = kISA_BlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001002 return kCoverageAsAlpha_BlendOptFlag;
1003 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001004 } else if (dstCoeffIsOne) {
1005 // the dst coeff is effectively one so blend works out to:
1006 // cS + (c)(1)D + (1-c)D = cS + D.
1007 *dstCoeff = kOne_BlendCoeff;
1008 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001009 }
1010 }
1011 return kNone_BlendOpt;
1012}
1013
1014bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001015 // there is a conflict between using smooth lines and our use of
1016 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1017 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001018 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001019 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001020 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001021 return false;
1022 }
1023 BlendOptFlags opts = this->getBlendOpts();
1024 return (kDisableBlend_BlendOptFlag & opts) &&
1025 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001026}
1027
1028bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001029 // we can correctly apply coverage if a) we have dual source blending
1030 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001031 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001032 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001033}
1034
bsalomon@google.com934c5702012-03-20 21:17:58 +00001035////////////////////////////////////////////////////////////////////////////////
1036
1037void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1038 int instanceCount,
1039 int verticesPerInstance,
1040 int indicesPerInstance) {
1041 if (!verticesPerInstance || !indicesPerInstance) {
1042 return;
1043 }
1044
1045 int instancesPerDraw = this->indexCountInCurrentSource() /
1046 indicesPerInstance;
1047 if (!instancesPerDraw) {
1048 return;
1049 }
1050
1051 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1052 int startVertex = 0;
1053 while (instanceCount) {
1054 this->drawIndexed(type,
1055 startVertex,
1056 0,
1057 verticesPerInstance * instancesPerDraw,
1058 indicesPerInstance * instancesPerDraw);
1059 startVertex += verticesPerInstance;
1060 instanceCount -= instancesPerDraw;
1061 }
1062}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001063
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001064////////////////////////////////////////////////////////////////////////////////
1065
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001066void GrDrawTarget::drawRect(const GrRect& rect,
1067 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001068 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001069 const GrRect* srcRects[],
1070 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001071 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001072
1073 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001074 if (!geo.succeeded()) {
1075 GrPrintf("Failed to get space for vertices!\n");
1076 return;
1077 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001078
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001079 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001080 srcMatrices, layout, geo.vertices());
1081
1082 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
1083}
1084
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001085GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001086 const GrRect* srcRects[]) {
1087 GrVertexLayout layout = 0;
1088
tomhudson@google.com93813632011-10-27 20:21:16 +00001089 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001090 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001091 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001092 if (NULL != srcRects && NULL != srcRects[i]) {
1093 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1094 ++numTC;
1095 } else {
1096 layout |= StagePosAsTexCoordVertexLayoutBit(i);
1097 }
1098 }
1099 }
1100 return layout;
1101}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001102
1103void GrDrawTarget::clipWillBeSet(const GrClip& clip) {
1104}
1105
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001106void GrDrawTarget::SetRectVertices(const GrRect& rect,
1107 const GrMatrix* matrix,
1108 const GrRect* srcRects[],
1109 const GrMatrix* srcMatrices[],
1110 GrVertexLayout layout,
1111 void* vertices) {
1112#if GR_DEBUG
1113 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001114 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001115 if (VertexTexCoordsForStage(i, layout) >= 0) {
1116 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1117 } else {
1118 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1119 }
1120 }
1121#endif
1122
tomhudson@google.com93813632011-10-27 20:21:16 +00001123 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001124 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1125 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001126
bsalomon@google.coma3108262011-10-10 14:08:47 +00001127 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001128 rect.fRight, rect.fBottom,
1129 vsize);
1130 if (NULL != matrix) {
1131 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1132 }
1133
tomhudson@google.com93813632011-10-27 20:21:16 +00001134 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001135 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001136 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001137 stageOffsets[i]);
1138 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001139 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001140 vsize);
1141 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1142 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1143 }
1144 }
1145 }
1146}
1147
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001148////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001149
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001150GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1151 fDrawTarget = NULL;
1152}
reed@google.comac10a2d2010-12-22 21:39:39 +00001153
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001154GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1155 ASRInit init) {
1156 fDrawTarget = NULL;
1157 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001158}
1159
1160GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001161 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001162 fDrawTarget->setDrawState(fSavedState);
1163 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001164 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001165}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001166
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001167void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1168 GrAssert(NULL == fDrawTarget);
1169 fDrawTarget = target;
1170 fSavedState = target->drawState();
1171 GrAssert(fSavedState);
1172 fSavedState->ref();
1173 if (kReset_ASRInit == init) {
1174 // calls the default cons
1175 fTempState.init();
1176 } else {
1177 GrAssert(kPreserve_ASRInit == init);
1178 // calls the copy cons
1179 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001180 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001181 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001182}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001183
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001184////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001185
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001186GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1187 GrDrawTarget* target,
1188 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001189 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001190 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001191
1192 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001193 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001194 fStageMask = stageMask;
1195 if (fStageMask) {
1196 GrMatrix invVM;
1197 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001198 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001199 if (fStageMask & (1 << s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001200 fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001201 }
1202 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001203 drawState->preConcatSamplerMatrices(fStageMask, invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001204 } else {
1205 // sad trombone sound
1206 fStageMask = 0;
1207 }
1208 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001209 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001210}
1211
1212GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001213 GrDrawState* drawState = fDrawTarget->drawState();
1214 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001215 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001216 if (fStageMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001217 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001218 }
1219 }
1220}
1221
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001222////////////////////////////////////////////////////////////////////////////////
1223
1224GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1225 GrDrawTarget* target,
1226 GrVertexLayout vertexLayout,
1227 int vertexCount,
1228 int indexCount) {
1229 fTarget = NULL;
1230 this->set(target, vertexLayout, vertexCount, indexCount);
1231}
1232
1233GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1234 fTarget = NULL;
1235}
1236
1237GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1238 this->reset();
1239}
1240
1241bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1242 GrVertexLayout vertexLayout,
1243 int vertexCount,
1244 int indexCount) {
1245 this->reset();
1246 fTarget = target;
1247 bool success = true;
1248 if (NULL != fTarget) {
1249 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001250 success = target->reserveVertexAndIndexSpace(vertexLayout,
1251 vertexCount,
1252 indexCount,
1253 &fVertices,
1254 &fIndices);
1255 if (!success) {
1256 fTarget = NULL;
1257 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001258 }
1259 }
1260 GrAssert(success == (NULL != fTarget));
1261 return success;
1262}
1263
1264void GrDrawTarget::AutoReleaseGeometry::reset() {
1265 if (NULL != fTarget) {
1266 if (NULL != fVertices) {
1267 fTarget->resetVertexSource();
1268 }
1269 if (NULL != fIndices) {
1270 fTarget->resetIndexSource();
1271 }
1272 fTarget = NULL;
1273 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001274 fVertices = NULL;
1275 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001276}
1277
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001278void GrDrawTarget::Caps::print() const {
1279 static const char* gNY[] = {"NO", "YES"};
1280 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001281 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001282 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1283 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1284 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001285 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001286 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001287 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1288 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1289 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001290 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1291 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1292}
1293