blob: bd922fe9c24f53b54a1984422368e017ec1c19c7 [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,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000032 GrVertexLayout* texCoordMasks) {
33 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
34 stageTexCoordMasks[s] = 0;
35 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
36 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
37 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +000038 }
39 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
40 texCoordMasks[t] = 0;
41 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
42 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
43 }
44 }
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
bsalomon@google.com35ff3842011-12-15 16:58:19 +000047/**
48 * Run this function to generate the code that declares the global masks.
49 */
50void gen_globals() {
51 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000052 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +000053 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +000054
55 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
56 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
57 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
58 }
59 GrPrintf("};\n");
60 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
bsalomon@google.com35ff3842011-12-15 16:58:19 +000061 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
62 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
63 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
64 }
65 GrPrintf("};\n");
66 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000067}
68
bsalomon@google.com35ff3842011-12-15 16:58:19 +000069/* These values were generated by the above function */
70const GrVertexLayout gStageTexCoordMasks[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000071 0x1111,
72 0x2222,
73 0x4444,
74 0x8888,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000075};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000076GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000077
bsalomon@google.com35ff3842011-12-15 16:58:19 +000078const GrVertexLayout gTexCoordMasks[] = {
robertphillips@google.comec05eaa2012-04-27 18:59:52 +000079 0xf,
80 0xf0,
81 0xf00,
82 0xf000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000083};
84GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000085
86bool check_layout(GrVertexLayout layout) {
87 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000088 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +000089 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000090 if (stageBits && !GrIsPow2(stageBits)) {
91 return false;
92 }
93 }
94 return true;
95}
96
bsalomon@google.comaeb21602011-08-30 18:13:44 +000097int num_tex_coords(GrVertexLayout layout) {
98 int cnt = 0;
99 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000100 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000101 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000102 ++cnt;
103 }
104 }
105 return cnt;
106}
107
junov@google.com6acc9b32011-05-16 18:32:07 +0000108} //unnamed namespace
109
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000110size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
111 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000112
113 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000114 sizeof(GrGpuTextVertex) :
115 sizeof(GrPoint);
116
117 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000118 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000119 if (vertexLayout & kColor_VertexLayoutBit) {
120 size += sizeof(GrColor);
121 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000122 if (vertexLayout & kCoverage_VertexLayoutBit) {
123 size += sizeof(GrColor);
124 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000125 if (vertexLayout & kEdge_VertexLayoutBit) {
126 size += 4 * sizeof(GrScalar);
127 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000128 return size;
129}
130
bsalomon@google.coma3108262011-10-10 14:08:47 +0000131////////////////////////////////////////////////////////////////////////////////
132
133/**
134 * Functions for computing offsets of various components from the layout
135 * bitfield.
136 *
137 * Order of vertex components:
138 * Position
139 * Tex Coord 0
140 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000141 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000142 * Color
143 * Coverage
144 */
145
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000146int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
147 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000148
149 if (!StageUsesTexCoords(vertexLayout, stage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000150 return 0;
151 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000152 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
153 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000154
155 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000156 sizeof(GrGpuTextVertex) :
157 sizeof(GrPoint);
158 int offset = vecSize; // position
159 // figure out how many tex coordinates are present and precede this one.
160 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000161 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000162 offset += vecSize;
163 }
164 }
165 return offset;
166 }
167
reed@google.comac10a2d2010-12-22 21:39:39 +0000168 return -1;
169}
170
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000171int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000172 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000173
reed@google.comac10a2d2010-12-22 21:39:39 +0000174 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000175 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000176 sizeof(GrGpuTextVertex) :
177 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000178 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
179 }
180 return -1;
181}
182
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000183int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000184 GrAssert(check_layout(vertexLayout));
185
186 if (vertexLayout & kCoverage_VertexLayoutBit) {
187 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
188 sizeof(GrGpuTextVertex) :
189 sizeof(GrPoint);
190
191 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
192 if (vertexLayout & kColor_VertexLayoutBit) {
193 offset += sizeof(GrColor);
194 }
195 return offset;
196 }
197 return -1;
198}
199
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000200int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000201 GrAssert(check_layout(vertexLayout));
202
203 // edge pts are after the pos, tex coords, and color
204 if (vertexLayout & kEdge_VertexLayoutBit) {
205 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
206 sizeof(GrGpuTextVertex) :
207 sizeof(GrPoint);
208 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
209 if (vertexLayout & kColor_VertexLayoutBit) {
210 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000212 if (vertexLayout & kCoverage_VertexLayoutBit) {
213 offset += sizeof(GrColor);
214 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000215 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 }
217 return -1;
218}
219
tomhudson@google.com93813632011-10-27 20:21:16 +0000220int GrDrawTarget::VertexSizeAndOffsetsByIdx(
221 GrVertexLayout vertexLayout,
222 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
223 int* colorOffset,
224 int* coverageOffset,
225 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000226 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000227
bsalomon@google.com5782d712011-01-21 21:03:59 +0000228 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000229 sizeof(GrGpuTextVertex) :
230 sizeof(GrPoint);
231 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000232
tomhudson@google.com93813632011-10-27 20:21:16 +0000233 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000234 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000235 if (NULL != texCoordOffsetsByIdx) {
236 texCoordOffsetsByIdx[t] = size;
237 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000238 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000239 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000240 if (NULL != texCoordOffsetsByIdx) {
241 texCoordOffsetsByIdx[t] = -1;
242 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000243 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000245 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000246 if (NULL != colorOffset) {
247 *colorOffset = size;
248 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000249 size += sizeof(GrColor);
250 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000251 if (NULL != colorOffset) {
252 *colorOffset = -1;
253 }
254 }
255 if (kCoverage_VertexLayoutBit & vertexLayout) {
256 if (NULL != coverageOffset) {
257 *coverageOffset = size;
258 }
259 size += sizeof(GrColor);
260 } else {
261 if (NULL != coverageOffset) {
262 *coverageOffset = -1;
263 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000265 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000266 if (NULL != edgeOffset) {
267 *edgeOffset = size;
268 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000269 size += 4 * sizeof(GrScalar);
270 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000271 if (NULL != edgeOffset) {
272 *edgeOffset = -1;
273 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000274 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000275 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000276}
277
tomhudson@google.com93813632011-10-27 20:21:16 +0000278int GrDrawTarget::VertexSizeAndOffsetsByStage(
279 GrVertexLayout vertexLayout,
280 int texCoordOffsetsByStage[GrDrawState::kNumStages],
281 int* colorOffset,
282 int* coverageOffset,
283 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000284 GrAssert(check_layout(vertexLayout));
285
tomhudson@google.com93813632011-10-27 20:21:16 +0000286 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000287 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000288 (NULL == texCoordOffsetsByStage) ?
289 NULL :
290 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000291 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000292 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000293 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000294 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000295 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000296 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
297 texCoordOffsetsByStage[s] =
298 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000299 }
300 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000301 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000302}
303
bsalomon@google.coma3108262011-10-10 14:08:47 +0000304////////////////////////////////////////////////////////////////////////////////
305
bsalomon@google.com5782d712011-01-21 21:03:59 +0000306bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000307 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000308 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000309 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000310 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000311}
312
tomhudson@google.com93813632011-10-27 20:21:16 +0000313int GrDrawTarget::VertexTexCoordsForStage(int stage,
314 GrVertexLayout vertexLayout) {
315 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000316 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000317 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000318 if (bit) {
319 // figure out which set of texture coordates is used
320 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
321 // and start at bit 0.
322 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000323 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000324 }
325 return -1;
326}
327
bsalomon@google.coma3108262011-10-10 14:08:47 +0000328////////////////////////////////////////////////////////////////////////////////
329
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000331 // Ensure that our globals mask arrays are correct
332 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000333 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000334 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000335 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
336 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000337 }
338 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
339 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
340 }
341
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000342 // not necessarily exhaustive
343 static bool run;
344 if (!run) {
345 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000346 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000347
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000348 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000349 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000350 stageMask |= StageTexCoordVertexLayoutBit(s,t);
351 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000352 GrAssert(1 == GrDrawState::kMaxTexCoords ||
353 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000354 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000355 GrAssert(!check_layout(stageMask));
356 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000357 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000358 GrVertexLayout tcMask = 0;
359 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000360 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000361 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000362 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
363 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
364 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
365 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000366 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000367 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000368
bsalomon@google.com19628322011-02-03 21:30:17 +0000369 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000370 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000371 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000372 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000373 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
374 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000375 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000376 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000377 GrAssert(-1 == VertexEdgeOffset(tcMask));
378 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000379 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000380 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000381 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000382 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000383 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000384 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
385 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000386 #if GR_DEBUG
387 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
388 #endif
389 GrAssert(-1 == VertexColorOffset(withEdge));
390 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
391 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
392 #if GR_DEBUG
393 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
394 #endif
395 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
396 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
397 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000398 #if GR_DEBUG
399 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
400 #endif
401 GrAssert(-1 == VertexColorOffset(withCoverage));
402 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
403 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
404 #if GR_DEBUG
405 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
406 kColor_VertexLayoutBit;
407 #endif
408 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
409 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
410 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000411 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000412 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000413 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000414
tomhudson@google.com93813632011-10-27 20:21:16 +0000415 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000416 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000417 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000418 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000419 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000420 size = VertexSizeAndOffsetsByStage(tcMask,
421 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000422 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000423 GrAssert(2*sizeof(GrPoint) == size);
424 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000425 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000426 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000427 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000428 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
429 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
430 }
431 }
432 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000433}
434
435////////////////////////////////////////////////////////////////////////////////
436
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000437#define DEBUG_INVAL_BUFFER 0xdeadcafe
438#define DEBUG_INVAL_START_IDX -1
439
bsalomon@google.com92669012011-09-27 19:10:05 +0000440GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000441#if GR_DEBUG
442 VertexLayoutUnitTest();
443#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000444 fDrawState = &fDefaultDrawState;
445 // We assume that fDrawState always owns a ref to the object it points at.
446 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000447 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000448#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000449 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
450 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
451 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
452 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000453#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000454 geoSrc.fVertexSrc = kNone_GeometrySrcType;
455 geoSrc.fIndexSrc = kNone_GeometrySrcType;
456}
457
458GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000459 GrAssert(1 == fGeoSrcStateStack.count());
460 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
461 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
462 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000463 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000464}
465
466void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000467 int popCnt = fGeoSrcStateStack.count() - 1;
468 while (popCnt) {
469 this->popGeometrySource();
470 --popCnt;
471 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000472 this->resetVertexSource();
473 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000474}
475
476void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000477 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000478 fClip = clip;
479}
480
481const GrClip& GrDrawTarget::getClip() const {
482 return fClip;
483}
484
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000485void GrDrawTarget::setDrawState(GrDrawState* drawState) {
486 GrAssert(NULL != fDrawState);
487 if (NULL == drawState) {
488 drawState = &fDefaultDrawState;
489 }
490 if (fDrawState != drawState) {
491 fDrawState->unref();
492 drawState->ref();
493 fDrawState = drawState;
494 }
495}
496
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000497bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
498 int vertexCount,
499 void** vertices) {
500 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
501 bool acquired = false;
502 if (vertexCount > 0) {
503 GrAssert(NULL != vertices);
504 this->releasePreviousVertexSource();
505 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000506
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000507 acquired = this->onReserveVertexSpace(vertexLayout,
508 vertexCount,
509 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000510 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000511 if (acquired) {
512 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
513 geoSrc.fVertexCount = vertexCount;
514 geoSrc.fVertexLayout = vertexLayout;
515 } else if (NULL != vertices) {
516 *vertices = NULL;
517 }
518 return acquired;
519}
520
521bool GrDrawTarget::reserveIndexSpace(int indexCount,
522 void** indices) {
523 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
524 bool acquired = false;
525 if (indexCount > 0) {
526 GrAssert(NULL != indices);
527 this->releasePreviousIndexSource();
528 geoSrc.fIndexSrc = kNone_GeometrySrcType;
529
530 acquired = this->onReserveIndexSpace(indexCount, indices);
531 }
532 if (acquired) {
533 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
534 geoSrc.fIndexCount = indexCount;
535 } else if (NULL != indices) {
536 *indices = NULL;
537 }
538 return acquired;
539
reed@google.comac10a2d2010-12-22 21:39:39 +0000540}
541
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000542bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) {
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000543 return SkToBool(layout & gStageTexCoordMasks[stage]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000544}
545
bsalomon@google.come3d70952012-03-13 12:40:53 +0000546bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
547 int vertexCount,
548 int indexCount,
549 void** vertices,
550 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000551 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000552 if (vertexCount) {
553 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
554 if (indexCount) {
555 this->resetIndexSource();
556 }
557 return false;
558 }
559 }
560 if (indexCount) {
561 if (!this->reserveIndexSpace(indexCount, indices)) {
562 if (vertexCount) {
563 this->resetVertexSource();
564 }
565 return false;
566 }
567 }
568 return true;
569}
570
reed@google.comac10a2d2010-12-22 21:39:39 +0000571bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
572 int32_t* vertexCount,
573 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000574 if (NULL != vertexCount) {
575 *vertexCount = -1;
576 }
577 if (NULL != indexCount) {
578 *indexCount = -1;
579 }
580 return false;
581}
582
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000583void GrDrawTarget::releasePreviousVertexSource() {
584 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
585 switch (geoSrc.fVertexSrc) {
586 case kNone_GeometrySrcType:
587 break;
588 case kArray_GeometrySrcType:
589 this->releaseVertexArray();
590 break;
591 case kReserved_GeometrySrcType:
592 this->releaseReservedVertexSpace();
593 break;
594 case kBuffer_GeometrySrcType:
595 geoSrc.fVertexBuffer->unref();
596#if GR_DEBUG
597 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
598#endif
599 break;
600 default:
601 GrCrash("Unknown Vertex Source Type.");
602 break;
603 }
604}
605
606void GrDrawTarget::releasePreviousIndexSource() {
607 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
608 switch (geoSrc.fIndexSrc) {
609 case kNone_GeometrySrcType: // these two don't require
610 break;
611 case kArray_GeometrySrcType:
612 this->releaseIndexArray();
613 break;
614 case kReserved_GeometrySrcType:
615 this->releaseReservedIndexSpace();
616 break;
617 case kBuffer_GeometrySrcType:
618 geoSrc.fIndexBuffer->unref();
619#if GR_DEBUG
620 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
621#endif
622 break;
623 default:
624 GrCrash("Unknown Index Source Type.");
625 break;
626 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000627}
628
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000629void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
630 const void* vertexArray,
631 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000632 this->releasePreviousVertexSource();
633 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
634 geoSrc.fVertexSrc = kArray_GeometrySrcType;
635 geoSrc.fVertexLayout = vertexLayout;
636 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000637 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000638}
639
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000640void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
641 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000642 this->releasePreviousIndexSource();
643 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
644 geoSrc.fIndexSrc = kArray_GeometrySrcType;
645 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000646 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000647}
648
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000649void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
650 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000651 this->releasePreviousVertexSource();
652 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
653 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
654 geoSrc.fVertexBuffer = buffer;
655 buffer->ref();
656 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000657}
658
659void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000660 this->releasePreviousIndexSource();
661 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
662 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
663 geoSrc.fIndexBuffer = buffer;
664 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000665}
666
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000667void GrDrawTarget::resetVertexSource() {
668 this->releasePreviousVertexSource();
669 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
670 geoSrc.fVertexSrc = kNone_GeometrySrcType;
671}
672
673void GrDrawTarget::resetIndexSource() {
674 this->releasePreviousIndexSource();
675 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
676 geoSrc.fIndexSrc = kNone_GeometrySrcType;
677}
678
679void GrDrawTarget::pushGeometrySource() {
680 this->geometrySourceWillPush();
681 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
682 newState.fIndexSrc = kNone_GeometrySrcType;
683 newState.fVertexSrc = kNone_GeometrySrcType;
684#if GR_DEBUG
685 newState.fVertexCount = ~0;
686 newState.fVertexBuffer = (GrVertexBuffer*)~0;
687 newState.fIndexCount = ~0;
688 newState.fIndexBuffer = (GrIndexBuffer*)~0;
689#endif
690}
691
692void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000693 // if popping last element then pops are unbalanced with pushes
694 GrAssert(fGeoSrcStateStack.count() > 1);
695
696 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
697 this->releasePreviousVertexSource();
698 this->releasePreviousIndexSource();
699 fGeoSrcStateStack.pop_back();
700}
701
702////////////////////////////////////////////////////////////////////////////////
703
bsalomon@google.come8262622011-11-07 02:30:51 +0000704bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
705 int startIndex, int vertexCount,
706 int indexCount) const {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000707#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000708 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000709 int maxVertex = startVertex + vertexCount;
710 int maxValidVertex;
711 switch (geoSrc.fVertexSrc) {
712 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000713 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000714 case kReserved_GeometrySrcType: // fallthrough
715 case kArray_GeometrySrcType:
716 maxValidVertex = geoSrc.fVertexCount;
717 break;
718 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000719 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000720 break;
721 }
722 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000723 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000724 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000725 if (indexCount > 0) {
726 int maxIndex = startIndex + indexCount;
727 int maxValidIndex;
728 switch (geoSrc.fIndexSrc) {
729 case kNone_GeometrySrcType:
730 GrCrash("Attempting to draw indexed geom without index src.");
731 case kReserved_GeometrySrcType: // fallthrough
732 case kArray_GeometrySrcType:
733 maxValidIndex = geoSrc.fIndexCount;
734 break;
735 case kBuffer_GeometrySrcType:
736 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
737 break;
738 }
739 if (maxIndex > maxValidIndex) {
740 GrCrash("Index reads outside valid index range.");
741 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000742 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000743
744 GrAssert(NULL != this->getDrawState().getRenderTarget());
745 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
746 if (this->getDrawState().getTexture(i)) {
747 GrAssert(this->getDrawState().getTexture(i)->asRenderTarget() !=
748 this->getDrawState().getRenderTarget());
749 }
750 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000751#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000752 const GrDrawState& drawState = this->getDrawState();
753 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000754 return false;
755 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000756 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000757 if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
758 kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000759 return false;
760 }
761 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000762 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000763 // We don't support using unpremultiplied textures with filters (other than nearest). Alpha-
764 // premulling is not distributive WRT to filtering. We'd have to filter each texel before
765 // filtering. We could do this for our custom filters but we would also have to disable
766 // bilerp and do a custom bilerp in the shader. Until Skia itself supports unpremul configs
767 // there is no pressure to implement this.
768 if (drawState.getTexture(s) &&
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000769 GrPixelConfigIsUnpremultiplied(drawState.getTexture(s)->config()) &&
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000770 GrSamplerState::kNearest_Filter != drawState.getSampler(s).getFilter()) {
bsalomon@google.comc4364992011-11-07 15:54:49 +0000771 return false;
772 }
773 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000774 return true;
775}
776
777void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
778 int startIndex, int vertexCount,
779 int indexCount) {
780 if (indexCount > 0 &&
781 this->checkDraw(type, startVertex, startIndex,
782 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000783 this->onDrawIndexed(type, startVertex, startIndex,
784 vertexCount, indexCount);
785 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000786}
787
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000788void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
789 int startVertex,
790 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000791 if (vertexCount > 0 &&
792 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000793 this->onDrawNonIndexed(type, startVertex, vertexCount);
794 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000795}
796
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000797void GrDrawTarget::stencilPath(const GrPath* path, GrPathFill fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000798 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000799 GrAssert(NULL != path);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000800 GrAssert(fCaps.fPathStencilingSupport);
801 GrAssert(kHairLine_GrPathFill != fill);
802 GrAssert(!GrIsFillInverted(fill));
803 this->onStencilPath(path, fill);
804}
805
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000806////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000807
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000808// Some blend modes allow folding a partial coverage value into the color's
809// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000810bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000811 /**
812 * The fractional coverage is f
813 * The src and dst coeffs are Cs and Cd
814 * The dst and src colors are S and D
815 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
816 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
817 * obvious that that first term will always be ok. The second term can be
818 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
819 * for Cd we find that only 1, ISA, and ISC produce the correct depth
820 * coeffecient in terms of S' and D.
821 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000822 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000823 return kOne_GrBlendCoeff == dstCoeff ||
824 kISA_GrBlendCoeff == dstCoeff ||
825 kISC_GrBlendCoeff == dstCoeff;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000826}
827
bsalomon@google.come79c8152012-03-29 19:07:12 +0000828bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000829 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000830
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000831 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000832 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000833 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000834 return false;
835 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000836 // Check if color filter could introduce an alpha
837 // (TODO: Consider being more aggressive with regards to detecting 0xff
838 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000839 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000840 return false;
841 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000842 // Check if a color stage could create a partial alpha
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000843 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000844 if (this->isStageEnabled(s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 GrAssert(NULL != drawState.getTexture(s));
846 GrPixelConfig config = drawState.getTexture(s)->config();
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000847 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000848 return false;
849 }
850 }
851 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000852 return true;
853}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000854
bsalomon@google.come79c8152012-03-29 19:07:12 +0000855namespace {
856GrVertexLayout default_blend_opts_vertex_layout() {
857 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000858 return layout;
859}
860}
861
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000862GrDrawTarget::BlendOptFlags
863GrDrawTarget::getBlendOpts(bool forceCoverage,
864 GrBlendCoeff* srcCoeff,
865 GrBlendCoeff* dstCoeff) const {
866
bsalomon@google.come79c8152012-03-29 19:07:12 +0000867 GrVertexLayout layout;
868 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
869 layout = default_blend_opts_vertex_layout();
870 } else {
871 layout = this->getVertexLayout();
872 }
873
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000874 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000875
876 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
877 if (NULL == srcCoeff) {
878 srcCoeff = &bogusSrcCoeff;
879 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000880 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000881
882 if (NULL == dstCoeff) {
883 dstCoeff = &bogusDstCoeff;
884 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000885 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000886
887 // We don't ever expect source coeffecients to reference the source
bsalomon@google.com47059542012-06-06 20:51:20 +0000888 GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
889 kISA_GrBlendCoeff != *srcCoeff &&
890 kSC_GrBlendCoeff != *srcCoeff &&
891 kISC_GrBlendCoeff != *srcCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000892 // same for dst
bsalomon@google.com47059542012-06-06 20:51:20 +0000893 GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
894 kIDA_GrBlendCoeff != *dstCoeff &&
895 kDC_GrBlendCoeff != *dstCoeff &&
896 kIDC_GrBlendCoeff != *dstCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000897
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000898 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000899 *srcCoeff = kZero_GrBlendCoeff;
900 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000901 }
902
bsalomon@google.come79c8152012-03-29 19:07:12 +0000903 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000904 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
905 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
906 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
907 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000908
909
910 // When coeffs are (0,1) there is no reason to draw at all, unless
911 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000912 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.com47059542012-06-06 20:51:20 +0000913 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000914 (!(layout & kCoverage_VertexLayoutBit) &&
915 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000916 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000917 return kDisableBlend_BlendOptFlag |
918 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000919 } else {
920 return kSkipDraw_BlendOptFlag;
921 }
922 }
923
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000924 // check for coverage due to constant coverage, per-vertex coverage,
925 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000926 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000927 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000928 (layout & kCoverage_VertexLayoutBit) ||
929 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000930 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000931 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000932 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000933 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000934 hasCoverage = true;
935 }
936 }
937
938 // if we don't have coverage we can check whether the dst
939 // has to read at all. If not, we'll disable blending.
940 if (!hasCoverage) {
941 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000942 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000943 // if there is no coverage and coeffs are (1,0) then we
944 // won't need to read the dst at all, it gets replaced by src
945 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000946 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000947 // if the op is "clear" then we don't need to emit a color
948 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000949 *srcCoeff = kOne_GrBlendCoeff;
950 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000951 return kDisableBlend_BlendOptFlag |
952 kEmitTransBlack_BlendOptFlag;
953 }
954 }
955 } else {
956 // check whether coverage can be safely rolled into alpha
957 // of if we can skip color computation and just emit coverage
958 if (this->canTweakAlphaForCoverage()) {
959 return kCoverageAsAlpha_BlendOptFlag;
960 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000961 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000962 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000963 // the source color is not included in the blend
964 // the dst coeff is effectively zero so blend works out to:
965 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000966 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000967 return kEmitCoverage_BlendOptFlag;
968 } else if (srcAIsOne) {
969 // the dst coeff is effectively zero so blend works out to:
970 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
971 // If Sa is 1 then we can replace Sa with c
972 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000973 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000974 return kCoverageAsAlpha_BlendOptFlag;
975 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000976 } else if (dstCoeffIsOne) {
977 // the dst coeff is effectively one so blend works out to:
978 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000979 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000980 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000981 }
982 }
983 return kNone_BlendOpt;
984}
985
986bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000987 // there is a conflict between using smooth lines and our use of
988 // premultiplied alpha. Smooth lines tweak the incoming alpha value
989 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000990 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000991 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000992 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000993 return false;
994 }
995 BlendOptFlags opts = this->getBlendOpts();
996 return (kDisableBlend_BlendOptFlag & opts) &&
997 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000998}
999
1000bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001001 // we can correctly apply coverage if a) we have dual source blending
1002 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001003 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001004 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001005}
1006
bsalomon@google.com934c5702012-03-20 21:17:58 +00001007////////////////////////////////////////////////////////////////////////////////
1008
1009void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1010 int instanceCount,
1011 int verticesPerInstance,
1012 int indicesPerInstance) {
1013 if (!verticesPerInstance || !indicesPerInstance) {
1014 return;
1015 }
1016
1017 int instancesPerDraw = this->indexCountInCurrentSource() /
1018 indicesPerInstance;
1019 if (!instancesPerDraw) {
1020 return;
1021 }
1022
1023 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1024 int startVertex = 0;
1025 while (instanceCount) {
1026 this->drawIndexed(type,
1027 startVertex,
1028 0,
1029 verticesPerInstance * instancesPerDraw,
1030 indicesPerInstance * instancesPerDraw);
1031 startVertex += verticesPerInstance;
1032 instanceCount -= instancesPerDraw;
1033 }
1034}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001035
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001036////////////////////////////////////////////////////////////////////////////////
1037
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001038void GrDrawTarget::drawRect(const GrRect& rect,
1039 const GrMatrix* matrix,
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001040 StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001041 const GrRect* srcRects[],
1042 const GrMatrix* srcMatrices[]) {
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001043 GrVertexLayout layout = GetRectVertexLayout(stageMask, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001044
1045 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001046 if (!geo.succeeded()) {
1047 GrPrintf("Failed to get space for vertices!\n");
1048 return;
1049 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001050
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001051 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001052 srcMatrices, layout, geo.vertices());
1053
bsalomon@google.com47059542012-06-06 20:51:20 +00001054 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001055}
1056
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001057GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001058 const GrRect* srcRects[]) {
1059 GrVertexLayout layout = 0;
1060
tomhudson@google.com93813632011-10-27 20:21:16 +00001061 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001062 int numTC = 0;
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001063 if (stageMask & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001064 if (NULL != srcRects && NULL != srcRects[i]) {
1065 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1066 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001067 }
1068 }
1069 }
1070 return layout;
1071}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001072
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001073void GrDrawTarget::SetRectVertices(const GrRect& rect,
1074 const GrMatrix* matrix,
1075 const GrRect* srcRects[],
1076 const GrMatrix* srcMatrices[],
1077 GrVertexLayout layout,
1078 void* vertices) {
1079#if GR_DEBUG
1080 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001081 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001082 if (VertexTexCoordsForStage(i, layout) >= 0) {
1083 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1084 } else {
1085 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1086 }
1087 }
1088#endif
1089
tomhudson@google.com93813632011-10-27 20:21:16 +00001090 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001091 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1092 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001093
bsalomon@google.coma3108262011-10-10 14:08:47 +00001094 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001095 rect.fRight, rect.fBottom,
1096 vsize);
1097 if (NULL != matrix) {
1098 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1099 }
1100
tomhudson@google.com93813632011-10-27 20:21:16 +00001101 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001102 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001103 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001104 stageOffsets[i]);
1105 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001106 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001107 vsize);
1108 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1109 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1110 }
1111 }
1112 }
1113}
1114
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001115////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001116
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001117GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1118 fDrawTarget = NULL;
1119}
reed@google.comac10a2d2010-12-22 21:39:39 +00001120
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001121GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1122 ASRInit init) {
1123 fDrawTarget = NULL;
1124 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001125}
1126
1127GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001128 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001129 fDrawTarget->setDrawState(fSavedState);
1130 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001131 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001132}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001133
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001134void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1135 GrAssert(NULL == fDrawTarget);
1136 fDrawTarget = target;
1137 fSavedState = target->drawState();
1138 GrAssert(fSavedState);
1139 fSavedState->ref();
1140 if (kReset_ASRInit == init) {
1141 // calls the default cons
1142 fTempState.init();
1143 } else {
1144 GrAssert(kPreserve_ASRInit == init);
1145 // calls the copy cons
1146 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001147 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001148 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001149}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001150
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001151////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001152
bsalomon@google.com39ee0ff2011-12-06 15:32:52 +00001153GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
1154 GrDrawTarget* target,
1155 GrDrawState::StageMask stageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001156 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001157 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001158
1159 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001160 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001161 fStageMask = stageMask;
1162 if (fStageMask) {
1163 GrMatrix invVM;
1164 if (fViewMatrix.invert(&invVM)) {
tomhudson@google.com93813632011-10-27 20:21:16 +00001165 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001166 if (fStageMask & (1 << s)) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001167 fSamplerMatrices[s] = drawState->getSampler(s).getMatrix();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001168 }
1169 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001170 drawState->preConcatSamplerMatrices(fStageMask, invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001171 } else {
1172 // sad trombone sound
1173 fStageMask = 0;
1174 }
1175 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001176 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001177}
1178
1179GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001180 GrDrawState* drawState = fDrawTarget->drawState();
1181 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001182 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001183 if (fStageMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001184 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001185 }
1186 }
1187}
1188
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001189////////////////////////////////////////////////////////////////////////////////
1190
1191GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1192 GrDrawTarget* target,
1193 GrVertexLayout vertexLayout,
1194 int vertexCount,
1195 int indexCount) {
1196 fTarget = NULL;
1197 this->set(target, vertexLayout, vertexCount, indexCount);
1198}
1199
1200GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1201 fTarget = NULL;
1202}
1203
1204GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1205 this->reset();
1206}
1207
1208bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1209 GrVertexLayout vertexLayout,
1210 int vertexCount,
1211 int indexCount) {
1212 this->reset();
1213 fTarget = target;
1214 bool success = true;
1215 if (NULL != fTarget) {
1216 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001217 success = target->reserveVertexAndIndexSpace(vertexLayout,
1218 vertexCount,
1219 indexCount,
1220 &fVertices,
1221 &fIndices);
1222 if (!success) {
1223 fTarget = NULL;
1224 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001225 }
1226 }
1227 GrAssert(success == (NULL != fTarget));
1228 return success;
1229}
1230
1231void GrDrawTarget::AutoReleaseGeometry::reset() {
1232 if (NULL != fTarget) {
1233 if (NULL != fVertices) {
1234 fTarget->resetVertexSource();
1235 }
1236 if (NULL != fIndices) {
1237 fTarget->resetIndexSource();
1238 }
1239 fTarget = NULL;
1240 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001241 fVertices = NULL;
1242 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001243}
1244
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001245void GrDrawTarget::Caps::print() const {
1246 static const char* gNY[] = {"NO", "YES"};
1247 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001248 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001249 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1250 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1251 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001252 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001253 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001254 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1255 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1256 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001257 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1258 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1259}
1260
robertphillips@google.comec05eaa2012-04-27 18:59:52 +00001261