blob: 39ea5bfe3902b8e366a955319b2b4ae8f40aeb43 [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
robertphillips@google.coma72eef32012-05-01 17:22:59 +000023 * are defined in GrDrawTarget.h changes this function should be rerun to
bsalomon@google.com35ff3842011-12-15 16:58:19 +000024 * 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 }
tomhudson@google.comb213ed82012-06-25 15:22:12 +000037 stageMasks[s] = stageTexCoordMasks[s];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000038 }
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[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000078 0x1111,
79 0x2222,
80 0x4444,
81 0x8888,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000082};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000083GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000084
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000085const GrVertexLayout gStageMasks[] = {
tomhudson@google.comb213ed82012-06-25 15:22:12 +000086 0x1111,
87 0x2222,
88 0x4444,
89 0x8888,
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000090};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000091GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000092
bsalomon@google.com35ff3842011-12-15 16:58:19 +000093const GrVertexLayout gTexCoordMasks[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000094 0xf,
95 0xf0,
96 0xf00,
97 0xf000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000098};
99GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000100
robertphillips@google.comec05eaa2012-04-27 18:59:52 +0000101
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000102
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000103bool check_layout(GrVertexLayout layout) {
104 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +0000105 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000106 int stageBits = layout & gStageMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000107 if (stageBits && !GrIsPow2(stageBits)) {
108 return false;
109 }
110 }
111 return true;
112}
113
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000114int num_tex_coords(GrVertexLayout layout) {
115 int cnt = 0;
116 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000117 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000118 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000119 ++cnt;
120 }
121 }
122 return cnt;
123}
124
junov@google.com6acc9b32011-05-16 18:32:07 +0000125} //unnamed namespace
126
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000127size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
128 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000129
130 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131 sizeof(GrGpuTextVertex) :
132 sizeof(GrPoint);
133
134 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000135 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000136 if (vertexLayout & kColor_VertexLayoutBit) {
137 size += sizeof(GrColor);
138 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000139 if (vertexLayout & kCoverage_VertexLayoutBit) {
140 size += sizeof(GrColor);
141 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000142 if (vertexLayout & kEdge_VertexLayoutBit) {
143 size += 4 * sizeof(GrScalar);
144 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000145 return size;
146}
147
bsalomon@google.coma3108262011-10-10 14:08:47 +0000148////////////////////////////////////////////////////////////////////////////////
149
150/**
151 * Functions for computing offsets of various components from the layout
152 * bitfield.
153 *
154 * Order of vertex components:
155 * Position
156 * Tex Coord 0
157 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000158 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000159 * Color
160 * Coverage
161 */
162
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000163int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
164 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000165
166 if (!StageUsesTexCoords(vertexLayout, stage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000167 return 0;
168 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000169 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
170 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000171
172 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000173 sizeof(GrGpuTextVertex) :
174 sizeof(GrPoint);
175 int offset = vecSize; // position
176 // figure out how many tex coordinates are present and precede this one.
177 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000178 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000179 offset += vecSize;
180 }
181 }
182 return offset;
183 }
184
reed@google.comac10a2d2010-12-22 21:39:39 +0000185 return -1;
186}
187
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000188int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000189 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000190
reed@google.comac10a2d2010-12-22 21:39:39 +0000191 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000192 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 sizeof(GrGpuTextVertex) :
194 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000195 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
196 }
197 return -1;
198}
199
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000200int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000201 GrAssert(check_layout(vertexLayout));
202
203 if (vertexLayout & kCoverage_VertexLayoutBit) {
204 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
205 sizeof(GrGpuTextVertex) :
206 sizeof(GrPoint);
207
208 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
209 if (vertexLayout & kColor_VertexLayoutBit) {
210 offset += sizeof(GrColor);
211 }
212 return offset;
213 }
214 return -1;
215}
216
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000217int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000218 GrAssert(check_layout(vertexLayout));
219
220 // edge pts are after the pos, tex coords, and color
221 if (vertexLayout & kEdge_VertexLayoutBit) {
222 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
223 sizeof(GrGpuTextVertex) :
224 sizeof(GrPoint);
225 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
226 if (vertexLayout & kColor_VertexLayoutBit) {
227 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000229 if (vertexLayout & kCoverage_VertexLayoutBit) {
230 offset += sizeof(GrColor);
231 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000232 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000233 }
234 return -1;
235}
236
tomhudson@google.com93813632011-10-27 20:21:16 +0000237int GrDrawTarget::VertexSizeAndOffsetsByIdx(
238 GrVertexLayout vertexLayout,
239 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
240 int* colorOffset,
241 int* coverageOffset,
242 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000243 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000244
bsalomon@google.com5782d712011-01-21 21:03:59 +0000245 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000246 sizeof(GrGpuTextVertex) :
247 sizeof(GrPoint);
248 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000249
tomhudson@google.com93813632011-10-27 20:21:16 +0000250 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000251 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000252 if (NULL != texCoordOffsetsByIdx) {
253 texCoordOffsetsByIdx[t] = size;
254 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000255 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000256 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000257 if (NULL != texCoordOffsetsByIdx) {
258 texCoordOffsetsByIdx[t] = -1;
259 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000260 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000261 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000262 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000263 if (NULL != colorOffset) {
264 *colorOffset = size;
265 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000266 size += sizeof(GrColor);
267 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000268 if (NULL != colorOffset) {
269 *colorOffset = -1;
270 }
271 }
272 if (kCoverage_VertexLayoutBit & vertexLayout) {
273 if (NULL != coverageOffset) {
274 *coverageOffset = size;
275 }
276 size += sizeof(GrColor);
277 } else {
278 if (NULL != coverageOffset) {
279 *coverageOffset = -1;
280 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000281 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000282 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000283 if (NULL != edgeOffset) {
284 *edgeOffset = size;
285 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000286 size += 4 * sizeof(GrScalar);
287 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000288 if (NULL != edgeOffset) {
289 *edgeOffset = -1;
290 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000291 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000292 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000293}
294
tomhudson@google.com93813632011-10-27 20:21:16 +0000295int GrDrawTarget::VertexSizeAndOffsetsByStage(
296 GrVertexLayout vertexLayout,
297 int texCoordOffsetsByStage[GrDrawState::kNumStages],
298 int* colorOffset,
299 int* coverageOffset,
300 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000301 GrAssert(check_layout(vertexLayout));
302
tomhudson@google.com93813632011-10-27 20:21:16 +0000303 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000304 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000305 (NULL == texCoordOffsetsByStage) ?
306 NULL :
307 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000308 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000309 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000310 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000311 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000312 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000313 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
314 texCoordOffsetsByStage[s] =
315 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000316 }
317 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000318 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000319}
320
bsalomon@google.coma3108262011-10-10 14:08:47 +0000321////////////////////////////////////////////////////////////////////////////////
322
bsalomon@google.com5782d712011-01-21 21:03:59 +0000323bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000324 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000325 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000326 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000327 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328}
329
tomhudson@google.com93813632011-10-27 20:21:16 +0000330int GrDrawTarget::VertexTexCoordsForStage(int stage,
331 GrVertexLayout vertexLayout) {
332 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000333 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000334 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000335 if (bit) {
336 // figure out which set of texture coordates is used
337 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
338 // and start at bit 0.
339 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000340 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000341 }
342 return -1;
343}
344
bsalomon@google.coma3108262011-10-10 14:08:47 +0000345////////////////////////////////////////////////////////////////////////////////
346
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000347void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000348 // Ensure that our globals mask arrays are correct
349 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
350 GrVertexLayout stageMasks[GrDrawState::kNumStages];
351 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
352 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
353 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
354 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
355 GrAssert(stageMasks[s] == gStageMasks[s]);
356 }
357 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
358 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
359 }
360
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000361 // not necessarily exhaustive
362 static bool run;
363 if (!run) {
364 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000365 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000366
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000367 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000368 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000369 stageMask |= StageTexCoordVertexLayoutBit(s,t);
370 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000371 GrAssert(1 == GrDrawState::kMaxTexCoords ||
372 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000373 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000374 GrAssert(!check_layout(stageMask));
375 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000376 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000377 GrVertexLayout tcMask = 0;
378 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000379 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000380 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000381 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
382 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
383 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
384 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000385 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000386 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000387
bsalomon@google.com19628322011-02-03 21:30:17 +0000388 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000389 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000390 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000391 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000392 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
393 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000394 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000395 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000396 GrAssert(-1 == VertexEdgeOffset(tcMask));
397 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000398 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000399 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000400 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000401 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000402 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000403 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
404 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000405 #if GR_DEBUG
406 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
407 #endif
408 GrAssert(-1 == VertexColorOffset(withEdge));
409 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
410 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
411 #if GR_DEBUG
412 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
413 #endif
414 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
415 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
416 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000417 #if GR_DEBUG
418 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
419 #endif
420 GrAssert(-1 == VertexColorOffset(withCoverage));
421 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
422 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
423 #if GR_DEBUG
424 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
425 kColor_VertexLayoutBit;
426 #endif
427 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
428 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
429 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000430 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000431 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000432 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000433
tomhudson@google.com93813632011-10-27 20:21:16 +0000434 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000435 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000436 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000437 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000438 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000439 size = VertexSizeAndOffsetsByStage(tcMask,
440 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000441 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000442 GrAssert(2*sizeof(GrPoint) == size);
443 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000444 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000445 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000446 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000447 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
448 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
449 }
450 }
451 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000452}
453
454////////////////////////////////////////////////////////////////////////////////
455
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000456#define DEBUG_INVAL_BUFFER 0xdeadcafe
457#define DEBUG_INVAL_START_IDX -1
458
bsalomon@google.com92669012011-09-27 19:10:05 +0000459GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000460#if GR_DEBUG
461 VertexLayoutUnitTest();
462#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000463 fDrawState = &fDefaultDrawState;
464 // We assume that fDrawState always owns a ref to the object it points at.
465 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000466 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000467#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000468 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
469 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
470 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
471 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000472#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000473 geoSrc.fVertexSrc = kNone_GeometrySrcType;
474 geoSrc.fIndexSrc = kNone_GeometrySrcType;
475}
476
477GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000478 GrAssert(1 == fGeoSrcStateStack.count());
479 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
480 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
481 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000482 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000483}
484
485void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000486 int popCnt = fGeoSrcStateStack.count() - 1;
487 while (popCnt) {
488 this->popGeometrySource();
489 --popCnt;
490 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000491 this->resetVertexSource();
492 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000493}
494
495void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000496 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000497 fClip = clip;
498}
499
500const GrClip& GrDrawTarget::getClip() const {
501 return fClip;
502}
503
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000504void GrDrawTarget::setDrawState(GrDrawState* drawState) {
505 GrAssert(NULL != fDrawState);
506 if (NULL == drawState) {
507 drawState = &fDefaultDrawState;
508 }
509 if (fDrawState != drawState) {
510 fDrawState->unref();
511 drawState->ref();
512 fDrawState = drawState;
513 }
514}
515
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000516bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
517 int vertexCount,
518 void** vertices) {
519 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
520 bool acquired = false;
521 if (vertexCount > 0) {
522 GrAssert(NULL != vertices);
523 this->releasePreviousVertexSource();
524 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000525
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000526 acquired = this->onReserveVertexSpace(vertexLayout,
527 vertexCount,
528 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000529 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000530 if (acquired) {
531 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
532 geoSrc.fVertexCount = vertexCount;
533 geoSrc.fVertexLayout = vertexLayout;
534 } else if (NULL != vertices) {
535 *vertices = NULL;
536 }
537 return acquired;
538}
539
540bool GrDrawTarget::reserveIndexSpace(int indexCount,
541 void** indices) {
542 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
543 bool acquired = false;
544 if (indexCount > 0) {
545 GrAssert(NULL != indices);
546 this->releasePreviousIndexSource();
547 geoSrc.fIndexSrc = kNone_GeometrySrcType;
548
549 acquired = this->onReserveIndexSpace(indexCount, indices);
550 }
551 if (acquired) {
552 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
553 geoSrc.fIndexCount = indexCount;
554 } else if (NULL != indices) {
555 *indices = NULL;
556 }
557 return acquired;
558
reed@google.comac10a2d2010-12-22 21:39:39 +0000559}
560
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000561bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) {
562 return layout & gStageTexCoordMasks[stage];
563}
564
bsalomon@google.come3d70952012-03-13 12:40:53 +0000565bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
566 int vertexCount,
567 int indexCount,
568 void** vertices,
569 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000570 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000571 if (vertexCount) {
572 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
573 if (indexCount) {
574 this->resetIndexSource();
575 }
576 return false;
577 }
578 }
579 if (indexCount) {
580 if (!this->reserveIndexSpace(indexCount, indices)) {
581 if (vertexCount) {
582 this->resetVertexSource();
583 }
584 return false;
585 }
586 }
587 return true;
588}
589
reed@google.comac10a2d2010-12-22 21:39:39 +0000590bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
591 int32_t* vertexCount,
592 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000593 if (NULL != vertexCount) {
594 *vertexCount = -1;
595 }
596 if (NULL != indexCount) {
597 *indexCount = -1;
598 }
599 return false;
600}
601
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000602void GrDrawTarget::releasePreviousVertexSource() {
603 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
604 switch (geoSrc.fVertexSrc) {
605 case kNone_GeometrySrcType:
606 break;
607 case kArray_GeometrySrcType:
608 this->releaseVertexArray();
609 break;
610 case kReserved_GeometrySrcType:
611 this->releaseReservedVertexSpace();
612 break;
613 case kBuffer_GeometrySrcType:
614 geoSrc.fVertexBuffer->unref();
615#if GR_DEBUG
616 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
617#endif
618 break;
619 default:
620 GrCrash("Unknown Vertex Source Type.");
621 break;
622 }
623}
624
625void GrDrawTarget::releasePreviousIndexSource() {
626 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
627 switch (geoSrc.fIndexSrc) {
628 case kNone_GeometrySrcType: // these two don't require
629 break;
630 case kArray_GeometrySrcType:
631 this->releaseIndexArray();
632 break;
633 case kReserved_GeometrySrcType:
634 this->releaseReservedIndexSpace();
635 break;
636 case kBuffer_GeometrySrcType:
637 geoSrc.fIndexBuffer->unref();
638#if GR_DEBUG
639 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
640#endif
641 break;
642 default:
643 GrCrash("Unknown Index Source Type.");
644 break;
645 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000646}
647
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000648void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
649 const void* vertexArray,
650 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651 this->releasePreviousVertexSource();
652 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
653 geoSrc.fVertexSrc = kArray_GeometrySrcType;
654 geoSrc.fVertexLayout = vertexLayout;
655 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000656 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000657}
658
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000659void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
660 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000661 this->releasePreviousIndexSource();
662 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
663 geoSrc.fIndexSrc = kArray_GeometrySrcType;
664 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000665 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000666}
667
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000668void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
669 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000670 this->releasePreviousVertexSource();
671 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
672 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
673 geoSrc.fVertexBuffer = buffer;
674 buffer->ref();
675 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000676}
677
678void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000679 this->releasePreviousIndexSource();
680 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
681 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
682 geoSrc.fIndexBuffer = buffer;
683 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000684}
685
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000686void GrDrawTarget::resetVertexSource() {
687 this->releasePreviousVertexSource();
688 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
689 geoSrc.fVertexSrc = kNone_GeometrySrcType;
690}
691
692void GrDrawTarget::resetIndexSource() {
693 this->releasePreviousIndexSource();
694 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
695 geoSrc.fIndexSrc = kNone_GeometrySrcType;
696}
697
698void GrDrawTarget::pushGeometrySource() {
699 this->geometrySourceWillPush();
700 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
701 newState.fIndexSrc = kNone_GeometrySrcType;
702 newState.fVertexSrc = kNone_GeometrySrcType;
703#if GR_DEBUG
704 newState.fVertexCount = ~0;
705 newState.fVertexBuffer = (GrVertexBuffer*)~0;
706 newState.fIndexCount = ~0;
707 newState.fIndexBuffer = (GrIndexBuffer*)~0;
708#endif
709}
710
711void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712 // if popping last element then pops are unbalanced with pushes
713 GrAssert(fGeoSrcStateStack.count() > 1);
714
715 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
716 this->releasePreviousVertexSource();
717 this->releasePreviousIndexSource();
718 fGeoSrcStateStack.pop_back();
719}
720
721////////////////////////////////////////////////////////////////////////////////
722
bsalomon@google.come8262622011-11-07 02:30:51 +0000723bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
724 int startIndex, int vertexCount,
725 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000727 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000728 int maxVertex = startVertex + vertexCount;
729 int maxValidVertex;
730 switch (geoSrc.fVertexSrc) {
731 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000732 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000733 case kReserved_GeometrySrcType: // fallthrough
734 case kArray_GeometrySrcType:
735 maxValidVertex = geoSrc.fVertexCount;
736 break;
737 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000738 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000739 VertexSize(geoSrc.fVertexLayout);
740 break;
741 }
742 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000743 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000744 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000745 if (indexCount > 0) {
746 int maxIndex = startIndex + indexCount;
747 int maxValidIndex;
748 switch (geoSrc.fIndexSrc) {
749 case kNone_GeometrySrcType:
750 GrCrash("Attempting to draw indexed geom without index src.");
751 case kReserved_GeometrySrcType: // fallthrough
752 case kArray_GeometrySrcType:
753 maxValidIndex = geoSrc.fIndexCount;
754 break;
755 case kBuffer_GeometrySrcType:
756 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
757 break;
758 }
759 if (maxIndex > maxValidIndex) {
760 GrCrash("Index reads outside valid index range.");
761 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000762 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000763
764 GrAssert(NULL != this->getDrawState().getRenderTarget());
765 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
766 if (this->getDrawState().getTexture(i)) {
767 GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
768 this->getDrawState().getRenderTarget());
769 }
770 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000771#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000772 const GrDrawState& drawState = this->getDrawState();
773 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000774 return false;
775 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000776 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000777 if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
778 kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000779 return false;
780 }
781 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000782 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com74b98712011-11-11 19:46:16 +0000783 // We don't support using unpremultiplied textures with filters (other
784 // than nearest). Alpha-premulling is not distributive WRT to filtering.
785 // We'd have to filter each texel before filtering. We could do this for
786 // our custom filters but we would also have to disable bilerp and do
787 // a custom bilerp in the shader. Until Skia itself supports unpremul
788 // configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000789 if (this->isStageEnabled(s) &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000790 GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
791 GrSamplerState::kNearest_Filter !=
792 drawState.getSampler(s).getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000793 return false;
794 }
795 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000796 return true;
797}
798
799void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
800 int startIndex, int vertexCount,
801 int indexCount) {
802 if (indexCount > 0 &&
803 this->checkDraw(type, startVertex, startIndex,
804 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000805 this->onDrawIndexed(type, startVertex, startIndex,
806 vertexCount, indexCount);
807 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000808}
809
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000810void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
811 int startVertex,
812 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000813 if (vertexCount > 0 &&
814 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000815 this->onDrawNonIndexed(type, startVertex, vertexCount);
816 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000817}
818
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000819void GrDrawTarget::stencilPath(const GrPath& path, GrPathFill fill) {
820 // TODO: extract portions of checkDraw that are relevant to path stenciling.
821 GrAssert(fCaps.fPathStencilingSupport);
822 GrAssert(kHairLine_GrPathFill != fill);
823 GrAssert(!GrIsFillInverted(fill));
824 this->onStencilPath(path, fill);
825}
826
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000827////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000828
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000829// Some blend modes allow folding a partial coverage value into the color's
830// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000831bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000832 /**
833 * The fractional coverage is f
834 * The src and dst coeffs are Cs and Cd
835 * The dst and src colors are S and D
836 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
837 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
838 * obvious that that first term will always be ok. The second term can be
839 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
840 * for Cd we find that only 1, ISA, and ISC produce the correct depth
841 * coeffecient in terms of S' and D.
842 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000843 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000844 return kOne_GrBlendCoeff == dstCoeff ||
845 kISA_GrBlendCoeff == dstCoeff ||
846 kISC_GrBlendCoeff == dstCoeff;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000847}
848
bsalomon@google.come79c8152012-03-29 19:07:12 +0000849bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000850 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000851
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000852 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000853 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000854 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000855 return false;
856 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000857 // Check if color filter could introduce an alpha
858 // (TODO: Consider being more aggressive with regards to detecting 0xff
859 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000860 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000861 return false;
862 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000863 // Check if a color stage could create a partial alpha
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000864 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000865 if (this->isStageEnabled(s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000866 GrAssert(NULL != drawState.getTexture(s));
867 GrPixelConfig config = drawState.getTexture(s)->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000868 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000869 return false;
870 }
871 }
872 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000873 return true;
874}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000875
bsalomon@google.come79c8152012-03-29 19:07:12 +0000876namespace {
877GrVertexLayout default_blend_opts_vertex_layout() {
878 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000879 return layout;
880}
881}
882
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000883GrDrawTarget::BlendOptFlags
884GrDrawTarget::getBlendOpts(bool forceCoverage,
885 GrBlendCoeff* srcCoeff,
886 GrBlendCoeff* dstCoeff) const {
887
bsalomon@google.come79c8152012-03-29 19:07:12 +0000888 GrVertexLayout layout;
889 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
890 layout = default_blend_opts_vertex_layout();
891 } else {
892 layout = this->getVertexLayout();
893 }
894
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000895 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000896
897 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
898 if (NULL == srcCoeff) {
899 srcCoeff = &bogusSrcCoeff;
900 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000901 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000902
903 if (NULL == dstCoeff) {
904 dstCoeff = &bogusDstCoeff;
905 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000906 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000907
908 // We don't ever expect source coeffecients to reference the source
bsalomon@google.com47059542012-06-06 20:51:20 +0000909 GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
910 kISA_GrBlendCoeff != *srcCoeff &&
911 kSC_GrBlendCoeff != *srcCoeff &&
912 kISC_GrBlendCoeff != *srcCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000913 // same for dst
bsalomon@google.com47059542012-06-06 20:51:20 +0000914 GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
915 kIDA_GrBlendCoeff != *dstCoeff &&
916 kDC_GrBlendCoeff != *dstCoeff &&
917 kIDC_GrBlendCoeff != *dstCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000918
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000919 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000920 *srcCoeff = kZero_GrBlendCoeff;
921 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000922 }
923
bsalomon@google.come79c8152012-03-29 19:07:12 +0000924 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000925 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
926 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
927 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
928 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000929
930
931 // When coeffs are (0,1) there is no reason to draw at all, unless
932 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000933 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.com47059542012-06-06 20:51:20 +0000934 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000935 (!(layout & kCoverage_VertexLayoutBit) &&
936 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000937 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000938 return kDisableBlend_BlendOptFlag |
939 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000940 } else {
941 return kSkipDraw_BlendOptFlag;
942 }
943 }
944
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000945 // check for coverage due to constant coverage, per-vertex coverage,
946 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000947 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000948 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000949 (layout & kCoverage_VertexLayoutBit) ||
950 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000951 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000952 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000953 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000954 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000955 hasCoverage = true;
956 }
957 }
958
959 // if we don't have coverage we can check whether the dst
960 // has to read at all. If not, we'll disable blending.
961 if (!hasCoverage) {
962 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000963 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000964 // if there is no coverage and coeffs are (1,0) then we
965 // won't need to read the dst at all, it gets replaced by src
966 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000967 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000968 // if the op is "clear" then we don't need to emit a color
969 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000970 *srcCoeff = kOne_GrBlendCoeff;
971 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000972 return kDisableBlend_BlendOptFlag |
973 kEmitTransBlack_BlendOptFlag;
974 }
975 }
976 } else {
977 // check whether coverage can be safely rolled into alpha
978 // of if we can skip color computation and just emit coverage
979 if (this->canTweakAlphaForCoverage()) {
980 return kCoverageAsAlpha_BlendOptFlag;
981 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000982 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000983 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000984 // the source color is not included in the blend
985 // the dst coeff is effectively zero so blend works out to:
986 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000987 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000988 return kEmitCoverage_BlendOptFlag;
989 } else if (srcAIsOne) {
990 // the dst coeff is effectively zero so blend works out to:
991 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
992 // If Sa is 1 then we can replace Sa with c
993 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000994 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000995 return kCoverageAsAlpha_BlendOptFlag;
996 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000997 } else if (dstCoeffIsOne) {
998 // the dst coeff is effectively one so blend works out to:
999 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +00001000 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001001 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001002 }
1003 }
1004 return kNone_BlendOpt;
1005}
1006
1007bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001008 // there is a conflict between using smooth lines and our use of
1009 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1010 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001011 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001012 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001013 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001014 return false;
1015 }
1016 BlendOptFlags opts = this->getBlendOpts();
1017 return (kDisableBlend_BlendOptFlag & opts) &&
1018 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001019}
1020
1021bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001022 // we can correctly apply coverage if a) we have dual source blending
1023 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001024 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001025 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001026}
1027
bsalomon@google.com934c5702012-03-20 21:17:58 +00001028////////////////////////////////////////////////////////////////////////////////
1029
1030void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1031 int instanceCount,
1032 int verticesPerInstance,
1033 int indicesPerInstance) {
1034 if (!verticesPerInstance || !indicesPerInstance) {
1035 return;
1036 }
1037
1038 int instancesPerDraw = this->indexCountInCurrentSource() /
1039 indicesPerInstance;
1040 if (!instancesPerDraw) {
1041 return;
1042 }
1043
1044 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1045 int startVertex = 0;
1046 while (instanceCount) {
1047 this->drawIndexed(type,
1048 startVertex,
1049 0,
1050 verticesPerInstance * instancesPerDraw,
1051 indicesPerInstance * instancesPerDraw);
1052 startVertex += verticesPerInstance;
1053 instanceCount -= instancesPerDraw;
1054 }
1055}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001056
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001057////////////////////////////////////////////////////////////////////////////////
1058
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001059void GrDrawTarget::drawRect(const GrRect& rect,
1060 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001061 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001062 const GrRect* srcRects[],
1063 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001064 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001065
1066 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001067 if (!geo.succeeded()) {
1068 GrPrintf("Failed to get space for vertices!\n");
1069 return;
1070 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001071
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001072 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001073 srcMatrices, layout, geo.vertices());
1074
bsalomon@google.com47059542012-06-06 20:51:20 +00001075 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001076}
1077
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001078GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001079 const GrRect* srcRects[]) {
1080 GrVertexLayout layout = 0;
1081
tomhudson@google.com93813632011-10-27 20:21:16 +00001082 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001083 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001084 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001085 if (NULL != srcRects && NULL != srcRects[i]) {
1086 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1087 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001088 }
1089 }
1090 }
1091 return layout;
1092}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001093
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001094void GrDrawTarget::SetRectVertices(const GrRect& rect,
1095 const GrMatrix* matrix,
1096 const GrRect* srcRects[],
1097 const GrMatrix* srcMatrices[],
1098 GrVertexLayout layout,
1099 void* vertices) {
1100#if GR_DEBUG
1101 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001102 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001103 if (VertexTexCoordsForStage(i, layout) >= 0) {
1104 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1105 } else {
1106 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1107 }
1108 }
1109#endif
1110
tomhudson@google.com93813632011-10-27 20:21:16 +00001111 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001112 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1113 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001114
bsalomon@google.coma3108262011-10-10 14:08:47 +00001115 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001116 rect.fRight, rect.fBottom,
1117 vsize);
1118 if (NULL != matrix) {
1119 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1120 }
1121
tomhudson@google.com93813632011-10-27 20:21:16 +00001122 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001123 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001124 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001125 stageOffsets[i]);
1126 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001127 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001128 vsize);
1129 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1130 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1131 }
1132 }
1133 }
1134}
1135
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001136////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001137
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001138GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1139 fDrawTarget = NULL;
1140}
reed@google.comac10a2d2010-12-22 21:39:39 +00001141
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001142GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1143 ASRInit init) {
1144 fDrawTarget = NULL;
1145 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001146}
1147
1148GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001149 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001150 fDrawTarget->setDrawState(fSavedState);
1151 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001152 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001153}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001154
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001155void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1156 GrAssert(NULL == fDrawTarget);
1157 fDrawTarget = target;
1158 fSavedState = target->drawState();
1159 GrAssert(fSavedState);
1160 fSavedState->ref();
1161 if (kReset_ASRInit == init) {
1162 // calls the default cons
1163 fTempState.init();
1164 } else {
1165 GrAssert(kPreserve_ASRInit == init);
1166 // calls the copy cons
1167 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001168 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001169 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001170}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001171
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001172////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001173
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001174GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1175 GrDrawTarget* target,
1176 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001177 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001178 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001179
1180 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001181 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001182 fStageMask = stageMask;
1183 if (fStageMask) {
1184 GrMatrix invVM;
1185 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001186 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001187 if (fStageMask & (1 << s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001188 fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001189 }
1190 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001191 drawState->preConcatSamplerMatrices(fStageMask, invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001192 } else {
1193 // sad trombone sound
1194 fStageMask = 0;
1195 }
1196 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001197 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001198}
1199
1200GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001201 GrDrawState* drawState = fDrawTarget->drawState();
1202 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001203 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001204 if (fStageMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001205 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001206 }
1207 }
1208}
1209
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001210////////////////////////////////////////////////////////////////////////////////
1211
1212GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1213 GrDrawTarget* target,
1214 GrVertexLayout vertexLayout,
1215 int vertexCount,
1216 int indexCount) {
1217 fTarget = NULL;
1218 this->set(target, vertexLayout, vertexCount, indexCount);
1219}
1220
1221GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1222 fTarget = NULL;
1223}
1224
1225GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1226 this->reset();
1227}
1228
1229bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1230 GrVertexLayout vertexLayout,
1231 int vertexCount,
1232 int indexCount) {
1233 this->reset();
1234 fTarget = target;
1235 bool success = true;
1236 if (NULL != fTarget) {
1237 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001238 success = target->reserveVertexAndIndexSpace(vertexLayout,
1239 vertexCount,
1240 indexCount,
1241 &fVertices,
1242 &fIndices);
1243 if (!success) {
1244 fTarget = NULL;
1245 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001246 }
1247 }
1248 GrAssert(success == (NULL != fTarget));
1249 return success;
1250}
1251
1252void GrDrawTarget::AutoReleaseGeometry::reset() {
1253 if (NULL != fTarget) {
1254 if (NULL != fVertices) {
1255 fTarget->resetVertexSource();
1256 }
1257 if (NULL != fIndices) {
1258 fTarget->resetIndexSource();
1259 }
1260 fTarget = NULL;
1261 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001262 fVertices = NULL;
1263 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001264}
1265
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001266void GrDrawTarget::Caps::print() const {
1267 static const char* gNY[] = {"NO", "YES"};
1268 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001269 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001270 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1271 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1272 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001273 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001274 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001275 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1276 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1277 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001278 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1279 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1280}
1281
robertphillips@google.comec05eaa2012-04-27 18:59:52 +00001282