blob: b0bac8ae77c48e24d038b20afb4a00673a45db96 [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/**
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +000049 * Uncomment and run the gen_globals function to generate
humper@google.com05af1af2013-01-07 16:47:43 +000050 * 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 */
skia.committer@gmail.com4e8ef332013-01-08 02:01:29 +000054
humper@google.com05af1af2013-01-07 16:47:43 +000055#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
humper@google.com0e515772013-01-07 19:54:40 +000096#ifdef SK_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097bool check_layout(GrVertexLayout layout) {
98 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000099 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +0000100 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000101 if (stageBits && !GrIsPow2(stageBits)) {
102 return false;
103 }
104 }
105 return true;
106}
humper@google.com0e515772013-01-07 19:54:40 +0000107#endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000108
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000109int num_tex_coords(GrVertexLayout layout) {
110 int cnt = 0;
111 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000112 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000113 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000114 ++cnt;
115 }
116 }
117 return cnt;
118}
119
junov@google.com6acc9b32011-05-16 18:32:07 +0000120} //unnamed namespace
121
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000122size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
123 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000124
125 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000126 sizeof(GrGpuTextVertex) :
127 sizeof(GrPoint);
128
129 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000130 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131 if (vertexLayout & kColor_VertexLayoutBit) {
132 size += sizeof(GrColor);
133 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000134 if (vertexLayout & kCoverage_VertexLayoutBit) {
135 size += sizeof(GrColor);
136 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000137 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000138 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000139 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000140 return size;
141}
142
bsalomon@google.coma3108262011-10-10 14:08:47 +0000143////////////////////////////////////////////////////////////////////////////////
144
145/**
146 * Functions for computing offsets of various components from the layout
147 * bitfield.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 *
bsalomon@google.coma3108262011-10-10 14:08:47 +0000149 * Order of vertex components:
150 * Position
151 * Tex Coord 0
152 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000153 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000154 * Color
155 * Coverage
156 */
157
bsalomon@google.com08283af2012-10-26 13:01:20 +0000158int GrDrawTarget::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000159 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000160
bsalomon@google.com08283af2012-10-26 13:01:20 +0000161 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000162 return 0;
163 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000164 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000165 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000166
167 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000168 sizeof(GrGpuTextVertex) :
169 sizeof(GrPoint);
170 int offset = vecSize; // position
171 // figure out how many tex coordinates are present and precede this one.
172 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000173 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000174 offset += vecSize;
175 }
176 }
177 return offset;
178 }
179
reed@google.comac10a2d2010-12-22 21:39:39 +0000180 return -1;
181}
182
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000183int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000184 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000185
reed@google.comac10a2d2010-12-22 21:39:39 +0000186 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000187 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000188 sizeof(GrGpuTextVertex) :
189 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000190 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
191 }
192 return -1;
193}
194
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000195int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000196 GrAssert(check_layout(vertexLayout));
197
198 if (vertexLayout & kCoverage_VertexLayoutBit) {
199 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
200 sizeof(GrGpuTextVertex) :
201 sizeof(GrPoint);
202
203 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
204 if (vertexLayout & kColor_VertexLayoutBit) {
205 offset += sizeof(GrColor);
206 }
207 return offset;
208 }
209 return -1;
210}
211
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000212int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000213 GrAssert(check_layout(vertexLayout));
214
215 // edge pts are after the pos, tex coords, and color
216 if (vertexLayout & kEdge_VertexLayoutBit) {
217 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
218 sizeof(GrGpuTextVertex) :
219 sizeof(GrPoint);
220 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
221 if (vertexLayout & kColor_VertexLayoutBit) {
222 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000223 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000224 if (vertexLayout & kCoverage_VertexLayoutBit) {
225 offset += sizeof(GrColor);
226 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000227 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 }
229 return -1;
230}
231
tomhudson@google.com93813632011-10-27 20:21:16 +0000232int GrDrawTarget::VertexSizeAndOffsetsByIdx(
233 GrVertexLayout vertexLayout,
234 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
235 int* colorOffset,
236 int* coverageOffset,
237 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000238 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000239
bsalomon@google.com5782d712011-01-21 21:03:59 +0000240 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000241 sizeof(GrGpuTextVertex) :
242 sizeof(GrPoint);
243 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000244
tomhudson@google.com93813632011-10-27 20:21:16 +0000245 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000246 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000247 if (NULL != texCoordOffsetsByIdx) {
248 texCoordOffsetsByIdx[t] = size;
249 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000250 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000251 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000252 if (NULL != texCoordOffsetsByIdx) {
253 texCoordOffsetsByIdx[t] = -1;
254 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000256 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000257 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000258 if (NULL != colorOffset) {
259 *colorOffset = size;
260 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000261 size += sizeof(GrColor);
262 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000263 if (NULL != colorOffset) {
264 *colorOffset = -1;
265 }
266 }
267 if (kCoverage_VertexLayoutBit & vertexLayout) {
268 if (NULL != coverageOffset) {
269 *coverageOffset = size;
270 }
271 size += sizeof(GrColor);
272 } else {
273 if (NULL != coverageOffset) {
274 *coverageOffset = -1;
275 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000276 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000277 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000278 if (NULL != edgeOffset) {
279 *edgeOffset = size;
280 }
bsalomon@google.com81712882012-11-01 17:12:34 +0000281 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000282 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000283 if (NULL != edgeOffset) {
284 *edgeOffset = -1;
285 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000286 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000287 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000288}
289
tomhudson@google.com93813632011-10-27 20:21:16 +0000290int GrDrawTarget::VertexSizeAndOffsetsByStage(
291 GrVertexLayout vertexLayout,
292 int texCoordOffsetsByStage[GrDrawState::kNumStages],
293 int* colorOffset,
294 int* coverageOffset,
295 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000296 GrAssert(check_layout(vertexLayout));
297
tomhudson@google.com93813632011-10-27 20:21:16 +0000298 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000299 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000300 (NULL == texCoordOffsetsByStage) ?
301 NULL :
302 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000303 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000304 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000305 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000306 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000307 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000308 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
309 texCoordOffsetsByStage[s] =
310 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000311 }
312 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000313 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000314}
315
bsalomon@google.coma3108262011-10-10 14:08:47 +0000316////////////////////////////////////////////////////////////////////////////////
317
bsalomon@google.com5782d712011-01-21 21:03:59 +0000318bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000319 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000320 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000321 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000322 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000323}
324
bsalomon@google.com08283af2012-10-26 13:01:20 +0000325int GrDrawTarget::VertexTexCoordsForStage(int stageIdx,
tomhudson@google.com93813632011-10-27 20:21:16 +0000326 GrVertexLayout vertexLayout) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000327 GrAssert(stageIdx < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 GrAssert(check_layout(vertexLayout));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000329 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330 if (bit) {
331 // figure out which set of texture coordates is used
332 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
333 // and start at bit 0.
334 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000335 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000336 }
337 return -1;
338}
339
bsalomon@google.coma3108262011-10-10 14:08:47 +0000340////////////////////////////////////////////////////////////////////////////////
341
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000342void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000343 // Ensure that our globals mask arrays are correct
344 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000345 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000346 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000347 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
348 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000349 }
350 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
351 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
352 }
353
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000354 // not necessarily exhaustive
355 static bool run;
356 if (!run) {
357 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000358 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000359
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000360 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000361 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000362 stageMask |= StageTexCoordVertexLayoutBit(s,t);
363 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000364 GrAssert(1 == GrDrawState::kMaxTexCoords ||
365 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000366 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000367 GrAssert(!check_layout(stageMask));
368 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000369 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000370 GrVertexLayout tcMask = 0;
371 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000372 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000373 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000374 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
375 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
376 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
377 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000378 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000379 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000380
bsalomon@google.com19628322011-02-03 21:30:17 +0000381 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000382 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000383 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000384 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000385 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
386 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000387 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000388 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000389 GrAssert(-1 == VertexEdgeOffset(tcMask));
390 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000391 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000392 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000393 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000394 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000395 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000396 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
397 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000398 #if GR_DEBUG
399 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
400 #endif
401 GrAssert(-1 == VertexColorOffset(withEdge));
402 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
403 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
404 #if GR_DEBUG
405 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
406 #endif
407 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
408 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
409 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000410 #if GR_DEBUG
411 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
412 #endif
413 GrAssert(-1 == VertexColorOffset(withCoverage));
414 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
415 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
416 #if GR_DEBUG
417 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
418 kColor_VertexLayoutBit;
419 #endif
420 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
421 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
422 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000423 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000424 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000425 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000426
tomhudson@google.com93813632011-10-27 20:21:16 +0000427 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000428 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000429 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000430 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000431 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000432 size = VertexSizeAndOffsetsByStage(tcMask,
433 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000434 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000435 GrAssert(2*sizeof(GrPoint) == size);
436 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000437 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000438 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000439 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000440 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
441 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
442 }
443 }
444 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000445}
446
447////////////////////////////////////////////////////////////////////////////////
448
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000449#define DEBUG_INVAL_BUFFER 0xdeadcafe
450#define DEBUG_INVAL_START_IDX -1
451
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000452GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000453#if GR_DEBUG
454 VertexLayoutUnitTest();
455#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000456 fDrawState = &fDefaultDrawState;
457 // We assume that fDrawState always owns a ref to the object it points at.
458 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000459 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000460#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000461 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
462 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
463 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
464 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000465#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000466 geoSrc.fVertexSrc = kNone_GeometrySrcType;
467 geoSrc.fIndexSrc = kNone_GeometrySrcType;
468}
469
470GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000471 GrAssert(1 == fGeoSrcStateStack.count());
humper@google.com0e515772013-01-07 19:54:40 +0000472 SkDEBUGCODE(GeometrySrcState& geoSrc = fGeoSrcStateStack.back());
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000473 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
474 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000475 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000476}
477
478void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000479 int popCnt = fGeoSrcStateStack.count() - 1;
480 while (popCnt) {
481 this->popGeometrySource();
482 --popCnt;
483 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000484 this->resetVertexSource();
485 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000486}
487
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000488void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000489 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000490 fClip = clip;
491}
492
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000493const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000494 return fClip;
495}
496
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000497void GrDrawTarget::setDrawState(GrDrawState* drawState) {
498 GrAssert(NULL != fDrawState);
499 if (NULL == drawState) {
500 drawState = &fDefaultDrawState;
501 }
502 if (fDrawState != drawState) {
503 fDrawState->unref();
504 drawState->ref();
505 fDrawState = drawState;
506 }
507}
508
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000509bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
510 int vertexCount,
511 void** vertices) {
512 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
513 bool acquired = false;
514 if (vertexCount > 0) {
515 GrAssert(NULL != vertices);
516 this->releasePreviousVertexSource();
517 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000518
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000519 acquired = this->onReserveVertexSpace(vertexLayout,
520 vertexCount,
521 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000522 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000523 if (acquired) {
524 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
525 geoSrc.fVertexCount = vertexCount;
526 geoSrc.fVertexLayout = vertexLayout;
527 } else if (NULL != vertices) {
528 *vertices = NULL;
529 }
530 return acquired;
531}
532
533bool GrDrawTarget::reserveIndexSpace(int indexCount,
534 void** indices) {
535 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
536 bool acquired = false;
537 if (indexCount > 0) {
538 GrAssert(NULL != indices);
539 this->releasePreviousIndexSource();
540 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000541
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000542 acquired = this->onReserveIndexSpace(indexCount, indices);
543 }
544 if (acquired) {
545 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
546 geoSrc.fIndexCount = indexCount;
547 } else if (NULL != indices) {
548 *indices = NULL;
549 }
550 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000551
reed@google.comac10a2d2010-12-22 21:39:39 +0000552}
553
bsalomon@google.com08283af2012-10-26 13:01:20 +0000554bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
555 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000556}
557
bsalomon@google.come3d70952012-03-13 12:40:53 +0000558bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
559 int vertexCount,
560 int indexCount,
561 void** vertices,
562 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000563 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000564 if (vertexCount) {
565 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
566 if (indexCount) {
567 this->resetIndexSource();
568 }
569 return false;
570 }
571 }
572 if (indexCount) {
573 if (!this->reserveIndexSpace(indexCount, indices)) {
574 if (vertexCount) {
575 this->resetVertexSource();
576 }
577 return false;
578 }
579 }
580 return true;
581}
582
reed@google.comac10a2d2010-12-22 21:39:39 +0000583bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
584 int32_t* vertexCount,
585 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000586 if (NULL != vertexCount) {
587 *vertexCount = -1;
588 }
589 if (NULL != indexCount) {
590 *indexCount = -1;
591 }
592 return false;
593}
594
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000595void GrDrawTarget::releasePreviousVertexSource() {
596 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
597 switch (geoSrc.fVertexSrc) {
598 case kNone_GeometrySrcType:
599 break;
600 case kArray_GeometrySrcType:
601 this->releaseVertexArray();
602 break;
603 case kReserved_GeometrySrcType:
604 this->releaseReservedVertexSpace();
605 break;
606 case kBuffer_GeometrySrcType:
607 geoSrc.fVertexBuffer->unref();
608#if GR_DEBUG
609 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
610#endif
611 break;
612 default:
613 GrCrash("Unknown Vertex Source Type.");
614 break;
615 }
616}
617
618void GrDrawTarget::releasePreviousIndexSource() {
619 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
620 switch (geoSrc.fIndexSrc) {
621 case kNone_GeometrySrcType: // these two don't require
622 break;
623 case kArray_GeometrySrcType:
624 this->releaseIndexArray();
625 break;
626 case kReserved_GeometrySrcType:
627 this->releaseReservedIndexSpace();
628 break;
629 case kBuffer_GeometrySrcType:
630 geoSrc.fIndexBuffer->unref();
631#if GR_DEBUG
632 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
633#endif
634 break;
635 default:
636 GrCrash("Unknown Index Source Type.");
637 break;
638 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000639}
640
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000641void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
642 const void* vertexArray,
643 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000644 this->releasePreviousVertexSource();
645 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
646 geoSrc.fVertexSrc = kArray_GeometrySrcType;
647 geoSrc.fVertexLayout = vertexLayout;
648 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000649 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000650}
651
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000652void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
653 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000654 this->releasePreviousIndexSource();
655 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
656 geoSrc.fIndexSrc = kArray_GeometrySrcType;
657 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000658 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000659}
660
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000661void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
662 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663 this->releasePreviousVertexSource();
664 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
665 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
666 geoSrc.fVertexBuffer = buffer;
667 buffer->ref();
668 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000669}
670
671void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000672 this->releasePreviousIndexSource();
673 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
674 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
675 geoSrc.fIndexBuffer = buffer;
676 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000677}
678
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000679void GrDrawTarget::resetVertexSource() {
680 this->releasePreviousVertexSource();
681 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
682 geoSrc.fVertexSrc = kNone_GeometrySrcType;
683}
684
685void GrDrawTarget::resetIndexSource() {
686 this->releasePreviousIndexSource();
687 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
688 geoSrc.fIndexSrc = kNone_GeometrySrcType;
689}
690
691void GrDrawTarget::pushGeometrySource() {
692 this->geometrySourceWillPush();
693 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
694 newState.fIndexSrc = kNone_GeometrySrcType;
695 newState.fVertexSrc = kNone_GeometrySrcType;
696#if GR_DEBUG
697 newState.fVertexCount = ~0;
698 newState.fVertexBuffer = (GrVertexBuffer*)~0;
699 newState.fIndexCount = ~0;
700 newState.fIndexBuffer = (GrIndexBuffer*)~0;
701#endif
702}
703
704void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000705 // if popping last element then pops are unbalanced with pushes
706 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000707
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000708 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
709 this->releasePreviousVertexSource();
710 this->releasePreviousIndexSource();
711 fGeoSrcStateStack.pop_back();
712}
713
714////////////////////////////////////////////////////////////////////////////////
715
bsalomon@google.come8262622011-11-07 02:30:51 +0000716bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
717 int startIndex, int vertexCount,
718 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000719 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000720#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000721 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000722 int maxVertex = startVertex + vertexCount;
723 int maxValidVertex;
724 switch (geoSrc.fVertexSrc) {
725 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000726 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000727 case kReserved_GeometrySrcType: // fallthrough
728 case kArray_GeometrySrcType:
729 maxValidVertex = geoSrc.fVertexCount;
730 break;
731 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000732 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000733 break;
734 }
735 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000736 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000737 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000738 if (indexCount > 0) {
739 int maxIndex = startIndex + indexCount;
740 int maxValidIndex;
741 switch (geoSrc.fIndexSrc) {
742 case kNone_GeometrySrcType:
743 GrCrash("Attempting to draw indexed geom without index src.");
744 case kReserved_GeometrySrcType: // fallthrough
745 case kArray_GeometrySrcType:
746 maxValidIndex = geoSrc.fIndexCount;
747 break;
748 case kBuffer_GeometrySrcType:
749 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
750 break;
751 }
752 if (maxIndex > maxValidIndex) {
753 GrCrash("Index reads outside valid index range.");
754 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000755 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000756
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000757 GrAssert(NULL != drawState.getRenderTarget());
758 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
759 if (drawState.isStageEnabled(s)) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000760 const GrEffectRef& effect = *drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000761 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000762 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000763 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000764 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
765 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000766 }
767 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000768#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000769 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000770 return false;
771 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000772 return true;
773}
774
775void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
776 int startIndex, int vertexCount,
777 int indexCount) {
778 if (indexCount > 0 &&
779 this->checkDraw(type, startVertex, startIndex,
780 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000781 this->onDrawIndexed(type, startVertex, startIndex,
782 vertexCount, indexCount);
783 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000784}
785
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000786void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
787 int startVertex,
788 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000789 if (vertexCount > 0 &&
790 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000791 this->onDrawNonIndexed(type, startVertex, vertexCount);
792 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000793}
794
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000795void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000796 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000797 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000798 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000799 GrAssert(!stroke.isHairlineStyle());
800 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000801 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000802}
803
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000804////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000805
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000806// Some blend modes allow folding a partial coverage value into the color's
807// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000808bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000809 /**
810 * The fractional coverage is f
811 * The src and dst coeffs are Cs and Cd
812 * The dst and src colors are S and D
813 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
814 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
815 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000816 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000817 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000818 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000819 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000820 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000821 return kOne_GrBlendCoeff == dstCoeff ||
822 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000823 kISC_GrBlendCoeff == dstCoeff ||
824 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000825}
826
bsalomon@google.come79c8152012-03-29 19:07:12 +0000827bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000828 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000829
bsalomon@google.com371e1052013-01-11 21:08:55 +0000830 uint32_t validComponentFlags;
831 GrColor color;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000832 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com371e1052013-01-11 21:08:55 +0000833 if (layout & kColor_VertexLayoutBit) {
834 validComponentFlags = 0;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000835 } else {
bsalomon@google.com371e1052013-01-11 21:08:55 +0000836 validComponentFlags = GrEffect::kAll_ValidComponentFlags;
837 color = drawState.getColor();
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000838 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000839
840 // Run through the color stages
841 int stageCnt = drawState.getFirstCoverageStage();
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000842 for (int s = 0; s < stageCnt; ++s) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000843 const GrEffectRef* effect = drawState.getStage(s).getEffect();
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000844 if (NULL != effect) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000845 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
bsalomon@google.com371e1052013-01-11 21:08:55 +0000846 }
847 }
848
849 // Check if the color filter could introduce an alpha.
850 // We could skip the above work when this is true, but it is rare and the right fix is to make
851 // the color filter a GrEffect and implement getConstantColorComponents() for it.
852 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
853 validComponentFlags = 0;
854 }
855
856 // Check whether coverage is treated as color. If so we run through the coverage computation.
857 if (drawState.isCoverageDrawing()) {
858 GrColor coverageColor = drawState.getCoverage();
859 GrColor oldColor = color;
860 color = 0;
861 for (int c = 0; c < 4; ++c) {
862 if (validComponentFlags & (1 << c)) {
863 U8CPU a = (oldColor >> (c * 8)) & 0xff;
864 U8CPU b = (coverageColor >> (c * 8)) & 0xff;
865 color |= (SkMulDiv255Round(a, b) << (c * 8));
866 }
867 }
868 for (int s = drawState.getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000869 const GrEffectRef* effect = drawState.getStage(s).getEffect();
bsalomon@google.com371e1052013-01-11 21:08:55 +0000870 if (NULL != effect) {
bsalomon@google.com6340a412013-01-22 19:55:59 +0000871 (*effect)->getConstantColorComponents(&color, &validComponentFlags);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000872 }
873 }
874 }
bsalomon@google.com371e1052013-01-11 21:08:55 +0000875 return (GrEffect::kA_ValidComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000876}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000877
bsalomon@google.come79c8152012-03-29 19:07:12 +0000878namespace {
879GrVertexLayout default_blend_opts_vertex_layout() {
880 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000881 return layout;
882}
883}
884
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000885GrDrawTarget::BlendOptFlags
886GrDrawTarget::getBlendOpts(bool forceCoverage,
887 GrBlendCoeff* srcCoeff,
888 GrBlendCoeff* dstCoeff) const {
889
bsalomon@google.come79c8152012-03-29 19:07:12 +0000890 GrVertexLayout layout;
891 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
892 layout = default_blend_opts_vertex_layout();
893 } else {
894 layout = this->getVertexLayout();
895 }
896
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000897 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000898
899 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
900 if (NULL == srcCoeff) {
901 srcCoeff = &bogusSrcCoeff;
902 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000903 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000904
905 if (NULL == dstCoeff) {
906 dstCoeff = &bogusDstCoeff;
907 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000908 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000909
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000910 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000911 *srcCoeff = kZero_GrBlendCoeff;
912 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000913 }
914
bsalomon@google.come79c8152012-03-29 19:07:12 +0000915 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000916 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
917 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
918 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
919 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000920
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000921 bool covIsZero = !drawState.isCoverageDrawing() &&
922 !(layout & kCoverage_VertexLayoutBit) &&
923 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000924 // When coeffs are (0,1) there is no reason to draw at all, unless
925 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000926 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000927 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000928 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000929 return kDisableBlend_BlendOptFlag |
930 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000931 } else {
932 return kSkipDraw_BlendOptFlag;
933 }
934 }
935
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000936 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000937 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000938 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000939 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000940 (layout & kCoverage_VertexLayoutBit) ||
941 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000942 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000943 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000944 ++s) {
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +0000945 if (drawState.isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000946 hasCoverage = true;
947 }
948 }
949
950 // if we don't have coverage we can check whether the dst
951 // has to read at all. If not, we'll disable blending.
952 if (!hasCoverage) {
953 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000954 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000955 // if there is no coverage and coeffs are (1,0) then we
956 // won't need to read the dst at all, it gets replaced by src
957 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000958 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000959 // if the op is "clear" then we don't need to emit a color
960 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000961 *srcCoeff = kOne_GrBlendCoeff;
962 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000963 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000964 }
965 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000966 } else if (drawState.isCoverageDrawing()) {
967 // we have coverage but we aren't distinguishing it from alpha by request.
968 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000969 } else {
970 // check whether coverage can be safely rolled into alpha
971 // of if we can skip color computation and just emit coverage
972 if (this->canTweakAlphaForCoverage()) {
973 return kCoverageAsAlpha_BlendOptFlag;
974 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000975 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000976 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000977 // the source color is not included in the blend
978 // the dst coeff is effectively zero so blend works out to:
979 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000980 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000981 return kEmitCoverage_BlendOptFlag;
982 } else if (srcAIsOne) {
983 // the dst coeff is effectively zero so blend works out to:
984 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000985 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000986 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000987 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000988 return kCoverageAsAlpha_BlendOptFlag;
989 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000990 } else if (dstCoeffIsOne) {
991 // the dst coeff is effectively one so blend works out to:
992 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000993 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000994 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000995 }
996 }
997 return kNone_BlendOpt;
998}
999
1000bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001001 // there is a conflict between using smooth lines and our use of
1002 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1003 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001004 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +00001005 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001006 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001007 return false;
1008 }
1009 BlendOptFlags opts = this->getBlendOpts();
1010 return (kDisableBlend_BlendOptFlag & opts) &&
1011 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001012}
1013
1014bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001015 // we can correctly apply coverage if a) we have dual source blending
1016 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +00001017 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001018 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001019}
1020
bsalomon@google.com934c5702012-03-20 21:17:58 +00001021////////////////////////////////////////////////////////////////////////////////
1022
1023void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1024 int instanceCount,
1025 int verticesPerInstance,
1026 int indicesPerInstance) {
1027 if (!verticesPerInstance || !indicesPerInstance) {
1028 return;
1029 }
1030
1031 int instancesPerDraw = this->indexCountInCurrentSource() /
1032 indicesPerInstance;
1033 if (!instancesPerDraw) {
1034 return;
1035 }
1036
1037 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1038 int startVertex = 0;
1039 while (instanceCount) {
1040 this->drawIndexed(type,
1041 startVertex,
1042 0,
1043 verticesPerInstance * instancesPerDraw,
1044 indicesPerInstance * instancesPerDraw);
1045 startVertex += verticesPerInstance;
1046 instanceCount -= instancesPerDraw;
1047 }
1048}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001049
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001050////////////////////////////////////////////////////////////////////////////////
1051
rmistry@google.comd6176b02012-08-23 18:14:13 +00001052void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001053 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001054 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001055 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001056 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001057
1058 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001059 if (!geo.succeeded()) {
1060 GrPrintf("Failed to get space for vertices!\n");
1061 return;
1062 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001063
rmistry@google.comd6176b02012-08-23 18:14:13 +00001064 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001065 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001066
bsalomon@google.com47059542012-06-06 20:51:20 +00001067 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001068}
1069
bsalomon@google.come3d32162012-07-20 13:37:06 +00001070GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
1071 if (NULL == srcRects) {
1072 return 0;
1073 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001074
bsalomon@google.come3d32162012-07-20 13:37:06 +00001075 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +00001076 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001077 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +00001078 if (NULL != srcRects[i]) {
1079 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1080 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001081 }
1082 }
1083 return layout;
1084}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001085
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001086// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001087// matrix - is applied to each vertex
1088// srcRects - provide the uvs for each vertex
1089// srcMatrices - are applied to the corresponding 'srcRect'
1090// color - vertex color (replicated in each vertex)
1091// layout - specifies which uvs and/or color are present
1092// vertices - storage for the resulting vertices
1093// Note: the color parameter will only be used when kColor_VertexLayoutBit
1094// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001095void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001096 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001097 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001098 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001099 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001100 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001101 void* vertices) {
1102#if GR_DEBUG
1103 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001104 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001105 if (VertexTexCoordsForStage(i, layout) >= 0) {
1106 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1107 } else {
1108 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1109 }
1110 }
1111#endif
1112
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001113 int stageOffsets[GrDrawState::kNumStages], colorOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +00001114 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001115 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001116
bsalomon@google.coma3108262011-10-10 14:08:47 +00001117 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001118 rect.fRight, rect.fBottom,
1119 vsize);
1120 if (NULL != matrix) {
1121 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1122 }
1123
tomhudson@google.com93813632011-10-27 20:21:16 +00001124 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001125 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001126 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001127 stageOffsets[i]);
1128 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001129 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001130 vsize);
1131 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1132 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1133 }
1134 }
1135 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001136
1137 if (layout & kColor_VertexLayoutBit) {
1138
1139 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
1140
1141 for (int i = 0; i < 4; ++i) {
1142 *vertCol = color;
1143 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
1144 }
1145 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001146}
1147
bsalomon@google.com02ddc8b2013-01-28 15:35:28 +00001148void GrDrawTarget::clipWillBeSet(const GrClipData* clipData) {
1149}
1150
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001151////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001152
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001153GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1154 fDrawTarget = NULL;
1155}
reed@google.comac10a2d2010-12-22 21:39:39 +00001156
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001157GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1158 ASRInit init) {
1159 fDrawTarget = NULL;
1160 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001161}
1162
1163GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001164 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001165 fDrawTarget->setDrawState(fSavedState);
1166 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001167 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001168}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001169
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001170void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1171 GrAssert(NULL == fDrawTarget);
1172 fDrawTarget = target;
1173 fSavedState = target->drawState();
1174 GrAssert(fSavedState);
1175 fSavedState->ref();
1176 if (kReset_ASRInit == init) {
1177 // calls the default cons
1178 fTempState.init();
1179 } else {
1180 GrAssert(kPreserve_ASRInit == init);
1181 // calls the copy cons
1182 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001183 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001184 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001185}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001186
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001187////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001188
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001189GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1190 GrDrawTarget* target,
1191 GrVertexLayout vertexLayout,
1192 int vertexCount,
1193 int indexCount) {
1194 fTarget = NULL;
1195 this->set(target, vertexLayout, vertexCount, indexCount);
1196}
rmistry@google.comd6176b02012-08-23 18:14:13 +00001197
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001198GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1199 fTarget = NULL;
1200}
1201
1202GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1203 this->reset();
1204}
1205
1206bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1207 GrVertexLayout vertexLayout,
1208 int vertexCount,
1209 int indexCount) {
1210 this->reset();
1211 fTarget = target;
1212 bool success = true;
1213 if (NULL != fTarget) {
1214 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001215 success = target->reserveVertexAndIndexSpace(vertexLayout,
1216 vertexCount,
1217 indexCount,
1218 &fVertices,
1219 &fIndices);
1220 if (!success) {
1221 fTarget = NULL;
1222 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001223 }
1224 }
1225 GrAssert(success == (NULL != fTarget));
1226 return success;
1227}
1228
1229void GrDrawTarget::AutoReleaseGeometry::reset() {
1230 if (NULL != fTarget) {
1231 if (NULL != fVertices) {
1232 fTarget->resetVertexSource();
1233 }
1234 if (NULL != fIndices) {
1235 fTarget->resetIndexSource();
1236 }
1237 fTarget = NULL;
1238 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001239 fVertices = NULL;
1240 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001241}
1242
bsalomon@google.com8d67c072012-12-13 20:38:14 +00001243GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
1244 fTarget = target;
1245 fClip = fTarget->getClip();
1246 fStack.init();
1247 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
1248 fReplacementClip.fClipStack = fStack.get();
1249 target->setClip(&fReplacementClip);
1250}
1251
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001252void GrDrawTarget::Caps::print() const {
1253 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +00001254 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
1255 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
1256 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
1257 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
1258 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
1259 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
1260 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
1261 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
1262 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
1263 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
1264 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
1265 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
1266 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001267}