blob: 976448d699b739ffdac10f819ecb69981a78af28 [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 "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000014#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000015#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
sugoi@google.com5f74cf82012-12-17 21:16:45 +000017#include "SkStrokeRec.h"
sugoi@google.com12b4e272012-12-06 20:13:11 +000018
reed@google.comfa35e3d2012-06-26 20:16:17 +000019SK_DEFINE_INST_COUNT(GrDrawTarget)
20
junov@google.com6acc9b32011-05-16 18:32:07 +000021namespace {
22
bsalomon@google.com35ff3842011-12-15 16:58:19 +000023/**
24 * This function generates some masks that we like to have known at compile
25 * time. When the number of stages or tex coords is bumped or the way bits
robertphillips@google.coma72eef32012-05-01 17:22:59 +000026 * are defined in GrDrawTarget.h changes this function should be rerun to
bsalomon@google.com35ff3842011-12-15 16:58:19 +000027 * generate the new masks. (We attempted to force the compiler to generate the
28 * masks using recursive templates but always wound up with static initializers
29 * under gcc, even if they were just a series of immediate->memory moves.)
rmistry@google.comd6176b02012-08-23 18:14:13 +000030 *
bsalomon@google.com35ff3842011-12-15 16:58:19 +000031 */
32void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000033 GrVertexLayout* texCoordMasks) {
34 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
35 stageTexCoordMasks[s] = 0;
36 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
37 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
38 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +000039 }
40 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
41 texCoordMasks[t] = 0;
42 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
43 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
44 }
45 }
reed@google.comac10a2d2010-12-22 21:39:39 +000046}
47
rmistry@google.comd6176b02012-08-23 18:14:13 +000048/**
humper@google.com05af1af2013-01-07 16:47:43 +000049 * Uncomment and run the gen_globals function to generate
50 * the code that declares the global masks.
51 *
52 * #if 0'ed out to avoid unused function warning.
bsalomon@google.com35ff3842011-12-15 16:58:19 +000053 */
humper@google.com05af1af2013-01-07 16:47:43 +000054
55#if 0
bsalomon@google.com35ff3842011-12-15 16:58:19 +000056void gen_globals() {
57 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000058 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +000059 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
rmistry@google.comd6176b02012-08-23 18:14:13 +000060
bsalomon@google.com35ff3842011-12-15 16:58:19 +000061 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
62 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
63 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
64 }
65 GrPrintf("};\n");
66 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
bsalomon@google.com35ff3842011-12-15 16:58:19 +000067 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
68 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
69 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
70 }
71 GrPrintf("};\n");
72 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000073}
humper@google.com05af1af2013-01-07 16:47:43 +000074#endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000075
bsalomon@google.com35ff3842011-12-15 16:58:19 +000076/* These values were generated by the above function */
twiz@google.com58071162012-07-18 21:41:50 +000077
bsalomon@google.com35ff3842011-12-15 16:58:19 +000078const GrVertexLayout gStageTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000079 0x108421,
80 0x210842,
81 0x421084,
82 0x842108,
83 0x1084210,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000084};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000085GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000086
bsalomon@google.com35ff3842011-12-15 16:58:19 +000087const GrVertexLayout gTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000088 0x1f,
89 0x3e0,
90 0x7c00,
91 0xf8000,
92 0x1f00000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000093};
94GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000095
96bool check_layout(GrVertexLayout layout) {
97 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000098 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +000099 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000100 if (stageBits && !GrIsPow2(stageBits)) {
101 return false;
102 }
103 }
104 return true;
105}
106
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000107int num_tex_coords(GrVertexLayout layout) {
108 int cnt = 0;
109 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000110 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000111 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000112 ++cnt;
113 }
114 }
115 return cnt;
116}
117
junov@google.com6acc9b32011-05-16 18:32:07 +0000118} //unnamed namespace
119
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000120size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
121 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000122
123 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000124 sizeof(GrGpuTextVertex) :
125 sizeof(GrPoint);
126
127 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000128 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000129 if (vertexLayout & kColor_VertexLayoutBit) {
130 size += sizeof(GrColor);
131 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000132 if (vertexLayout & kCoverage_VertexLayoutBit) {
133 size += sizeof(GrColor);
134 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000135 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000136 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000137 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000138 return size;
139}
140
bsalomon@google.coma3108262011-10-10 14:08:47 +0000141////////////////////////////////////////////////////////////////////////////////
142
143/**
144 * Functions for computing offsets of various components from the layout
145 * bitfield.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000146 *
bsalomon@google.coma3108262011-10-10 14:08:47 +0000147 * Order of vertex components:
148 * Position
149 * Tex Coord 0
150 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000151 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000152 * Color
153 * Coverage
154 */
155
bsalomon@google.com08283af2012-10-26 13:01:20 +0000156int GrDrawTarget::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000157 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000158
bsalomon@google.com08283af2012-10-26 13:01:20 +0000159 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 return 0;
161 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000162 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000163 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000164
165 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000166 sizeof(GrGpuTextVertex) :
167 sizeof(GrPoint);
168 int offset = vecSize; // position
169 // figure out how many tex coordinates are present and precede this one.
170 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000171 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000172 offset += vecSize;
173 }
174 }
175 return offset;
176 }
177
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 return -1;
179}
180
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000181int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000182 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000183
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000185 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000186 sizeof(GrGpuTextVertex) :
187 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000188 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
189 }
190 return -1;
191}
192
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000193int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000194 GrAssert(check_layout(vertexLayout));
195
196 if (vertexLayout & kCoverage_VertexLayoutBit) {
197 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
198 sizeof(GrGpuTextVertex) :
199 sizeof(GrPoint);
200
201 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
202 if (vertexLayout & kColor_VertexLayoutBit) {
203 offset += sizeof(GrColor);
204 }
205 return offset;
206 }
207 return -1;
208}
209
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000210int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000211 GrAssert(check_layout(vertexLayout));
212
213 // edge pts are after the pos, tex coords, and color
214 if (vertexLayout & kEdge_VertexLayoutBit) {
215 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
216 sizeof(GrGpuTextVertex) :
217 sizeof(GrPoint);
218 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
219 if (vertexLayout & kColor_VertexLayoutBit) {
220 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000221 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000222 if (vertexLayout & kCoverage_VertexLayoutBit) {
223 offset += sizeof(GrColor);
224 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000225 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000226 }
227 return -1;
228}
229
tomhudson@google.com93813632011-10-27 20:21:16 +0000230int GrDrawTarget::VertexSizeAndOffsetsByIdx(
231 GrVertexLayout vertexLayout,
232 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
233 int* colorOffset,
234 int* coverageOffset,
235 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000236 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000237
bsalomon@google.com5782d712011-01-21 21:03:59 +0000238 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000239 sizeof(GrGpuTextVertex) :
240 sizeof(GrPoint);
241 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000242
tomhudson@google.com93813632011-10-27 20:21:16 +0000243 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000244 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000245 if (NULL != texCoordOffsetsByIdx) {
246 texCoordOffsetsByIdx[t] = size;
247 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000250 if (NULL != texCoordOffsetsByIdx) {
251 texCoordOffsetsByIdx[t] = -1;
252 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000253 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000254 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000255 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000256 if (NULL != colorOffset) {
257 *colorOffset = size;
258 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000259 size += sizeof(GrColor);
260 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000261 if (NULL != colorOffset) {
262 *colorOffset = -1;
263 }
264 }
265 if (kCoverage_VertexLayoutBit & vertexLayout) {
266 if (NULL != coverageOffset) {
267 *coverageOffset = size;
268 }
269 size += sizeof(GrColor);
270 } else {
271 if (NULL != coverageOffset) {
272 *coverageOffset = -1;
273 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000274 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000275 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000276 if (NULL != edgeOffset) {
277 *edgeOffset = size;
278 }
bsalomon@google.com81712882012-11-01 17:12:34 +0000279 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000280 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000281 if (NULL != edgeOffset) {
282 *edgeOffset = -1;
283 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000284 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000285 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000286}
287
tomhudson@google.com93813632011-10-27 20:21:16 +0000288int GrDrawTarget::VertexSizeAndOffsetsByStage(
289 GrVertexLayout vertexLayout,
290 int texCoordOffsetsByStage[GrDrawState::kNumStages],
291 int* colorOffset,
292 int* coverageOffset,
293 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000294 GrAssert(check_layout(vertexLayout));
295
tomhudson@google.com93813632011-10-27 20:21:16 +0000296 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000297 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000298 (NULL == texCoordOffsetsByStage) ?
299 NULL :
300 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000301 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000302 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000303 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000304 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000305 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000306 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
307 texCoordOffsetsByStage[s] =
308 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000309 }
310 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000311 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000312}
313
bsalomon@google.coma3108262011-10-10 14:08:47 +0000314////////////////////////////////////////////////////////////////////////////////
315
bsalomon@google.com5782d712011-01-21 21:03:59 +0000316bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000317 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000318 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000319 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000320 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000321}
322
bsalomon@google.com08283af2012-10-26 13:01:20 +0000323int GrDrawTarget::VertexTexCoordsForStage(int stageIdx,
tomhudson@google.com93813632011-10-27 20:21:16 +0000324 GrVertexLayout vertexLayout) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000325 GrAssert(stageIdx < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000326 GrAssert(check_layout(vertexLayout));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000327 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 if (bit) {
329 // figure out which set of texture coordates is used
330 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
331 // and start at bit 0.
332 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000333 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000334 }
335 return -1;
336}
337
bsalomon@google.coma3108262011-10-10 14:08:47 +0000338////////////////////////////////////////////////////////////////////////////////
339
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000340void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000341 // Ensure that our globals mask arrays are correct
342 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000343 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000344 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000345 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
346 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000347 }
348 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
349 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
350 }
351
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352 // not necessarily exhaustive
353 static bool run;
354 if (!run) {
355 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000356 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000357
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000358 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000359 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000360 stageMask |= StageTexCoordVertexLayoutBit(s,t);
361 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000362 GrAssert(1 == GrDrawState::kMaxTexCoords ||
363 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000364 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000365 GrAssert(!check_layout(stageMask));
366 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000367 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000368 GrVertexLayout tcMask = 0;
369 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000370 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000371 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000372 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
373 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
374 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
375 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000376 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000377 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000378
bsalomon@google.com19628322011-02-03 21:30:17 +0000379 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000380 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000381 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000382 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000383 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
384 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000385 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000386 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000387 GrAssert(-1 == VertexEdgeOffset(tcMask));
388 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000389 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000390 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000391 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000392 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000393 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000394 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
395 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000396 #if GR_DEBUG
397 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
398 #endif
399 GrAssert(-1 == VertexColorOffset(withEdge));
400 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
401 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
402 #if GR_DEBUG
403 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
404 #endif
405 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
406 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
407 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000408 #if GR_DEBUG
409 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
410 #endif
411 GrAssert(-1 == VertexColorOffset(withCoverage));
412 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
413 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
414 #if GR_DEBUG
415 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
416 kColor_VertexLayoutBit;
417 #endif
418 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
419 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
420 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000421 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000422 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000423 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000424
tomhudson@google.com93813632011-10-27 20:21:16 +0000425 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000426 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000427 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000428 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000429 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000430 size = VertexSizeAndOffsetsByStage(tcMask,
431 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000432 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000433 GrAssert(2*sizeof(GrPoint) == size);
434 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000435 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000436 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000437 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000438 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
439 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
440 }
441 }
442 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000443}
444
445////////////////////////////////////////////////////////////////////////////////
446
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000447#define DEBUG_INVAL_BUFFER 0xdeadcafe
448#define DEBUG_INVAL_START_IDX -1
449
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000450GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000451#if GR_DEBUG
452 VertexLayoutUnitTest();
453#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000454 fDrawState = &fDefaultDrawState;
455 // We assume that fDrawState always owns a ref to the object it points at.
456 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000457 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000458#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000459 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
460 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
461 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
462 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000463#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000464 geoSrc.fVertexSrc = kNone_GeometrySrcType;
465 geoSrc.fIndexSrc = kNone_GeometrySrcType;
466}
467
468GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000469 GrAssert(1 == fGeoSrcStateStack.count());
470 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
471 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
472 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000473 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000474}
475
476void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000477 int popCnt = fGeoSrcStateStack.count() - 1;
478 while (popCnt) {
479 this->popGeometrySource();
480 --popCnt;
481 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000482 this->resetVertexSource();
483 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000484}
485
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000486void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000487 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000488 fClip = clip;
489}
490
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000491const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000492 return fClip;
493}
494
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000495void GrDrawTarget::setDrawState(GrDrawState* drawState) {
496 GrAssert(NULL != fDrawState);
497 if (NULL == drawState) {
498 drawState = &fDefaultDrawState;
499 }
500 if (fDrawState != drawState) {
501 fDrawState->unref();
502 drawState->ref();
503 fDrawState = drawState;
504 }
505}
506
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000507bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
508 int vertexCount,
509 void** vertices) {
510 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
511 bool acquired = false;
512 if (vertexCount > 0) {
513 GrAssert(NULL != vertices);
514 this->releasePreviousVertexSource();
515 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000516
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000517 acquired = this->onReserveVertexSpace(vertexLayout,
518 vertexCount,
519 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000520 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000521 if (acquired) {
522 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
523 geoSrc.fVertexCount = vertexCount;
524 geoSrc.fVertexLayout = vertexLayout;
525 } else if (NULL != vertices) {
526 *vertices = NULL;
527 }
528 return acquired;
529}
530
531bool GrDrawTarget::reserveIndexSpace(int indexCount,
532 void** indices) {
533 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
534 bool acquired = false;
535 if (indexCount > 0) {
536 GrAssert(NULL != indices);
537 this->releasePreviousIndexSource();
538 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000539
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000540 acquired = this->onReserveIndexSpace(indexCount, indices);
541 }
542 if (acquired) {
543 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
544 geoSrc.fIndexCount = indexCount;
545 } else if (NULL != indices) {
546 *indices = NULL;
547 }
548 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000549
reed@google.comac10a2d2010-12-22 21:39:39 +0000550}
551
bsalomon@google.com08283af2012-10-26 13:01:20 +0000552bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
553 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000554}
555
bsalomon@google.come3d70952012-03-13 12:40:53 +0000556bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
557 int vertexCount,
558 int indexCount,
559 void** vertices,
560 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000561 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000562 if (vertexCount) {
563 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
564 if (indexCount) {
565 this->resetIndexSource();
566 }
567 return false;
568 }
569 }
570 if (indexCount) {
571 if (!this->reserveIndexSpace(indexCount, indices)) {
572 if (vertexCount) {
573 this->resetVertexSource();
574 }
575 return false;
576 }
577 }
578 return true;
579}
580
reed@google.comac10a2d2010-12-22 21:39:39 +0000581bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
582 int32_t* vertexCount,
583 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000584 if (NULL != vertexCount) {
585 *vertexCount = -1;
586 }
587 if (NULL != indexCount) {
588 *indexCount = -1;
589 }
590 return false;
591}
592
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000593void GrDrawTarget::releasePreviousVertexSource() {
594 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
595 switch (geoSrc.fVertexSrc) {
596 case kNone_GeometrySrcType:
597 break;
598 case kArray_GeometrySrcType:
599 this->releaseVertexArray();
600 break;
601 case kReserved_GeometrySrcType:
602 this->releaseReservedVertexSpace();
603 break;
604 case kBuffer_GeometrySrcType:
605 geoSrc.fVertexBuffer->unref();
606#if GR_DEBUG
607 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
608#endif
609 break;
610 default:
611 GrCrash("Unknown Vertex Source Type.");
612 break;
613 }
614}
615
616void GrDrawTarget::releasePreviousIndexSource() {
617 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
618 switch (geoSrc.fIndexSrc) {
619 case kNone_GeometrySrcType: // these two don't require
620 break;
621 case kArray_GeometrySrcType:
622 this->releaseIndexArray();
623 break;
624 case kReserved_GeometrySrcType:
625 this->releaseReservedIndexSpace();
626 break;
627 case kBuffer_GeometrySrcType:
628 geoSrc.fIndexBuffer->unref();
629#if GR_DEBUG
630 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
631#endif
632 break;
633 default:
634 GrCrash("Unknown Index Source Type.");
635 break;
636 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000637}
638
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000639void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
640 const void* vertexArray,
641 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000642 this->releasePreviousVertexSource();
643 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
644 geoSrc.fVertexSrc = kArray_GeometrySrcType;
645 geoSrc.fVertexLayout = vertexLayout;
646 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000647 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000648}
649
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000650void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
651 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000652 this->releasePreviousIndexSource();
653 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
654 geoSrc.fIndexSrc = kArray_GeometrySrcType;
655 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000656 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000657}
658
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000659void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
660 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000661 this->releasePreviousVertexSource();
662 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
663 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
664 geoSrc.fVertexBuffer = buffer;
665 buffer->ref();
666 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000667}
668
669void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000670 this->releasePreviousIndexSource();
671 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
672 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
673 geoSrc.fIndexBuffer = buffer;
674 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000675}
676
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000677void GrDrawTarget::resetVertexSource() {
678 this->releasePreviousVertexSource();
679 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
680 geoSrc.fVertexSrc = kNone_GeometrySrcType;
681}
682
683void GrDrawTarget::resetIndexSource() {
684 this->releasePreviousIndexSource();
685 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
686 geoSrc.fIndexSrc = kNone_GeometrySrcType;
687}
688
689void GrDrawTarget::pushGeometrySource() {
690 this->geometrySourceWillPush();
691 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
692 newState.fIndexSrc = kNone_GeometrySrcType;
693 newState.fVertexSrc = kNone_GeometrySrcType;
694#if GR_DEBUG
695 newState.fVertexCount = ~0;
696 newState.fVertexBuffer = (GrVertexBuffer*)~0;
697 newState.fIndexCount = ~0;
698 newState.fIndexBuffer = (GrIndexBuffer*)~0;
699#endif
700}
701
702void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000703 // if popping last element then pops are unbalanced with pushes
704 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000705
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000706 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
707 this->releasePreviousVertexSource();
708 this->releasePreviousIndexSource();
709 fGeoSrcStateStack.pop_back();
710}
711
712////////////////////////////////////////////////////////////////////////////////
713
bsalomon@google.come8262622011-11-07 02:30:51 +0000714bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
715 int startIndex, int vertexCount,
716 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000717 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000718#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000719 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000720 int maxVertex = startVertex + vertexCount;
721 int maxValidVertex;
722 switch (geoSrc.fVertexSrc) {
723 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000724 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000725 case kReserved_GeometrySrcType: // fallthrough
726 case kArray_GeometrySrcType:
727 maxValidVertex = geoSrc.fVertexCount;
728 break;
729 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000730 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000731 break;
732 }
733 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000734 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000735 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000736 if (indexCount > 0) {
737 int maxIndex = startIndex + indexCount;
738 int maxValidIndex;
739 switch (geoSrc.fIndexSrc) {
740 case kNone_GeometrySrcType:
741 GrCrash("Attempting to draw indexed geom without index src.");
742 case kReserved_GeometrySrcType: // fallthrough
743 case kArray_GeometrySrcType:
744 maxValidIndex = geoSrc.fIndexCount;
745 break;
746 case kBuffer_GeometrySrcType:
747 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
748 break;
749 }
750 if (maxIndex > maxValidIndex) {
751 GrCrash("Index reads outside valid index range.");
752 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000753 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000754
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000755 GrAssert(NULL != drawState.getRenderTarget());
756 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
757 if (drawState.isStageEnabled(s)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000758 const GrEffect* effect = drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000759 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000760 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000761 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000762 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
763 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000764 }
765 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000766#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000767 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000768 return false;
769 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000770 return true;
771}
772
773void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
774 int startIndex, int vertexCount,
775 int indexCount) {
776 if (indexCount > 0 &&
777 this->checkDraw(type, startVertex, startIndex,
778 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000779 this->onDrawIndexed(type, startVertex, startIndex,
780 vertexCount, indexCount);
781 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000782}
783
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000784void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
785 int startVertex,
786 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000787 if (vertexCount > 0 &&
788 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000789 this->onDrawNonIndexed(type, startVertex, vertexCount);
790 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000791}
792
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000793void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000794 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000795 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000796 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000797 GrAssert(!stroke.isHairlineStyle());
798 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000799 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000800}
801
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000802////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000803
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000804// Some blend modes allow folding a partial coverage value into the color's
805// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000806bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000807 /**
808 * The fractional coverage is f
809 * The src and dst coeffs are Cs and Cd
810 * The dst and src colors are S and D
811 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
812 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
813 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000814 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000815 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000816 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000817 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000818 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000819 return kOne_GrBlendCoeff == dstCoeff ||
820 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000821 kISC_GrBlendCoeff == dstCoeff ||
822 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000823}
824
bsalomon@google.come79c8152012-03-29 19:07:12 +0000825bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000826 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000827
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000828 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000829 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000830 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000831 return false;
832 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000833 // Check if color filter could introduce an alpha
834 // (TODO: Consider being more aggressive with regards to detecting 0xff
835 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000836 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000837 return false;
838 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000839 int stageCnt;
840 // Check whether coverage is treated as color
841 if (drawState.isCoverageDrawing()) {
842 if (0xff != GrColorUnpackA(drawState.getCoverage())) {
843 return false;
844 }
845 stageCnt = GrDrawState::kNumStages;
846 } else {
847 stageCnt = drawState.getFirstCoverageStage();
848 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000849 // Check if a color stage could create a partial alpha
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000850 for (int s = 0; s < stageCnt; ++s) {
851 const GrEffect* effect = drawState.getStage(s).getEffect();
852 if (NULL != effect) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000853 // FIXME: The param indicates whether the texture is opaque or not. However, the effect
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000854 // already controls its textures. It really needs to know whether the incoming color
855 // (from a uni, per-vertex colors, or previous stage) is opaque or not.
bsalomon@google.com021fc732012-10-25 12:47:42 +0000856 if (!effect->isOpaque(true)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000857 return false;
858 }
859 }
860 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000861 return true;
862}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000863
bsalomon@google.come79c8152012-03-29 19:07:12 +0000864namespace {
865GrVertexLayout default_blend_opts_vertex_layout() {
866 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000867 return layout;
868}
869}
870
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000871GrDrawTarget::BlendOptFlags
872GrDrawTarget::getBlendOpts(bool forceCoverage,
873 GrBlendCoeff* srcCoeff,
874 GrBlendCoeff* dstCoeff) const {
875
bsalomon@google.come79c8152012-03-29 19:07:12 +0000876 GrVertexLayout layout;
877 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
878 layout = default_blend_opts_vertex_layout();
879 } else {
880 layout = this->getVertexLayout();
881 }
882
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000883 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000884
885 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
886 if (NULL == srcCoeff) {
887 srcCoeff = &bogusSrcCoeff;
888 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000889 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000890
891 if (NULL == dstCoeff) {
892 dstCoeff = &bogusDstCoeff;
893 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000894 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000895
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000896 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000897 *srcCoeff = kZero_GrBlendCoeff;
898 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000899 }
900
bsalomon@google.come79c8152012-03-29 19:07:12 +0000901 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000902 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
903 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
904 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
905 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000906
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000907 bool covIsZero = !drawState.isCoverageDrawing() &&
908 !(layout & kCoverage_VertexLayoutBit) &&
909 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000910 // 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.comcf939ae2012-12-13 19:59:23 +0000913 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000914 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000915 return kDisableBlend_BlendOptFlag |
916 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000917 } else {
918 return kSkipDraw_BlendOptFlag;
919 }
920 }
921
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000922 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000923 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000924 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000925 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000926 (layout & kCoverage_VertexLayoutBit) ||
927 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000929 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000930 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000931 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000932 hasCoverage = true;
933 }
934 }
935
936 // if we don't have coverage we can check whether the dst
937 // has to read at all. If not, we'll disable blending.
938 if (!hasCoverage) {
939 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000940 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000941 // if there is no coverage and coeffs are (1,0) then we
942 // won't need to read the dst at all, it gets replaced by src
943 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000944 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000945 // if the op is "clear" then we don't need to emit a color
946 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000947 *srcCoeff = kOne_GrBlendCoeff;
948 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000949 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000950 }
951 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000952 } else if (drawState.isCoverageDrawing()) {
953 // we have coverage but we aren't distinguishing it from alpha by request.
954 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000955 } 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.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000971 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000972 // 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.comf6601872012-08-28 21:11:35 +0000991 if (!fCaps.hwAALineSupport() ||
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.comf6601872012-08-28 21:11:35 +00001003 return this->getCaps().dualSourceBlendingSupport() ||
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
rmistry@google.comd6176b02012-08-23 18:14:13 +00001038void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001039 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001040 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001041 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001042 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001043
1044 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001045 if (!geo.succeeded()) {
1046 GrPrintf("Failed to get space for vertices!\n");
1047 return;
1048 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001049
rmistry@google.comd6176b02012-08-23 18:14:13 +00001050 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001051 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001052
bsalomon@google.com47059542012-06-06 20:51:20 +00001053 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001054}
1055
bsalomon@google.come3d32162012-07-20 13:37:06 +00001056GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
1057 if (NULL == srcRects) {
1058 return 0;
1059 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001060
bsalomon@google.come3d32162012-07-20 13:37:06 +00001061 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +00001062 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001063 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +00001064 if (NULL != srcRects[i]) {
1065 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1066 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001067 }
1068 }
1069 return layout;
1070}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001071
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001072// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001073// matrix - is applied to each vertex
1074// srcRects - provide the uvs for each vertex
1075// srcMatrices - are applied to the corresponding 'srcRect'
1076// color - vertex color (replicated in each vertex)
1077// layout - specifies which uvs and/or color are present
1078// vertices - storage for the resulting vertices
1079// Note: the color parameter will only be used when kColor_VertexLayoutBit
1080// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001081void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001082 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001083 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001084 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001085 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001086 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001087 void* vertices) {
1088#if GR_DEBUG
1089 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001090 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001091 if (VertexTexCoordsForStage(i, layout) >= 0) {
1092 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1093 } else {
1094 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1095 }
1096 }
1097#endif
1098
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001099 int stageOffsets[GrDrawState::kNumStages], colorOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +00001100 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001101 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001102
bsalomon@google.coma3108262011-10-10 14:08:47 +00001103 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001104 rect.fRight, rect.fBottom,
1105 vsize);
1106 if (NULL != matrix) {
1107 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1108 }
1109
tomhudson@google.com93813632011-10-27 20:21:16 +00001110 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001111 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001112 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001113 stageOffsets[i]);
1114 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001115 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001116 vsize);
1117 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1118 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1119 }
1120 }
1121 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001122
1123 if (layout & kColor_VertexLayoutBit) {
1124
1125 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
1126
1127 for (int i = 0; i < 4; ++i) {
1128 *vertCol = color;
1129 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
1130 }
1131 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001132}
1133
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001134////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001135
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001136GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1137 fDrawTarget = NULL;
1138}
reed@google.comac10a2d2010-12-22 21:39:39 +00001139
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001140GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1141 ASRInit init) {
1142 fDrawTarget = NULL;
1143 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001144}
1145
1146GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001147 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001148 fDrawTarget->setDrawState(fSavedState);
1149 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001150 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001151}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001152
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001153void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1154 GrAssert(NULL == fDrawTarget);
1155 fDrawTarget = target;
1156 fSavedState = target->drawState();
1157 GrAssert(fSavedState);
1158 fSavedState->ref();
1159 if (kReset_ASRInit == init) {
1160 // calls the default cons
1161 fTempState.init();
1162 } else {
1163 GrAssert(kPreserve_ASRInit == init);
1164 // calls the copy cons
1165 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001166 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001167 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001168}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001169
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001170////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001171
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001172GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1173 GrDrawTarget* target,
1174 GrVertexLayout vertexLayout,
1175 int vertexCount,
1176 int indexCount) {
1177 fTarget = NULL;
1178 this->set(target, vertexLayout, vertexCount, indexCount);
1179}
rmistry@google.comd6176b02012-08-23 18:14:13 +00001180
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001181GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1182 fTarget = NULL;
1183}
1184
1185GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1186 this->reset();
1187}
1188
1189bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1190 GrVertexLayout vertexLayout,
1191 int vertexCount,
1192 int indexCount) {
1193 this->reset();
1194 fTarget = target;
1195 bool success = true;
1196 if (NULL != fTarget) {
1197 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001198 success = target->reserveVertexAndIndexSpace(vertexLayout,
1199 vertexCount,
1200 indexCount,
1201 &fVertices,
1202 &fIndices);
1203 if (!success) {
1204 fTarget = NULL;
1205 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001206 }
1207 }
1208 GrAssert(success == (NULL != fTarget));
1209 return success;
1210}
1211
1212void GrDrawTarget::AutoReleaseGeometry::reset() {
1213 if (NULL != fTarget) {
1214 if (NULL != fVertices) {
1215 fTarget->resetVertexSource();
1216 }
1217 if (NULL != fIndices) {
1218 fTarget->resetIndexSource();
1219 }
1220 fTarget = NULL;
1221 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001222 fVertices = NULL;
1223 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001224}
1225
bsalomon@google.com8d67c072012-12-13 20:38:14 +00001226GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
1227 fTarget = target;
1228 fClip = fTarget->getClip();
1229 fStack.init();
1230 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
1231 fReplacementClip.fClipStack = fStack.get();
1232 target->setClip(&fReplacementClip);
1233}
1234
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001235void GrDrawTarget::Caps::print() const {
1236 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +00001237 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
1238 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
1239 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
1240 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
1241 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
1242 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
1243 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
1244 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
1245 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
1246 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
1247 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
1248 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
1249 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001250}