blob: bc373ba1f57b3ba93807eef5456a2824c0eaac15 [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 }
37 stageMasks[s] = stageTexCoordMasks[s] | GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
38 }
39 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
40 texCoordMasks[t] = 0;
41 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
42 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
43 }
44 }
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
bsalomon@google.com35ff3842011-12-15 16:58:19 +000047/**
48 * Run this function to generate the code that declares the global masks.
49 */
50void gen_globals() {
51 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
52 GrVertexLayout stageMasks[GrDrawState::kNumStages];
53 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
54 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
55
56 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
57 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
58 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
59 }
60 GrPrintf("};\n");
61 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
62 GrPrintf("const GrVertexLayout gStageMasks[] = {\n");
63 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
64 GrPrintf(" 0x%x,\n", stageMasks[s]);
65 }
66 GrPrintf("};\n");
67 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageMasks));\n\n");
68 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
69 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
70 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
71 }
72 GrPrintf("};\n");
73 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000074}
75
bsalomon@google.com35ff3842011-12-15 16:58:19 +000076/* These values were generated by the above function */
77const GrVertexLayout gStageTexCoordMasks[] = {
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[] = {
86 0x11111,
87 0x22222,
88 0x44444,
89 0x88888,
90};
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
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000102bool check_layout(GrVertexLayout layout) {
103 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +0000104 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000105 int stageBits = layout & gStageMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000106 if (stageBits && !GrIsPow2(stageBits)) {
107 return false;
108 }
109 }
110 return true;
111}
112
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000113int num_tex_coords(GrVertexLayout layout) {
114 int cnt = 0;
115 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000116 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000117 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000118 ++cnt;
119 }
120 }
121 return cnt;
122}
123
junov@google.com6acc9b32011-05-16 18:32:07 +0000124} //unnamed namespace
125
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000126size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
127 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000128
129 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000130 sizeof(GrGpuTextVertex) :
131 sizeof(GrPoint);
132
133 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000134 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000135 if (vertexLayout & kColor_VertexLayoutBit) {
136 size += sizeof(GrColor);
137 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000138 if (vertexLayout & kCoverage_VertexLayoutBit) {
139 size += sizeof(GrColor);
140 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000141 if (vertexLayout & kEdge_VertexLayoutBit) {
142 size += 4 * sizeof(GrScalar);
143 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000144 return size;
145}
146
bsalomon@google.coma3108262011-10-10 14:08:47 +0000147////////////////////////////////////////////////////////////////////////////////
148
149/**
150 * Functions for computing offsets of various components from the layout
151 * bitfield.
152 *
153 * Order of vertex components:
154 * Position
155 * Tex Coord 0
156 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000157 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000158 * Color
159 * Coverage
160 */
161
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000162int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
163 GrAssert(check_layout(vertexLayout));
164 if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 return 0;
166 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
168 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000169
170 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000171 sizeof(GrGpuTextVertex) :
172 sizeof(GrPoint);
173 int offset = vecSize; // position
174 // figure out how many tex coordinates are present and precede this one.
175 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000176 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000177 offset += vecSize;
178 }
179 }
180 return offset;
181 }
182
reed@google.comac10a2d2010-12-22 21:39:39 +0000183 return -1;
184}
185
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000186int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000187 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000188
reed@google.comac10a2d2010-12-22 21:39:39 +0000189 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000190 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000191 sizeof(GrGpuTextVertex) :
192 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000193 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
194 }
195 return -1;
196}
197
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000198int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000199 GrAssert(check_layout(vertexLayout));
200
201 if (vertexLayout & kCoverage_VertexLayoutBit) {
202 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
203 sizeof(GrGpuTextVertex) :
204 sizeof(GrPoint);
205
206 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
207 if (vertexLayout & kColor_VertexLayoutBit) {
208 offset += sizeof(GrColor);
209 }
210 return offset;
211 }
212 return -1;
213}
214
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000215int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000216 GrAssert(check_layout(vertexLayout));
217
218 // edge pts are after the pos, tex coords, and color
219 if (vertexLayout & kEdge_VertexLayoutBit) {
220 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
221 sizeof(GrGpuTextVertex) :
222 sizeof(GrPoint);
223 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
224 if (vertexLayout & kColor_VertexLayoutBit) {
225 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000226 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000227 if (vertexLayout & kCoverage_VertexLayoutBit) {
228 offset += sizeof(GrColor);
229 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000230 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000231 }
232 return -1;
233}
234
tomhudson@google.com93813632011-10-27 20:21:16 +0000235int GrDrawTarget::VertexSizeAndOffsetsByIdx(
236 GrVertexLayout vertexLayout,
237 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
238 int* colorOffset,
239 int* coverageOffset,
240 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000241 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000242
bsalomon@google.com5782d712011-01-21 21:03:59 +0000243 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000244 sizeof(GrGpuTextVertex) :
245 sizeof(GrPoint);
246 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000247
tomhudson@google.com93813632011-10-27 20:21:16 +0000248 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000249 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000250 if (NULL != texCoordOffsetsByIdx) {
251 texCoordOffsetsByIdx[t] = size;
252 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000253 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000254 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000255 if (NULL != texCoordOffsetsByIdx) {
256 texCoordOffsetsByIdx[t] = -1;
257 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000258 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000259 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000260 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000261 if (NULL != colorOffset) {
262 *colorOffset = size;
263 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 size += sizeof(GrColor);
265 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000266 if (NULL != colorOffset) {
267 *colorOffset = -1;
268 }
269 }
270 if (kCoverage_VertexLayoutBit & vertexLayout) {
271 if (NULL != coverageOffset) {
272 *coverageOffset = size;
273 }
274 size += sizeof(GrColor);
275 } else {
276 if (NULL != coverageOffset) {
277 *coverageOffset = -1;
278 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000279 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000280 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000281 if (NULL != edgeOffset) {
282 *edgeOffset = size;
283 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000284 size += 4 * sizeof(GrScalar);
285 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000286 if (NULL != edgeOffset) {
287 *edgeOffset = -1;
288 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000289 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000290 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000291}
292
tomhudson@google.com93813632011-10-27 20:21:16 +0000293int GrDrawTarget::VertexSizeAndOffsetsByStage(
294 GrVertexLayout vertexLayout,
295 int texCoordOffsetsByStage[GrDrawState::kNumStages],
296 int* colorOffset,
297 int* coverageOffset,
298 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000299 GrAssert(check_layout(vertexLayout));
300
tomhudson@google.com93813632011-10-27 20:21:16 +0000301 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000302 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000303 (NULL == texCoordOffsetsByStage) ?
304 NULL :
305 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000306 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000307 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000308 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000309 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000310 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000311 int tcIdx;
312 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
313 texCoordOffsetsByStage[s] = 0;
314 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
315 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
316 } else {
317 texCoordOffsetsByStage[s] = -1;
318 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000319 }
320 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000321 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000322}
323
bsalomon@google.coma3108262011-10-10 14:08:47 +0000324////////////////////////////////////////////////////////////////////////////////
325
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000326bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000327 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000329 return !!(gStageMasks[stage] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330}
331
bsalomon@google.com5782d712011-01-21 21:03:59 +0000332bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000333 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000334 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000335 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000336 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000337}
338
tomhudson@google.com93813632011-10-27 20:21:16 +0000339int GrDrawTarget::VertexTexCoordsForStage(int stage,
340 GrVertexLayout vertexLayout) {
341 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000342 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000343 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000344 if (bit) {
345 // figure out which set of texture coordates is used
346 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
347 // and start at bit 0.
348 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000349 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000350 }
351 return -1;
352}
353
bsalomon@google.coma3108262011-10-10 14:08:47 +0000354////////////////////////////////////////////////////////////////////////////////
355
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000356void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000357 // Ensure that our globals mask arrays are correct
358 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
359 GrVertexLayout stageMasks[GrDrawState::kNumStages];
360 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
361 gen_mask_arrays(stageTexCoordMasks, stageMasks, texCoordMasks);
362 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
363 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
364 GrAssert(stageMasks[s] == gStageMasks[s]);
365 }
366 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
367 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
368 }
369
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000370 // not necessarily exhaustive
371 static bool run;
372 if (!run) {
373 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000374 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000375
376 GrAssert(!VertexUsesStage(s, 0));
377 GrAssert(-1 == VertexStageCoordOffset(s, 0));
378 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000379 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000380 stageMask |= StageTexCoordVertexLayoutBit(s,t);
381 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000382 GrAssert(1 == GrDrawState::kMaxTexCoords ||
383 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000384 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000385 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000386 GrAssert(gStageMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000387 GrAssert(!check_layout(stageMask));
388 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000389 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000390 GrVertexLayout tcMask = 0;
391 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000392 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000393 tcMask |= StageTexCoordVertexLayoutBit(s,t);
394 GrAssert(VertexUsesStage(s, tcMask));
395 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
396 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
397 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
398 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000399 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000400 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
401 GrAssert(!VertexUsesStage(s2, tcMask));
402 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000403
bsalomon@google.com19628322011-02-03 21:30:17 +0000404 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000405 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000406 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000407 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
408 GrAssert(VertexUsesStage(s2, posAsTex));
409 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
410 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000411 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000412 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000413 GrAssert(-1 == VertexEdgeOffset(tcMask));
414 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000415 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000416 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000417 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000418 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000419 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000420 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
421 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000422 #if GR_DEBUG
423 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
424 #endif
425 GrAssert(-1 == VertexColorOffset(withEdge));
426 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
427 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
428 #if GR_DEBUG
429 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
430 #endif
431 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
432 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
433 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000434 #if GR_DEBUG
435 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
436 #endif
437 GrAssert(-1 == VertexColorOffset(withCoverage));
438 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
439 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
440 #if GR_DEBUG
441 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
442 kColor_VertexLayoutBit;
443 #endif
444 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
445 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
446 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000447 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000448 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000449 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000450
tomhudson@google.com93813632011-10-27 20:21:16 +0000451 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000452 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000453 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000454 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000455 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000456 size = VertexSizeAndOffsetsByStage(tcMask,
457 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000458 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000459 GrAssert(2*sizeof(GrPoint) == size);
460 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000461 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000462 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000463 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000464 GrAssert(VertexUsesStage(s, tcMask));
465 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
466 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
467 }
468 }
469 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000470}
471
472////////////////////////////////////////////////////////////////////////////////
473
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000474#define DEBUG_INVAL_BUFFER 0xdeadcafe
475#define DEBUG_INVAL_START_IDX -1
476
bsalomon@google.com92669012011-09-27 19:10:05 +0000477GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000478#if GR_DEBUG
479 VertexLayoutUnitTest();
480#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000481 fDrawState = &fDefaultDrawState;
482 // We assume that fDrawState always owns a ref to the object it points at.
483 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000484 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000485#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000486 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
487 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
488 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
489 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000490#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000491 geoSrc.fVertexSrc = kNone_GeometrySrcType;
492 geoSrc.fIndexSrc = kNone_GeometrySrcType;
493}
494
495GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000496 GrAssert(1 == fGeoSrcStateStack.count());
497 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
498 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
499 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000500 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000501}
502
503void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000504 int popCnt = fGeoSrcStateStack.count() - 1;
505 while (popCnt) {
506 this->popGeometrySource();
507 --popCnt;
508 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000509 this->resetVertexSource();
510 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000511}
512
513void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000514 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000515 fClip = clip;
516}
517
518const GrClip& GrDrawTarget::getClip() const {
519 return fClip;
520}
521
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000522void GrDrawTarget::setDrawState(GrDrawState* drawState) {
523 GrAssert(NULL != fDrawState);
524 if (NULL == drawState) {
525 drawState = &fDefaultDrawState;
526 }
527 if (fDrawState != drawState) {
528 fDrawState->unref();
529 drawState->ref();
530 fDrawState = drawState;
531 }
532}
533
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000534bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
535 int vertexCount,
536 void** vertices) {
537 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
538 bool acquired = false;
539 if (vertexCount > 0) {
540 GrAssert(NULL != vertices);
541 this->releasePreviousVertexSource();
542 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000543
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000544 acquired = this->onReserveVertexSpace(vertexLayout,
545 vertexCount,
546 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000547 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000548 if (acquired) {
549 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
550 geoSrc.fVertexCount = vertexCount;
551 geoSrc.fVertexLayout = vertexLayout;
552 } else if (NULL != vertices) {
553 *vertices = NULL;
554 }
555 return acquired;
556}
557
558bool GrDrawTarget::reserveIndexSpace(int indexCount,
559 void** indices) {
560 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
561 bool acquired = false;
562 if (indexCount > 0) {
563 GrAssert(NULL != indices);
564 this->releasePreviousIndexSource();
565 geoSrc.fIndexSrc = kNone_GeometrySrcType;
566
567 acquired = this->onReserveIndexSpace(indexCount, indices);
568 }
569 if (acquired) {
570 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
571 geoSrc.fIndexCount = indexCount;
572 } else if (NULL != indices) {
573 *indices = NULL;
574 }
575 return acquired;
576
reed@google.comac10a2d2010-12-22 21:39:39 +0000577}
578
bsalomon@google.come3d70952012-03-13 12:40:53 +0000579bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
580 int vertexCount,
581 int indexCount,
582 void** vertices,
583 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000584 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000585 if (vertexCount) {
586 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
587 if (indexCount) {
588 this->resetIndexSource();
589 }
590 return false;
591 }
592 }
593 if (indexCount) {
594 if (!this->reserveIndexSpace(indexCount, indices)) {
595 if (vertexCount) {
596 this->resetVertexSource();
597 }
598 return false;
599 }
600 }
601 return true;
602}
603
reed@google.comac10a2d2010-12-22 21:39:39 +0000604bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
605 int32_t* vertexCount,
606 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000607 if (NULL != vertexCount) {
608 *vertexCount = -1;
609 }
610 if (NULL != indexCount) {
611 *indexCount = -1;
612 }
613 return false;
614}
615
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000616void GrDrawTarget::releasePreviousVertexSource() {
617 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
618 switch (geoSrc.fVertexSrc) {
619 case kNone_GeometrySrcType:
620 break;
621 case kArray_GeometrySrcType:
622 this->releaseVertexArray();
623 break;
624 case kReserved_GeometrySrcType:
625 this->releaseReservedVertexSpace();
626 break;
627 case kBuffer_GeometrySrcType:
628 geoSrc.fVertexBuffer->unref();
629#if GR_DEBUG
630 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
631#endif
632 break;
633 default:
634 GrCrash("Unknown Vertex Source Type.");
635 break;
636 }
637}
638
639void GrDrawTarget::releasePreviousIndexSource() {
640 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
641 switch (geoSrc.fIndexSrc) {
642 case kNone_GeometrySrcType: // these two don't require
643 break;
644 case kArray_GeometrySrcType:
645 this->releaseIndexArray();
646 break;
647 case kReserved_GeometrySrcType:
648 this->releaseReservedIndexSpace();
649 break;
650 case kBuffer_GeometrySrcType:
651 geoSrc.fIndexBuffer->unref();
652#if GR_DEBUG
653 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
654#endif
655 break;
656 default:
657 GrCrash("Unknown Index Source Type.");
658 break;
659 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000660}
661
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000662void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
663 const void* vertexArray,
664 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000665 this->releasePreviousVertexSource();
666 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
667 geoSrc.fVertexSrc = kArray_GeometrySrcType;
668 geoSrc.fVertexLayout = vertexLayout;
669 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000670 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000671}
672
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000673void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
674 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000675 this->releasePreviousIndexSource();
676 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
677 geoSrc.fIndexSrc = kArray_GeometrySrcType;
678 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000679 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000680}
681
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000682void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
683 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000684 this->releasePreviousVertexSource();
685 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
686 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
687 geoSrc.fVertexBuffer = buffer;
688 buffer->ref();
689 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000690}
691
692void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000693 this->releasePreviousIndexSource();
694 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
695 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
696 geoSrc.fIndexBuffer = buffer;
697 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000698}
699
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000700void GrDrawTarget::resetVertexSource() {
701 this->releasePreviousVertexSource();
702 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
703 geoSrc.fVertexSrc = kNone_GeometrySrcType;
704}
705
706void GrDrawTarget::resetIndexSource() {
707 this->releasePreviousIndexSource();
708 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
709 geoSrc.fIndexSrc = kNone_GeometrySrcType;
710}
711
712void GrDrawTarget::pushGeometrySource() {
713 this->geometrySourceWillPush();
714 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
715 newState.fIndexSrc = kNone_GeometrySrcType;
716 newState.fVertexSrc = kNone_GeometrySrcType;
717#if GR_DEBUG
718 newState.fVertexCount = ~0;
719 newState.fVertexBuffer = (GrVertexBuffer*)~0;
720 newState.fIndexCount = ~0;
721 newState.fIndexBuffer = (GrIndexBuffer*)~0;
722#endif
723}
724
725void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726 // if popping last element then pops are unbalanced with pushes
727 GrAssert(fGeoSrcStateStack.count() > 1);
728
729 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
730 this->releasePreviousVertexSource();
731 this->releasePreviousIndexSource();
732 fGeoSrcStateStack.pop_back();
733}
734
735////////////////////////////////////////////////////////////////////////////////
736
bsalomon@google.come8262622011-11-07 02:30:51 +0000737bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
738 int startIndex, int vertexCount,
739 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000740#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000741 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000742 int maxVertex = startVertex + vertexCount;
743 int maxValidVertex;
744 switch (geoSrc.fVertexSrc) {
745 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000746 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000747 case kReserved_GeometrySrcType: // fallthrough
748 case kArray_GeometrySrcType:
749 maxValidVertex = geoSrc.fVertexCount;
750 break;
751 case kBuffer_GeometrySrcType:
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000752 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() /
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000753 VertexSize(geoSrc.fVertexLayout);
754 break;
755 }
756 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000757 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000758 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000759 if (indexCount > 0) {
760 int maxIndex = startIndex + indexCount;
761 int maxValidIndex;
762 switch (geoSrc.fIndexSrc) {
763 case kNone_GeometrySrcType:
764 GrCrash("Attempting to draw indexed geom without index src.");
765 case kReserved_GeometrySrcType: // fallthrough
766 case kArray_GeometrySrcType:
767 maxValidIndex = geoSrc.fIndexCount;
768 break;
769 case kBuffer_GeometrySrcType:
770 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
771 break;
772 }
773 if (maxIndex > maxValidIndex) {
774 GrCrash("Index reads outside valid index range.");
775 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000776 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000777
778 GrAssert(NULL != this->getDrawState().getRenderTarget());
779 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
780 if (this->getDrawState().getTexture(i)) {
781 GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
782 this->getDrawState().getRenderTarget());
783 }
784 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000785#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000786 const GrDrawState& drawState = this->getDrawState();
787 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000788 return false;
789 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000790 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000791 if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
792 kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000793 return false;
794 }
795 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000796 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com74b98712011-11-11 19:46:16 +0000797 // We don't support using unpremultiplied textures with filters (other
798 // than nearest). Alpha-premulling is not distributive WRT to filtering.
799 // We'd have to filter each texel before filtering. We could do this for
800 // our custom filters but we would also have to disable bilerp and do
801 // a custom bilerp in the shader. Until Skia itself supports unpremul
802 // configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000803 if (this->isStageEnabled(s) &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000804 GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
805 GrSamplerState::kNearest_Filter !=
806 drawState.getSampler(s).getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000807 return false;
808 }
809 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000810 return true;
811}
812
813void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
814 int startIndex, int vertexCount,
815 int indexCount) {
816 if (indexCount > 0 &&
817 this->checkDraw(type, startVertex, startIndex,
818 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000819 this->onDrawIndexed(type, startVertex, startIndex,
820 vertexCount, indexCount);
821 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000822}
823
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000824void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
825 int startVertex,
826 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000827 if (vertexCount > 0 &&
828 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000829 this->onDrawNonIndexed(type, startVertex, vertexCount);
830 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000831}
832
833////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000834
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000835// Some blend modes allow folding a partial coverage value into the color's
836// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000837bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000838 /**
839 * The fractional coverage is f
840 * The src and dst coeffs are Cs and Cd
841 * The dst and src colors are S and D
842 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
843 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
844 * obvious that that first term will always be ok. The second term can be
845 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
846 * for Cd we find that only 1, ISA, and ISC produce the correct depth
847 * coeffecient in terms of S' and D.
848 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000849 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000850 return kOne_GrBlendCoeff == dstCoeff ||
851 kISA_GrBlendCoeff == dstCoeff ||
852 kISC_GrBlendCoeff == dstCoeff;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000853}
854
bsalomon@google.come79c8152012-03-29 19:07:12 +0000855bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000856 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000857
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000858 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000859 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000860 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000861 return false;
862 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000863 // Check if color filter could introduce an alpha
864 // (TODO: Consider being more aggressive with regards to detecting 0xff
865 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000866 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000867 return false;
868 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000869 // Check if a color stage could create a partial alpha
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000870 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000871 if (StageWillBeUsed(s, layout, this->getDrawState())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000872 GrAssert(NULL != drawState.getTexture(s));
873 GrPixelConfig config = drawState.getTexture(s)->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000874 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000875 return false;
876 }
877 }
878 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000879 return true;
880}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000881
bsalomon@google.come79c8152012-03-29 19:07:12 +0000882namespace {
883GrVertexLayout default_blend_opts_vertex_layout() {
884 GrVertexLayout layout = 0;
885 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
886 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
887 }
888 return layout;
889}
890}
891
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000892GrDrawTarget::BlendOptFlags
893GrDrawTarget::getBlendOpts(bool forceCoverage,
894 GrBlendCoeff* srcCoeff,
895 GrBlendCoeff* dstCoeff) const {
896
bsalomon@google.come79c8152012-03-29 19:07:12 +0000897 GrVertexLayout layout;
898 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
899 layout = default_blend_opts_vertex_layout();
900 } else {
901 layout = this->getVertexLayout();
902 }
903
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000904 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000905
906 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
907 if (NULL == srcCoeff) {
908 srcCoeff = &bogusSrcCoeff;
909 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000910 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000911
912 if (NULL == dstCoeff) {
913 dstCoeff = &bogusDstCoeff;
914 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000915 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000916
917 // We don't ever expect source coeffecients to reference the source
bsalomon@google.com47059542012-06-06 20:51:20 +0000918 GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
919 kISA_GrBlendCoeff != *srcCoeff &&
920 kSC_GrBlendCoeff != *srcCoeff &&
921 kISC_GrBlendCoeff != *srcCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000922 // same for dst
bsalomon@google.com47059542012-06-06 20:51:20 +0000923 GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
924 kIDA_GrBlendCoeff != *dstCoeff &&
925 kDC_GrBlendCoeff != *dstCoeff &&
926 kIDC_GrBlendCoeff != *dstCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000927
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000929 *srcCoeff = kZero_GrBlendCoeff;
930 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000931 }
932
bsalomon@google.come79c8152012-03-29 19:07:12 +0000933 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000934 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
935 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
936 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
937 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000938
939
940 // When coeffs are (0,1) there is no reason to draw at all, unless
941 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000942 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.com47059542012-06-06 20:51:20 +0000943 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000944 (!(layout & kCoverage_VertexLayoutBit) &&
945 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000946 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000947 return kDisableBlend_BlendOptFlag |
948 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000949 } else {
950 return kSkipDraw_BlendOptFlag;
951 }
952 }
953
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000954 // check for coverage due to constant coverage, per-vertex coverage,
955 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000956 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000957 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000958 (layout & kCoverage_VertexLayoutBit) ||
959 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000960 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000961 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000962 ++s) {
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000963 if (StageWillBeUsed(s, layout, this->getDrawState())) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000964 hasCoverage = true;
965 }
966 }
967
968 // if we don't have coverage we can check whether the dst
969 // has to read at all. If not, we'll disable blending.
970 if (!hasCoverage) {
971 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000972 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000973 // if there is no coverage and coeffs are (1,0) then we
974 // won't need to read the dst at all, it gets replaced by src
975 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000976 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000977 // if the op is "clear" then we don't need to emit a color
978 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000979 *srcCoeff = kOne_GrBlendCoeff;
980 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000981 return kDisableBlend_BlendOptFlag |
982 kEmitTransBlack_BlendOptFlag;
983 }
984 }
985 } else {
986 // check whether coverage can be safely rolled into alpha
987 // of if we can skip color computation and just emit coverage
988 if (this->canTweakAlphaForCoverage()) {
989 return kCoverageAsAlpha_BlendOptFlag;
990 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000991 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000992 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000993 // the source color is not included in the blend
994 // the dst coeff is effectively zero so blend works out to:
995 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000996 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000997 return kEmitCoverage_BlendOptFlag;
998 } else if (srcAIsOne) {
999 // the dst coeff is effectively zero so blend works out to:
1000 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
1001 // If Sa is 1 then we can replace Sa with c
1002 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +00001003 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001004 return kCoverageAsAlpha_BlendOptFlag;
1005 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001006 } else if (dstCoeffIsOne) {
1007 // the dst coeff is effectively one so blend works out to:
1008 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +00001009 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +00001010 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001011 }
1012 }
1013 return kNone_BlendOpt;
1014}
1015
1016bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001017 // there is a conflict between using smooth lines and our use of
1018 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1019 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001020 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001021 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001022 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001023 return false;
1024 }
1025 BlendOptFlags opts = this->getBlendOpts();
1026 return (kDisableBlend_BlendOptFlag & opts) &&
1027 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001028}
1029
1030bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001031 // we can correctly apply coverage if a) we have dual source blending
1032 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001033 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001034 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001035}
1036
bsalomon@google.com934c5702012-03-20 21:17:58 +00001037////////////////////////////////////////////////////////////////////////////////
1038
1039void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1040 int instanceCount,
1041 int verticesPerInstance,
1042 int indicesPerInstance) {
1043 if (!verticesPerInstance || !indicesPerInstance) {
1044 return;
1045 }
1046
1047 int instancesPerDraw = this->indexCountInCurrentSource() /
1048 indicesPerInstance;
1049 if (!instancesPerDraw) {
1050 return;
1051 }
1052
1053 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1054 int startVertex = 0;
1055 while (instanceCount) {
1056 this->drawIndexed(type,
1057 startVertex,
1058 0,
1059 verticesPerInstance * instancesPerDraw,
1060 indicesPerInstance * instancesPerDraw);
1061 startVertex += verticesPerInstance;
1062 instanceCount -= instancesPerDraw;
1063 }
1064}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001065
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001066////////////////////////////////////////////////////////////////////////////////
1067
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001068void GrDrawTarget::drawRect(const GrRect& rect,
1069 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001070 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001071 const GrRect* srcRects[],
1072 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001073 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001074
1075 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001076 if (!geo.succeeded()) {
1077 GrPrintf("Failed to get space for vertices!\n");
1078 return;
1079 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001080
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001081 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001082 srcMatrices, layout, geo.vertices());
1083
bsalomon@google.com47059542012-06-06 20:51:20 +00001084 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001085}
1086
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001087GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001088 const GrRect* srcRects[]) {
1089 GrVertexLayout layout = 0;
1090
tomhudson@google.com93813632011-10-27 20:21:16 +00001091 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001092 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001093 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001094 if (NULL != srcRects && NULL != srcRects[i]) {
1095 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1096 ++numTC;
1097 } else {
1098 layout |= StagePosAsTexCoordVertexLayoutBit(i);
1099 }
1100 }
1101 }
1102 return layout;
1103}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001104
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001105void GrDrawTarget::SetRectVertices(const GrRect& rect,
1106 const GrMatrix* matrix,
1107 const GrRect* srcRects[],
1108 const GrMatrix* srcMatrices[],
1109 GrVertexLayout layout,
1110 void* vertices) {
1111#if GR_DEBUG
1112 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001113 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001114 if (VertexTexCoordsForStage(i, layout) >= 0) {
1115 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1116 } else {
1117 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1118 }
1119 }
1120#endif
1121
tomhudson@google.com93813632011-10-27 20:21:16 +00001122 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001123 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1124 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001125
bsalomon@google.coma3108262011-10-10 14:08:47 +00001126 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001127 rect.fRight, rect.fBottom,
1128 vsize);
1129 if (NULL != matrix) {
1130 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1131 }
1132
tomhudson@google.com93813632011-10-27 20:21:16 +00001133 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001134 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001135 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001136 stageOffsets[i]);
1137 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001138 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001139 vsize);
1140 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1141 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1142 }
1143 }
1144 }
1145}
1146
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001147////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001148
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001149GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1150 fDrawTarget = NULL;
1151}
reed@google.comac10a2d2010-12-22 21:39:39 +00001152
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001153GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1154 ASRInit init) {
1155 fDrawTarget = NULL;
1156 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001157}
1158
1159GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001160 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001161 fDrawTarget->setDrawState(fSavedState);
1162 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001163 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001164}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001165
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001166void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1167 GrAssert(NULL == fDrawTarget);
1168 fDrawTarget = target;
1169 fSavedState = target->drawState();
1170 GrAssert(fSavedState);
1171 fSavedState->ref();
1172 if (kReset_ASRInit == init) {
1173 // calls the default cons
1174 fTempState.init();
1175 } else {
1176 GrAssert(kPreserve_ASRInit == init);
1177 // calls the copy cons
1178 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001179 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001180 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001181}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001182
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001183////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001184
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001185GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1186 GrDrawTarget* target,
1187 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001188 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001189 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001190
1191 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001192 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001193 fStageMask = stageMask;
1194 if (fStageMask) {
1195 GrMatrix invVM;
1196 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001197 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001198 if (fStageMask & (1 << s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001199 fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001200 }
1201 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001202 drawState->preConcatSamplerMatrices(fStageMask, invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001203 } else {
1204 // sad trombone sound
1205 fStageMask = 0;
1206 }
1207 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001208 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001209}
1210
1211GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001212 GrDrawState* drawState = fDrawTarget->drawState();
1213 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001214 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001215 if (fStageMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001216 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001217 }
1218 }
1219}
1220
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001221////////////////////////////////////////////////////////////////////////////////
1222
1223GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1224 GrDrawTarget* target,
1225 GrVertexLayout vertexLayout,
1226 int vertexCount,
1227 int indexCount) {
1228 fTarget = NULL;
1229 this->set(target, vertexLayout, vertexCount, indexCount);
1230}
1231
1232GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1233 fTarget = NULL;
1234}
1235
1236GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1237 this->reset();
1238}
1239
1240bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1241 GrVertexLayout vertexLayout,
1242 int vertexCount,
1243 int indexCount) {
1244 this->reset();
1245 fTarget = target;
1246 bool success = true;
1247 if (NULL != fTarget) {
1248 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001249 success = target->reserveVertexAndIndexSpace(vertexLayout,
1250 vertexCount,
1251 indexCount,
1252 &fVertices,
1253 &fIndices);
1254 if (!success) {
1255 fTarget = NULL;
1256 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001257 }
1258 }
1259 GrAssert(success == (NULL != fTarget));
1260 return success;
1261}
1262
1263void GrDrawTarget::AutoReleaseGeometry::reset() {
1264 if (NULL != fTarget) {
1265 if (NULL != fVertices) {
1266 fTarget->resetVertexSource();
1267 }
1268 if (NULL != fIndices) {
1269 fTarget->resetIndexSource();
1270 }
1271 fTarget = NULL;
1272 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001273 fVertices = NULL;
1274 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001275}
1276
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001277void GrDrawTarget::Caps::print() const {
1278 static const char* gNY[] = {"NO", "YES"};
1279 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001280 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001281 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1282 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1283 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001284 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001285 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001286 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1287 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1288 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001289 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1290 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1291}
1292
robertphillips@google.comec05eaa2012-04-27 18:59:52 +00001293