blob: 745e4c947a73d26daa9b51f0aa9c11b89cd0390e [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
reed@google.comfa35e3d2012-06-26 20:16:17 +000018SK_DEFINE_INST_COUNT(GrDrawTarget)
19
junov@google.com6acc9b32011-05-16 18:32:07 +000020namespace {
21
bsalomon@google.com35ff3842011-12-15 16:58:19 +000022/**
23 * This function generates some masks that we like to have known at compile
24 * time. When the number of stages or tex coords is bumped or the way bits
robertphillips@google.coma72eef32012-05-01 17:22:59 +000025 * are defined in GrDrawTarget.h changes this function should be rerun to
bsalomon@google.com35ff3842011-12-15 16:58:19 +000026 * generate the new masks. (We attempted to force the compiler to generate the
27 * masks using recursive templates but always wound up with static initializers
28 * under gcc, even if they were just a series of immediate->memory moves.)
29 *
30 */
31void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
32 GrVertexLayout* stageMasks,
33 GrVertexLayout* texCoordMasks) {
34 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
35 stageTexCoordMasks[s] = 0;
36 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
37 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
38 }
tomhudson@google.comb213ed82012-06-25 15:22:12 +000039 stageMasks[s] = stageTexCoordMasks[s];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000040 }
41 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
42 texCoordMasks[t] = 0;
43 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
44 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
45 }
46 }
reed@google.comac10a2d2010-12-22 21:39:39 +000047}
48
bsalomon@google.com35ff3842011-12-15 16:58:19 +000049/**
50 * Run this function to generate the code that declares the global masks.
51 */
52void gen_globals() {
53 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
54 GrVertexLayout stageMasks[GrDrawState::kNumStages];
55 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
56 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
57
58 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
59 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
60 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
61 }
62 GrPrintf("};\n");
63 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
64 GrPrintf("const GrVertexLayout gStageMasks[] = {\n");
65 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
66 GrPrintf(" 0x%x,\n", stageMasks[s]);
67 }
68 GrPrintf("};\n");
69 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\n\n");
70 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
71 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
72 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
73 }
74 GrPrintf("};\n");
75 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000076}
77
bsalomon@google.com35ff3842011-12-15 16:58:19 +000078/* These values were generated by the above function */
79const GrVertexLayout gStageTexCoordMasks[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000080 0x1111,
81 0x2222,
82 0x4444,
83 0x8888,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000084};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000085GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000086
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000087const GrVertexLayout gStageMasks[] = {
tomhudson@google.comb213ed82012-06-25 15:22:12 +000088 0x1111,
89 0x2222,
90 0x4444,
91 0x8888,
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000092};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000093GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000094
bsalomon@google.com35ff3842011-12-15 16:58:19 +000095const GrVertexLayout gTexCoordMasks[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000096 0xf,
97 0xf0,
98 0xf00,
99 0xf000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000100};
101GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000102
robertphillips@google.comec05eaa2012-04-27 18:59:52 +0000103
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000104
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000105bool check_layout(GrVertexLayout layout) {
106 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +0000107 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000108 int stageBits = layout & gStageMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000109 if (stageBits && !GrIsPow2(stageBits)) {
110 return false;
111 }
112 }
113 return true;
114}
115
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000116int num_tex_coords(GrVertexLayout layout) {
117 int cnt = 0;
118 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000119 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000120 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000121 ++cnt;
122 }
123 }
124 return cnt;
125}
126
junov@google.com6acc9b32011-05-16 18:32:07 +0000127} //unnamed namespace
128
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000129size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
130 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000131
132 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000133 sizeof(GrGpuTextVertex) :
134 sizeof(GrPoint);
135
136 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000137 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000138 if (vertexLayout & kColor_VertexLayoutBit) {
139 size += sizeof(GrColor);
140 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000141 if (vertexLayout & kCoverage_VertexLayoutBit) {
142 size += sizeof(GrColor);
143 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000144 if (vertexLayout & kEdge_VertexLayoutBit) {
145 size += 4 * sizeof(GrScalar);
146 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000147 return size;
148}
149
bsalomon@google.coma3108262011-10-10 14:08:47 +0000150////////////////////////////////////////////////////////////////////////////////
151
152/**
153 * Functions for computing offsets of various components from the layout
154 * bitfield.
155 *
156 * Order of vertex components:
157 * Position
158 * Tex Coord 0
159 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000160 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000161 * Color
162 * Coverage
163 */
164
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000165int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
166 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000167
168 if (!StageUsesTexCoords(vertexLayout, stage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000169 return 0;
170 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000171 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
172 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000173
174 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000175 sizeof(GrGpuTextVertex) :
176 sizeof(GrPoint);
177 int offset = vecSize; // position
178 // figure out how many tex coordinates are present and precede this one.
179 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000180 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000181 offset += vecSize;
182 }
183 }
184 return offset;
185 }
186
reed@google.comac10a2d2010-12-22 21:39:39 +0000187 return -1;
188}
189
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000190int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000191 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000192
reed@google.comac10a2d2010-12-22 21:39:39 +0000193 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000195 sizeof(GrGpuTextVertex) :
196 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000197 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
198 }
199 return -1;
200}
201
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000202int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000203 GrAssert(check_layout(vertexLayout));
204
205 if (vertexLayout & kCoverage_VertexLayoutBit) {
206 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
207 sizeof(GrGpuTextVertex) :
208 sizeof(GrPoint);
209
210 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
211 if (vertexLayout & kColor_VertexLayoutBit) {
212 offset += sizeof(GrColor);
213 }
214 return offset;
215 }
216 return -1;
217}
218
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000219int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000220 GrAssert(check_layout(vertexLayout));
221
222 // edge pts are after the pos, tex coords, and color
223 if (vertexLayout & kEdge_VertexLayoutBit) {
224 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
225 sizeof(GrGpuTextVertex) :
226 sizeof(GrPoint);
227 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
228 if (vertexLayout & kColor_VertexLayoutBit) {
229 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000230 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000231 if (vertexLayout & kCoverage_VertexLayoutBit) {
232 offset += sizeof(GrColor);
233 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000234 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000235 }
236 return -1;
237}
238
tomhudson@google.com93813632011-10-27 20:21:16 +0000239int GrDrawTarget::VertexSizeAndOffsetsByIdx(
240 GrVertexLayout vertexLayout,
241 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
242 int* colorOffset,
243 int* coverageOffset,
244 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000245 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000246
bsalomon@google.com5782d712011-01-21 21:03:59 +0000247 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248 sizeof(GrGpuTextVertex) :
249 sizeof(GrPoint);
250 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000251
tomhudson@google.com93813632011-10-27 20:21:16 +0000252 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000253 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000254 if (NULL != texCoordOffsetsByIdx) {
255 texCoordOffsetsByIdx[t] = size;
256 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000257 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000258 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000259 if (NULL != texCoordOffsetsByIdx) {
260 texCoordOffsetsByIdx[t] = -1;
261 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000263 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000265 if (NULL != colorOffset) {
266 *colorOffset = size;
267 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000268 size += sizeof(GrColor);
269 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000270 if (NULL != colorOffset) {
271 *colorOffset = -1;
272 }
273 }
274 if (kCoverage_VertexLayoutBit & vertexLayout) {
275 if (NULL != coverageOffset) {
276 *coverageOffset = size;
277 }
278 size += sizeof(GrColor);
279 } else {
280 if (NULL != coverageOffset) {
281 *coverageOffset = -1;
282 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000283 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000284 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000285 if (NULL != edgeOffset) {
286 *edgeOffset = size;
287 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000288 size += 4 * sizeof(GrScalar);
289 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000290 if (NULL != edgeOffset) {
291 *edgeOffset = -1;
292 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000293 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000294 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000295}
296
tomhudson@google.com93813632011-10-27 20:21:16 +0000297int GrDrawTarget::VertexSizeAndOffsetsByStage(
298 GrVertexLayout vertexLayout,
299 int texCoordOffsetsByStage[GrDrawState::kNumStages],
300 int* colorOffset,
301 int* coverageOffset,
302 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303 GrAssert(check_layout(vertexLayout));
304
tomhudson@google.com93813632011-10-27 20:21:16 +0000305 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000306 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000307 (NULL == texCoordOffsetsByStage) ?
308 NULL :
309 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000310 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000311 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000312 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000313 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000314 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000315 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
316 texCoordOffsetsByStage[s] =
317 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000318 }
319 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000320 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000321}
322
bsalomon@google.coma3108262011-10-10 14:08:47 +0000323////////////////////////////////////////////////////////////////////////////////
324
bsalomon@google.com5782d712011-01-21 21:03:59 +0000325bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000326 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000327 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000329 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330}
331
tomhudson@google.com93813632011-10-27 20:21:16 +0000332int GrDrawTarget::VertexTexCoordsForStage(int stage,
333 GrVertexLayout vertexLayout) {
334 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000335 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000336 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000337 if (bit) {
338 // figure out which set of texture coordates is used
339 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
340 // and start at bit 0.
341 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000342 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000343 }
344 return -1;
345}
346
bsalomon@google.coma3108262011-10-10 14:08:47 +0000347////////////////////////////////////////////////////////////////////////////////
348
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000349void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000350 // Ensure that our globals mask arrays are correct
351 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
352 GrVertexLayout stageMasks[GrDrawState::kNumStages];
353 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
354 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
355 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
356 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
357 GrAssert(stageMasks[s] == gStageMasks[s]);
358 }
359 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
360 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
361 }
362
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000363 // not necessarily exhaustive
364 static bool run;
365 if (!run) {
366 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000367 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000368
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000369 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000370 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000371 stageMask |= StageTexCoordVertexLayoutBit(s,t);
372 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000373 GrAssert(1 == GrDrawState::kMaxTexCoords ||
374 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000375 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000376 GrAssert(!check_layout(stageMask));
377 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000378 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000379 GrVertexLayout tcMask = 0;
380 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000381 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000382 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000383 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
384 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
385 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
386 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000387 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000388 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000389
bsalomon@google.com19628322011-02-03 21:30:17 +0000390 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000391 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000392 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000393 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000394 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
395 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000396 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000397 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000398 GrAssert(-1 == VertexEdgeOffset(tcMask));
399 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000400 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000401 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000402 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000403 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000404 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000405 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
406 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000407 #if GR_DEBUG
408 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
409 #endif
410 GrAssert(-1 == VertexColorOffset(withEdge));
411 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
412 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
413 #if GR_DEBUG
414 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
415 #endif
416 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
417 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
418 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000419 #if GR_DEBUG
420 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
421 #endif
422 GrAssert(-1 == VertexColorOffset(withCoverage));
423 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
424 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
425 #if GR_DEBUG
426 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
427 kColor_VertexLayoutBit;
428 #endif
429 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
430 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
431 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000432 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000433 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000434 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000435
tomhudson@google.com93813632011-10-27 20:21:16 +0000436 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000437 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000438 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000439 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000440 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000441 size = VertexSizeAndOffsetsByStage(tcMask,
442 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000443 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000444 GrAssert(2*sizeof(GrPoint) == size);
445 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000446 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000447 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000448 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000449 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
450 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
451 }
452 }
453 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000454}
455
456////////////////////////////////////////////////////////////////////////////////
457
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000458#define DEBUG_INVAL_BUFFER 0xdeadcafe
459#define DEBUG_INVAL_START_IDX -1
460
bsalomon@google.com92669012011-09-27 19:10:05 +0000461GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000462#if GR_DEBUG
463 VertexLayoutUnitTest();
464#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000465 fDrawState = &fDefaultDrawState;
466 // We assume that fDrawState always owns a ref to the object it points at.
467 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000468 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000469#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000470 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
471 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
472 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
473 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000474#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000475 geoSrc.fVertexSrc = kNone_GeometrySrcType;
476 geoSrc.fIndexSrc = kNone_GeometrySrcType;
477}
478
479GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000480 GrAssert(1 == fGeoSrcStateStack.count());
481 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
482 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
483 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000484 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000485}
486
487void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000488 int popCnt = fGeoSrcStateStack.count() - 1;
489 while (popCnt) {
490 this->popGeometrySource();
491 --popCnt;
492 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000493 this->resetVertexSource();
494 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000495}
496
497void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000498 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000499 fClip = clip;
500}
501
502const GrClip& GrDrawTarget::getClip() const {
503 return fClip;
504}
505
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000506void GrDrawTarget::setDrawState(GrDrawState* drawState) {
507 GrAssert(NULL != fDrawState);
508 if (NULL == drawState) {
509 drawState = &fDefaultDrawState;
510 }
511 if (fDrawState != drawState) {
512 fDrawState->unref();
513 drawState->ref();
514 fDrawState = drawState;
515 }
516}
517
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000518bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
519 int vertexCount,
520 void** vertices) {
521 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
522 bool acquired = false;
523 if (vertexCount > 0) {
524 GrAssert(NULL != vertices);
525 this->releasePreviousVertexSource();
526 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000527
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000528 acquired = this->onReserveVertexSpace(vertexLayout,
529 vertexCount,
530 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000531 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000532 if (acquired) {
533 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
534 geoSrc.fVertexCount = vertexCount;
535 geoSrc.fVertexLayout = vertexLayout;
536 } else if (NULL != vertices) {
537 *vertices = NULL;
538 }
539 return acquired;
540}
541
542bool GrDrawTarget::reserveIndexSpace(int indexCount,
543 void** indices) {
544 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
545 bool acquired = false;
546 if (indexCount > 0) {
547 GrAssert(NULL != indices);
548 this->releasePreviousIndexSource();
549 geoSrc.fIndexSrc = kNone_GeometrySrcType;
550
551 acquired = this->onReserveIndexSpace(indexCount, indices);
552 }
553 if (acquired) {
554 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
555 geoSrc.fIndexCount = indexCount;
556 } else if (NULL != indices) {
557 *indices = NULL;
558 }
559 return acquired;
560
reed@google.comac10a2d2010-12-22 21:39:39 +0000561}
562
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000563bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) {
564 return layout & gStageTexCoordMasks[stage];
565}
566
bsalomon@google.come3d70952012-03-13 12:40:53 +0000567bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
568 int vertexCount,
569 int indexCount,
570 void** vertices,
571 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000572 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000573 if (vertexCount) {
574 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
575 if (indexCount) {
576 this->resetIndexSource();
577 }
578 return false;
579 }
580 }
581 if (indexCount) {
582 if (!this->reserveIndexSpace(indexCount, indices)) {
583 if (vertexCount) {
584 this->resetVertexSource();
585 }
586 return false;
587 }
588 }
589 return true;
590}
591
reed@google.comac10a2d2010-12-22 21:39:39 +0000592bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
593 int32_t* vertexCount,
594 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000595 if (NULL != vertexCount) {
596 *vertexCount = -1;
597 }
598 if (NULL != indexCount) {
599 *indexCount = -1;
600 }
601 return false;
602}
603
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000604void GrDrawTarget::releasePreviousVertexSource() {
605 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
606 switch (geoSrc.fVertexSrc) {
607 case kNone_GeometrySrcType:
608 break;
609 case kArray_GeometrySrcType:
610 this->releaseVertexArray();
611 break;
612 case kReserved_GeometrySrcType:
613 this->releaseReservedVertexSpace();
614 break;
615 case kBuffer_GeometrySrcType:
616 geoSrc.fVertexBuffer->unref();
617#if GR_DEBUG
618 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
619#endif
620 break;
621 default:
622 GrCrash("Unknown Vertex Source Type.");
623 break;
624 }
625}
626
627void GrDrawTarget::releasePreviousIndexSource() {
628 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
629 switch (geoSrc.fIndexSrc) {
630 case kNone_GeometrySrcType: // these two don't require
631 break;
632 case kArray_GeometrySrcType:
633 this->releaseIndexArray();
634 break;
635 case kReserved_GeometrySrcType:
636 this->releaseReservedIndexSpace();
637 break;
638 case kBuffer_GeometrySrcType:
639 geoSrc.fIndexBuffer->unref();
640#if GR_DEBUG
641 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
642#endif
643 break;
644 default:
645 GrCrash("Unknown Index Source Type.");
646 break;
647 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000648}
649
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000650void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
651 const void* vertexArray,
652 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000653 this->releasePreviousVertexSource();
654 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
655 geoSrc.fVertexSrc = kArray_GeometrySrcType;
656 geoSrc.fVertexLayout = vertexLayout;
657 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000658 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000659}
660
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000661void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
662 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663 this->releasePreviousIndexSource();
664 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
665 geoSrc.fIndexSrc = kArray_GeometrySrcType;
666 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000667 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000668}
669
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000670void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
671 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000672 this->releasePreviousVertexSource();
673 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
674 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
675 geoSrc.fVertexBuffer = buffer;
676 buffer->ref();
677 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000678}
679
680void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000681 this->releasePreviousIndexSource();
682 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
683 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
684 geoSrc.fIndexBuffer = buffer;
685 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000686}
687
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000688void GrDrawTarget::resetVertexSource() {
689 this->releasePreviousVertexSource();
690 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
691 geoSrc.fVertexSrc = kNone_GeometrySrcType;
692}
693
694void GrDrawTarget::resetIndexSource() {
695 this->releasePreviousIndexSource();
696 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
697 geoSrc.fIndexSrc = kNone_GeometrySrcType;
698}
699
700void GrDrawTarget::pushGeometrySource() {
701 this->geometrySourceWillPush();
702 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
703 newState.fIndexSrc = kNone_GeometrySrcType;
704 newState.fVertexSrc = kNone_GeometrySrcType;
705#if GR_DEBUG
706 newState.fVertexCount = ~0;
707 newState.fVertexBuffer = (GrVertexBuffer*)~0;
708 newState.fIndexCount = ~0;
709 newState.fIndexBuffer = (GrIndexBuffer*)~0;
710#endif
711}
712
713void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000714 // if popping last element then pops are unbalanced with pushes
715 GrAssert(fGeoSrcStateStack.count() > 1);
716
717 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
718 this->releasePreviousVertexSource();
719 this->releasePreviousIndexSource();
720 fGeoSrcStateStack.pop_back();
721}
722
723////////////////////////////////////////////////////////////////////////////////
724
bsalomon@google.come8262622011-11-07 02:30:51 +0000725bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
726 int startIndex, int vertexCount,
727 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000728#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000729 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000730 int maxVertex = startVertex + vertexCount;
731 int maxValidVertex;
732 switch (geoSrc.fVertexSrc) {
733 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000734 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000735 case kReserved_GeometrySrcType: // fallthrough
736 case kArray_GeometrySrcType:
737 maxValidVertex = geoSrc.fVertexCount;
738 break;
739 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000740 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000741 VertexSize(geoSrc.fVertexLayout);
742 break;
743 }
744 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000745 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000746 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000747 if (indexCount > 0) {
748 int maxIndex = startIndex + indexCount;
749 int maxValidIndex;
750 switch (geoSrc.fIndexSrc) {
751 case kNone_GeometrySrcType:
752 GrCrash("Attempting to draw indexed geom without index src.");
753 case kReserved_GeometrySrcType: // fallthrough
754 case kArray_GeometrySrcType:
755 maxValidIndex = geoSrc.fIndexCount;
756 break;
757 case kBuffer_GeometrySrcType:
758 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
759 break;
760 }
761 if (maxIndex > maxValidIndex) {
762 GrCrash("Index reads outside valid index range.");
763 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000764 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000765
766 GrAssert(NULL != this->getDrawState().getRenderTarget());
767 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
768 if (this->getDrawState().getTexture(i)) {
769 GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
770 this->getDrawState().getRenderTarget());
771 }
772 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000773#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000774 const GrDrawState& drawState = this->getDrawState();
775 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000776 return false;
777 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000778 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000779 if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
780 kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000781 return false;
782 }
783 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000784 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com74b98712011-11-11 19:46:16 +0000785 // We don't support using unpremultiplied textures with filters (other
786 // than nearest). Alpha-premulling is not distributive WRT to filtering.
787 // We'd have to filter each texel before filtering. We could do this for
788 // our custom filters but we would also have to disable bilerp and do
789 // a custom bilerp in the shader. Until Skia itself supports unpremul
790 // configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000791 if (this->isStageEnabled(s) &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000792 GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
793 GrSamplerState::kNearest_Filter !=
794 drawState.getSampler(s).getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000795 return false;
796 }
797 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000798 return true;
799}
800
801void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
802 int startIndex, int vertexCount,
803 int indexCount) {
804 if (indexCount > 0 &&
805 this->checkDraw(type, startVertex, startIndex,
806 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000807 this->onDrawIndexed(type, startVertex, startIndex,
808 vertexCount, indexCount);
809 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000810}
811
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000812void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
813 int startVertex,
814 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000815 if (vertexCount > 0 &&
816 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000817 this->onDrawNonIndexed(type, startVertex, vertexCount);
818 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000819}
820
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000821void GrDrawTarget::stencilPath(const GrPath* path, GrPathFill fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000822 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000823 GrAssert(NULL != path);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000824 GrAssert(fCaps.fPathStencilingSupport);
825 GrAssert(kHairLine_GrPathFill != fill);
826 GrAssert(!GrIsFillInverted(fill));
827 this->onStencilPath(path, fill);
828}
829
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000830////////////////////////////////////////////////////////////////////////////////
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();
bsalomon@google.com47059542012-06-06 20:51:20 +0000847 return kOne_GrBlendCoeff == dstCoeff ||
848 kISA_GrBlendCoeff == dstCoeff ||
849 kISC_GrBlendCoeff == 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) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000868 if (this->isStageEnabled(s)) {
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;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000882 return layout;
883}
884}
885
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000886GrDrawTarget::BlendOptFlags
887GrDrawTarget::getBlendOpts(bool forceCoverage,
888 GrBlendCoeff* srcCoeff,
889 GrBlendCoeff* dstCoeff) const {
890
bsalomon@google.come79c8152012-03-29 19:07:12 +0000891 GrVertexLayout layout;
892 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
893 layout = default_blend_opts_vertex_layout();
894 } else {
895 layout = this->getVertexLayout();
896 }
897
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000898 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000899
900 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
901 if (NULL == srcCoeff) {
902 srcCoeff = &bogusSrcCoeff;
903 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000905
906 if (NULL == dstCoeff) {
907 dstCoeff = &bogusDstCoeff;
908 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000909 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000910
911 // We don't ever expect source coeffecients to reference the source
bsalomon@google.com47059542012-06-06 20:51:20 +0000912 GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
913 kISA_GrBlendCoeff != *srcCoeff &&
914 kSC_GrBlendCoeff != *srcCoeff &&
915 kISC_GrBlendCoeff != *srcCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000916 // same for dst
bsalomon@google.com47059542012-06-06 20:51:20 +0000917 GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
918 kIDA_GrBlendCoeff != *dstCoeff &&
919 kDC_GrBlendCoeff != *dstCoeff &&
920 kIDC_GrBlendCoeff != *dstCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000921
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000922 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000923 *srcCoeff = kZero_GrBlendCoeff;
924 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000925 }
926
bsalomon@google.come79c8152012-03-29 19:07:12 +0000927 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000928 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
929 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
930 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
931 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000932
933
934 // When coeffs are (0,1) there is no reason to draw at all, unless
935 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000936 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.com47059542012-06-06 20:51:20 +0000937 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000938 (!(layout & kCoverage_VertexLayoutBit) &&
939 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000940 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000941 return kDisableBlend_BlendOptFlag |
942 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000943 } else {
944 return kSkipDraw_BlendOptFlag;
945 }
946 }
947
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000948 // check for coverage due to constant coverage, per-vertex coverage,
949 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000950 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000951 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000952 (layout & kCoverage_VertexLayoutBit) ||
953 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000954 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000955 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000956 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000957 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000958 hasCoverage = true;
959 }
960 }
961
962 // if we don't have coverage we can check whether the dst
963 // has to read at all. If not, we'll disable blending.
964 if (!hasCoverage) {
965 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000966 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000967 // if there is no coverage and coeffs are (1,0) then we
968 // won't need to read the dst at all, it gets replaced by src
969 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000970 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000971 // if the op is "clear" then we don't need to emit a color
972 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000973 *srcCoeff = kOne_GrBlendCoeff;
974 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000975 return kDisableBlend_BlendOptFlag |
976 kEmitTransBlack_BlendOptFlag;
977 }
978 }
979 } else {
980 // check whether coverage can be safely rolled into alpha
981 // of if we can skip color computation and just emit coverage
982 if (this->canTweakAlphaForCoverage()) {
983 return kCoverageAsAlpha_BlendOptFlag;
984 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000985 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000986 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000987 // the source color is not included in the blend
988 // the dst coeff is effectively zero so blend works out to:
989 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000990 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000991 return kEmitCoverage_BlendOptFlag;
992 } else if (srcAIsOne) {
993 // the dst coeff is effectively zero so blend works out to:
994 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
995 // If Sa is 1 then we can replace Sa with c
996 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000997 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000998 return kCoverageAsAlpha_BlendOptFlag;
999 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001000 } else if (dstCoeffIsOne) {
1001 // the dst coeff is effectively one so blend works out to:
1002 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +00001003 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001004 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001005 }
1006 }
1007 return kNone_BlendOpt;
1008}
1009
1010bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001011 // there is a conflict between using smooth lines and our use of
1012 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1013 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001014 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001015 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001016 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001017 return false;
1018 }
1019 BlendOptFlags opts = this->getBlendOpts();
1020 return (kDisableBlend_BlendOptFlag & opts) &&
1021 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001022}
1023
1024bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001025 // we can correctly apply coverage if a) we have dual source blending
1026 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001027 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001028 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001029}
1030
bsalomon@google.com934c5702012-03-20 21:17:58 +00001031////////////////////////////////////////////////////////////////////////////////
1032
1033void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1034 int instanceCount,
1035 int verticesPerInstance,
1036 int indicesPerInstance) {
1037 if (!verticesPerInstance || !indicesPerInstance) {
1038 return;
1039 }
1040
1041 int instancesPerDraw = this->indexCountInCurrentSource() /
1042 indicesPerInstance;
1043 if (!instancesPerDraw) {
1044 return;
1045 }
1046
1047 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1048 int startVertex = 0;
1049 while (instanceCount) {
1050 this->drawIndexed(type,
1051 startVertex,
1052 0,
1053 verticesPerInstance * instancesPerDraw,
1054 indicesPerInstance * instancesPerDraw);
1055 startVertex += verticesPerInstance;
1056 instanceCount -= instancesPerDraw;
1057 }
1058}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001059
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001060////////////////////////////////////////////////////////////////////////////////
1061
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001062void GrDrawTarget::drawRect(const GrRect& rect,
1063 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001064 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001065 const GrRect* srcRects[],
1066 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001067 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001068
1069 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001070 if (!geo.succeeded()) {
1071 GrPrintf("Failed to get space for vertices!\n");
1072 return;
1073 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001074
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001075 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001076 srcMatrices, layout, geo.vertices());
1077
bsalomon@google.com47059542012-06-06 20:51:20 +00001078 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001079}
1080
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001081GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001082 const GrRect* srcRects[]) {
1083 GrVertexLayout layout = 0;
1084
tomhudson@google.com93813632011-10-27 20:21:16 +00001085 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001086 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001087 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001088 if (NULL != srcRects && NULL != srcRects[i]) {
1089 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1090 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001091 }
1092 }
1093 }
1094 return layout;
1095}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001096
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001097void GrDrawTarget::SetRectVertices(const GrRect& rect,
1098 const GrMatrix* matrix,
1099 const GrRect* srcRects[],
1100 const GrMatrix* srcMatrices[],
1101 GrVertexLayout layout,
1102 void* vertices) {
1103#if GR_DEBUG
1104 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001105 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001106 if (VertexTexCoordsForStage(i, layout) >= 0) {
1107 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1108 } else {
1109 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1110 }
1111 }
1112#endif
1113
tomhudson@google.com93813632011-10-27 20:21:16 +00001114 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001115 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1116 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001117
bsalomon@google.coma3108262011-10-10 14:08:47 +00001118 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001119 rect.fRight, rect.fBottom,
1120 vsize);
1121 if (NULL != matrix) {
1122 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1123 }
1124
tomhudson@google.com93813632011-10-27 20:21:16 +00001125 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001126 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001127 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001128 stageOffsets[i]);
1129 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001130 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001131 vsize);
1132 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1133 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1134 }
1135 }
1136 }
1137}
1138
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001139////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001140
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001141GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1142 fDrawTarget = NULL;
1143}
reed@google.comac10a2d2010-12-22 21:39:39 +00001144
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001145GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1146 ASRInit init) {
1147 fDrawTarget = NULL;
1148 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001149}
1150
1151GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001152 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001153 fDrawTarget->setDrawState(fSavedState);
1154 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001155 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001156}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001157
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001158void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1159 GrAssert(NULL == fDrawTarget);
1160 fDrawTarget = target;
1161 fSavedState = target->drawState();
1162 GrAssert(fSavedState);
1163 fSavedState->ref();
1164 if (kReset_ASRInit == init) {
1165 // calls the default cons
1166 fTempState.init();
1167 } else {
1168 GrAssert(kPreserve_ASRInit == init);
1169 // calls the copy cons
1170 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001171 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001172 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001173}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001174
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001175////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001176
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001177GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1178 GrDrawTarget* target,
1179 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001180 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001181 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001182
1183 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001184 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001185 fStageMask = stageMask;
1186 if (fStageMask) {
1187 GrMatrix invVM;
1188 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001189 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001190 if (fStageMask & (1 << s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001191 fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001192 }
1193 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001194 drawState->preConcatSamplerMatrices(fStageMask, invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001195 } else {
1196 // sad trombone sound
1197 fStageMask = 0;
1198 }
1199 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001200 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001201}
1202
1203GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001204 GrDrawState* drawState = fDrawTarget->drawState();
1205 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001206 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001207 if (fStageMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001208 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001209 }
1210 }
1211}
1212
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001213////////////////////////////////////////////////////////////////////////////////
1214
1215GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1216 GrDrawTarget* target,
1217 GrVertexLayout vertexLayout,
1218 int vertexCount,
1219 int indexCount) {
1220 fTarget = NULL;
1221 this->set(target, vertexLayout, vertexCount, indexCount);
1222}
1223
1224GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1225 fTarget = NULL;
1226}
1227
1228GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1229 this->reset();
1230}
1231
1232bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1233 GrVertexLayout vertexLayout,
1234 int vertexCount,
1235 int indexCount) {
1236 this->reset();
1237 fTarget = target;
1238 bool success = true;
1239 if (NULL != fTarget) {
1240 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001241 success = target->reserveVertexAndIndexSpace(vertexLayout,
1242 vertexCount,
1243 indexCount,
1244 &fVertices,
1245 &fIndices);
1246 if (!success) {
1247 fTarget = NULL;
1248 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001249 }
1250 }
1251 GrAssert(success == (NULL != fTarget));
1252 return success;
1253}
1254
1255void GrDrawTarget::AutoReleaseGeometry::reset() {
1256 if (NULL != fTarget) {
1257 if (NULL != fVertices) {
1258 fTarget->resetVertexSource();
1259 }
1260 if (NULL != fIndices) {
1261 fTarget->resetIndexSource();
1262 }
1263 fTarget = NULL;
1264 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001265 fVertices = NULL;
1266 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001267}
1268
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001269void GrDrawTarget::Caps::print() const {
1270 static const char* gNY[] = {"NO", "YES"};
1271 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001272 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001273 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1274 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1275 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001276 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001277 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001278 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1279 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1280 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001281 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1282 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1283}
1284
robertphillips@google.comec05eaa2012-04-27 18:59:52 +00001285