blob: f80a4416f31b53c4f52df693aa9f40bc49c40200 [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/**
bsalomon@google.com35ff3842011-12-15 16:58:19 +000049 * Run this function to generate the code that declares the global masks.
50 */
51void gen_globals() {
52 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000053 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +000054 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
rmistry@google.comd6176b02012-08-23 18:14:13 +000055
bsalomon@google.com35ff3842011-12-15 16:58:19 +000056 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
57 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
58 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
59 }
60 GrPrintf("};\n");
61 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
bsalomon@google.com35ff3842011-12-15 16:58:19 +000062 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
63 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
64 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
65 }
66 GrPrintf("};\n");
67 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000068}
69
bsalomon@google.com35ff3842011-12-15 16:58:19 +000070/* These values were generated by the above function */
twiz@google.com58071162012-07-18 21:41:50 +000071
bsalomon@google.com35ff3842011-12-15 16:58:19 +000072const GrVertexLayout gStageTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000073 0x108421,
74 0x210842,
75 0x421084,
76 0x842108,
77 0x1084210,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000078};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000079GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000080
bsalomon@google.com35ff3842011-12-15 16:58:19 +000081const GrVertexLayout gTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000082 0x1f,
83 0x3e0,
84 0x7c00,
85 0xf8000,
86 0x1f00000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000087};
88GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000089
90bool check_layout(GrVertexLayout layout) {
91 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000092 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +000093 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000094 if (stageBits && !GrIsPow2(stageBits)) {
95 return false;
96 }
97 }
98 return true;
99}
100
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000101int num_tex_coords(GrVertexLayout layout) {
102 int cnt = 0;
103 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000104 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000105 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000106 ++cnt;
107 }
108 }
109 return cnt;
110}
111
junov@google.com6acc9b32011-05-16 18:32:07 +0000112} //unnamed namespace
113
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000114size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
115 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116
117 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000118 sizeof(GrGpuTextVertex) :
119 sizeof(GrPoint);
120
121 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000122 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000123 if (vertexLayout & kColor_VertexLayoutBit) {
124 size += sizeof(GrColor);
125 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000126 if (vertexLayout & kCoverage_VertexLayoutBit) {
127 size += sizeof(GrColor);
128 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000129 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000130 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000131 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000132 return size;
133}
134
bsalomon@google.coma3108262011-10-10 14:08:47 +0000135////////////////////////////////////////////////////////////////////////////////
136
137/**
138 * Functions for computing offsets of various components from the layout
139 * bitfield.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000140 *
bsalomon@google.coma3108262011-10-10 14:08:47 +0000141 * Order of vertex components:
142 * Position
143 * Tex Coord 0
144 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000145 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000146 * Color
147 * Coverage
148 */
149
bsalomon@google.com08283af2012-10-26 13:01:20 +0000150int GrDrawTarget::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000151 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000152
bsalomon@google.com08283af2012-10-26 13:01:20 +0000153 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 return 0;
155 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000156 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000157 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000158
159 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000160 sizeof(GrGpuTextVertex) :
161 sizeof(GrPoint);
162 int offset = vecSize; // position
163 // figure out how many tex coordinates are present and precede this one.
164 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000165 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000166 offset += vecSize;
167 }
168 }
169 return offset;
170 }
171
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 return -1;
173}
174
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000175int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000176 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000177
reed@google.comac10a2d2010-12-22 21:39:39 +0000178 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000179 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000180 sizeof(GrGpuTextVertex) :
181 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000182 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
183 }
184 return -1;
185}
186
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000187int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000188 GrAssert(check_layout(vertexLayout));
189
190 if (vertexLayout & kCoverage_VertexLayoutBit) {
191 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
192 sizeof(GrGpuTextVertex) :
193 sizeof(GrPoint);
194
195 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
196 if (vertexLayout & kColor_VertexLayoutBit) {
197 offset += sizeof(GrColor);
198 }
199 return offset;
200 }
201 return -1;
202}
203
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000204int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000205 GrAssert(check_layout(vertexLayout));
206
207 // edge pts are after the pos, tex coords, and color
208 if (vertexLayout & kEdge_VertexLayoutBit) {
209 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
210 sizeof(GrGpuTextVertex) :
211 sizeof(GrPoint);
212 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
213 if (vertexLayout & kColor_VertexLayoutBit) {
214 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000216 if (vertexLayout & kCoverage_VertexLayoutBit) {
217 offset += sizeof(GrColor);
218 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000219 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 }
221 return -1;
222}
223
tomhudson@google.com93813632011-10-27 20:21:16 +0000224int GrDrawTarget::VertexSizeAndOffsetsByIdx(
225 GrVertexLayout vertexLayout,
226 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
227 int* colorOffset,
228 int* coverageOffset,
229 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000230 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000231
bsalomon@google.com5782d712011-01-21 21:03:59 +0000232 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000233 sizeof(GrGpuTextVertex) :
234 sizeof(GrPoint);
235 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000236
tomhudson@google.com93813632011-10-27 20:21:16 +0000237 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000238 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000239 if (NULL != texCoordOffsetsByIdx) {
240 texCoordOffsetsByIdx[t] = size;
241 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000242 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000243 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000244 if (NULL != texCoordOffsetsByIdx) {
245 texCoordOffsetsByIdx[t] = -1;
246 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000247 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000249 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000250 if (NULL != colorOffset) {
251 *colorOffset = size;
252 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000253 size += sizeof(GrColor);
254 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000255 if (NULL != colorOffset) {
256 *colorOffset = -1;
257 }
258 }
259 if (kCoverage_VertexLayoutBit & vertexLayout) {
260 if (NULL != coverageOffset) {
261 *coverageOffset = size;
262 }
263 size += sizeof(GrColor);
264 } else {
265 if (NULL != coverageOffset) {
266 *coverageOffset = -1;
267 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000268 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000269 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000270 if (NULL != edgeOffset) {
271 *edgeOffset = size;
272 }
bsalomon@google.com81712882012-11-01 17:12:34 +0000273 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000274 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000275 if (NULL != edgeOffset) {
276 *edgeOffset = -1;
277 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000278 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000279 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000280}
281
tomhudson@google.com93813632011-10-27 20:21:16 +0000282int GrDrawTarget::VertexSizeAndOffsetsByStage(
283 GrVertexLayout vertexLayout,
284 int texCoordOffsetsByStage[GrDrawState::kNumStages],
285 int* colorOffset,
286 int* coverageOffset,
287 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000288 GrAssert(check_layout(vertexLayout));
289
tomhudson@google.com93813632011-10-27 20:21:16 +0000290 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000291 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000292 (NULL == texCoordOffsetsByStage) ?
293 NULL :
294 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000295 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000296 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000297 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000298 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000299 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000300 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
301 texCoordOffsetsByStage[s] =
302 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303 }
304 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000305 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000306}
307
bsalomon@google.coma3108262011-10-10 14:08:47 +0000308////////////////////////////////////////////////////////////////////////////////
309
bsalomon@google.com5782d712011-01-21 21:03:59 +0000310bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000311 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000312 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000313 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000314 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000315}
316
bsalomon@google.com08283af2012-10-26 13:01:20 +0000317int GrDrawTarget::VertexTexCoordsForStage(int stageIdx,
tomhudson@google.com93813632011-10-27 20:21:16 +0000318 GrVertexLayout vertexLayout) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000319 GrAssert(stageIdx < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000320 GrAssert(check_layout(vertexLayout));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000321 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000322 if (bit) {
323 // figure out which set of texture coordates is used
324 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
325 // and start at bit 0.
326 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000327 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000328 }
329 return -1;
330}
331
bsalomon@google.coma3108262011-10-10 14:08:47 +0000332////////////////////////////////////////////////////////////////////////////////
333
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000334void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000335 // Ensure that our globals mask arrays are correct
336 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000337 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000338 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000339 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
340 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000341 }
342 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
343 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
344 }
345
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000346 // not necessarily exhaustive
347 static bool run;
348 if (!run) {
349 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000350 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000351
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000353 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000354 stageMask |= StageTexCoordVertexLayoutBit(s,t);
355 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000356 GrAssert(1 == GrDrawState::kMaxTexCoords ||
357 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000358 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000359 GrAssert(!check_layout(stageMask));
360 }
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 GrVertexLayout tcMask = 0;
363 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000364 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000365 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000366 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
367 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
368 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
369 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000370 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000371 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000372
bsalomon@google.com19628322011-02-03 21:30:17 +0000373 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000374 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000375 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000376 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000377 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
378 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000379 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000380 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000381 GrAssert(-1 == VertexEdgeOffset(tcMask));
382 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000383 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000384 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000385 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000386 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000387 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000388 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
389 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000390 #if GR_DEBUG
391 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
392 #endif
393 GrAssert(-1 == VertexColorOffset(withEdge));
394 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
395 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
396 #if GR_DEBUG
397 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
398 #endif
399 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
400 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
401 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000402 #if GR_DEBUG
403 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
404 #endif
405 GrAssert(-1 == VertexColorOffset(withCoverage));
406 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
407 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
408 #if GR_DEBUG
409 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
410 kColor_VertexLayoutBit;
411 #endif
412 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
413 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
414 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000415 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000416 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000417 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000418
tomhudson@google.com93813632011-10-27 20:21:16 +0000419 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000420 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000421 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000422 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000423 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000424 size = VertexSizeAndOffsetsByStage(tcMask,
425 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000426 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000427 GrAssert(2*sizeof(GrPoint) == size);
428 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000429 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000430 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000431 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000432 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
433 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
434 }
435 }
436 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000437}
438
439////////////////////////////////////////////////////////////////////////////////
440
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000441#define DEBUG_INVAL_BUFFER 0xdeadcafe
442#define DEBUG_INVAL_START_IDX -1
443
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000444GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000445#if GR_DEBUG
446 VertexLayoutUnitTest();
447#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000448 fDrawState = &fDefaultDrawState;
449 // We assume that fDrawState always owns a ref to the object it points at.
450 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000451 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000452#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000453 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
454 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
455 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
456 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000457#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000458 geoSrc.fVertexSrc = kNone_GeometrySrcType;
459 geoSrc.fIndexSrc = kNone_GeometrySrcType;
460}
461
462GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000463 GrAssert(1 == fGeoSrcStateStack.count());
464 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
465 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
466 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000467 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000468}
469
470void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000471 int popCnt = fGeoSrcStateStack.count() - 1;
472 while (popCnt) {
473 this->popGeometrySource();
474 --popCnt;
475 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000476 this->resetVertexSource();
477 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000478}
479
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000480void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000481 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000482 fClip = clip;
483}
484
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000485const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000486 return fClip;
487}
488
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000489void GrDrawTarget::setDrawState(GrDrawState* drawState) {
490 GrAssert(NULL != fDrawState);
491 if (NULL == drawState) {
492 drawState = &fDefaultDrawState;
493 }
494 if (fDrawState != drawState) {
495 fDrawState->unref();
496 drawState->ref();
497 fDrawState = drawState;
498 }
499}
500
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000501bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
502 int vertexCount,
503 void** vertices) {
504 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
505 bool acquired = false;
506 if (vertexCount > 0) {
507 GrAssert(NULL != vertices);
508 this->releasePreviousVertexSource();
509 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000510
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000511 acquired = this->onReserveVertexSpace(vertexLayout,
512 vertexCount,
513 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000514 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000515 if (acquired) {
516 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
517 geoSrc.fVertexCount = vertexCount;
518 geoSrc.fVertexLayout = vertexLayout;
519 } else if (NULL != vertices) {
520 *vertices = NULL;
521 }
522 return acquired;
523}
524
525bool GrDrawTarget::reserveIndexSpace(int indexCount,
526 void** indices) {
527 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
528 bool acquired = false;
529 if (indexCount > 0) {
530 GrAssert(NULL != indices);
531 this->releasePreviousIndexSource();
532 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000533
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000534 acquired = this->onReserveIndexSpace(indexCount, indices);
535 }
536 if (acquired) {
537 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
538 geoSrc.fIndexCount = indexCount;
539 } else if (NULL != indices) {
540 *indices = NULL;
541 }
542 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000543
reed@google.comac10a2d2010-12-22 21:39:39 +0000544}
545
bsalomon@google.com08283af2012-10-26 13:01:20 +0000546bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
547 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000548}
549
bsalomon@google.come3d70952012-03-13 12:40:53 +0000550bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
551 int vertexCount,
552 int indexCount,
553 void** vertices,
554 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000555 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000556 if (vertexCount) {
557 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
558 if (indexCount) {
559 this->resetIndexSource();
560 }
561 return false;
562 }
563 }
564 if (indexCount) {
565 if (!this->reserveIndexSpace(indexCount, indices)) {
566 if (vertexCount) {
567 this->resetVertexSource();
568 }
569 return false;
570 }
571 }
572 return true;
573}
574
reed@google.comac10a2d2010-12-22 21:39:39 +0000575bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
576 int32_t* vertexCount,
577 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000578 if (NULL != vertexCount) {
579 *vertexCount = -1;
580 }
581 if (NULL != indexCount) {
582 *indexCount = -1;
583 }
584 return false;
585}
586
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000587void GrDrawTarget::releasePreviousVertexSource() {
588 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
589 switch (geoSrc.fVertexSrc) {
590 case kNone_GeometrySrcType:
591 break;
592 case kArray_GeometrySrcType:
593 this->releaseVertexArray();
594 break;
595 case kReserved_GeometrySrcType:
596 this->releaseReservedVertexSpace();
597 break;
598 case kBuffer_GeometrySrcType:
599 geoSrc.fVertexBuffer->unref();
600#if GR_DEBUG
601 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
602#endif
603 break;
604 default:
605 GrCrash("Unknown Vertex Source Type.");
606 break;
607 }
608}
609
610void GrDrawTarget::releasePreviousIndexSource() {
611 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
612 switch (geoSrc.fIndexSrc) {
613 case kNone_GeometrySrcType: // these two don't require
614 break;
615 case kArray_GeometrySrcType:
616 this->releaseIndexArray();
617 break;
618 case kReserved_GeometrySrcType:
619 this->releaseReservedIndexSpace();
620 break;
621 case kBuffer_GeometrySrcType:
622 geoSrc.fIndexBuffer->unref();
623#if GR_DEBUG
624 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
625#endif
626 break;
627 default:
628 GrCrash("Unknown Index Source Type.");
629 break;
630 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000631}
632
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000633void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
634 const void* vertexArray,
635 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000636 this->releasePreviousVertexSource();
637 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
638 geoSrc.fVertexSrc = kArray_GeometrySrcType;
639 geoSrc.fVertexLayout = vertexLayout;
640 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000641 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000642}
643
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000644void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
645 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000646 this->releasePreviousIndexSource();
647 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
648 geoSrc.fIndexSrc = kArray_GeometrySrcType;
649 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000650 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000651}
652
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000653void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
654 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000655 this->releasePreviousVertexSource();
656 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
657 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
658 geoSrc.fVertexBuffer = buffer;
659 buffer->ref();
660 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000661}
662
663void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000664 this->releasePreviousIndexSource();
665 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
666 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
667 geoSrc.fIndexBuffer = buffer;
668 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000669}
670
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000671void GrDrawTarget::resetVertexSource() {
672 this->releasePreviousVertexSource();
673 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
674 geoSrc.fVertexSrc = kNone_GeometrySrcType;
675}
676
677void GrDrawTarget::resetIndexSource() {
678 this->releasePreviousIndexSource();
679 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
680 geoSrc.fIndexSrc = kNone_GeometrySrcType;
681}
682
683void GrDrawTarget::pushGeometrySource() {
684 this->geometrySourceWillPush();
685 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
686 newState.fIndexSrc = kNone_GeometrySrcType;
687 newState.fVertexSrc = kNone_GeometrySrcType;
688#if GR_DEBUG
689 newState.fVertexCount = ~0;
690 newState.fVertexBuffer = (GrVertexBuffer*)~0;
691 newState.fIndexCount = ~0;
692 newState.fIndexBuffer = (GrIndexBuffer*)~0;
693#endif
694}
695
696void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000697 // if popping last element then pops are unbalanced with pushes
698 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000699
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000700 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
701 this->releasePreviousVertexSource();
702 this->releasePreviousIndexSource();
703 fGeoSrcStateStack.pop_back();
704}
705
706////////////////////////////////////////////////////////////////////////////////
707
bsalomon@google.come8262622011-11-07 02:30:51 +0000708bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
709 int startIndex, int vertexCount,
710 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000711 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000712#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000713 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000714 int maxVertex = startVertex + vertexCount;
715 int maxValidVertex;
716 switch (geoSrc.fVertexSrc) {
717 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000718 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000719 case kReserved_GeometrySrcType: // fallthrough
720 case kArray_GeometrySrcType:
721 maxValidVertex = geoSrc.fVertexCount;
722 break;
723 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000724 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000725 break;
726 }
727 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000728 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000729 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000730 if (indexCount > 0) {
731 int maxIndex = startIndex + indexCount;
732 int maxValidIndex;
733 switch (geoSrc.fIndexSrc) {
734 case kNone_GeometrySrcType:
735 GrCrash("Attempting to draw indexed geom without index src.");
736 case kReserved_GeometrySrcType: // fallthrough
737 case kArray_GeometrySrcType:
738 maxValidIndex = geoSrc.fIndexCount;
739 break;
740 case kBuffer_GeometrySrcType:
741 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
742 break;
743 }
744 if (maxIndex > maxValidIndex) {
745 GrCrash("Index reads outside valid index range.");
746 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000747 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000748
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000749 GrAssert(NULL != drawState.getRenderTarget());
750 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
751 if (drawState.isStageEnabled(s)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000752 const GrEffect* effect = drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000753 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000754 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000755 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000756 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
757 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000758 }
759 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000760#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000761 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000762 return false;
763 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000764 return true;
765}
766
767void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
768 int startIndex, int vertexCount,
769 int indexCount) {
770 if (indexCount > 0 &&
771 this->checkDraw(type, startVertex, startIndex,
772 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000773 this->onDrawIndexed(type, startVertex, startIndex,
774 vertexCount, indexCount);
775 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000776}
777
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000778void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
779 int startVertex,
780 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000781 if (vertexCount > 0 &&
782 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000783 this->onDrawNonIndexed(type, startVertex, vertexCount);
784 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000785}
786
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000787void GrDrawTarget::stencilPath(const GrPath* path, const SkStrokeRec& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000788 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000789 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000790 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com5f74cf82012-12-17 21:16:45 +0000791 GrAssert(!stroke.isHairlineStyle());
792 GrAssert(!SkPath::IsInverseFillType(fill));
sugoi@google.com12b4e272012-12-06 20:13:11 +0000793 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000794}
795
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000796////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000797
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000798// Some blend modes allow folding a partial coverage value into the color's
799// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000800bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000801 /**
802 * The fractional coverage is f
803 * The src and dst coeffs are Cs and Cd
804 * The dst and src colors are S and D
805 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
806 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
807 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000808 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000809 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000810 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000811 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000812 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000813 return kOne_GrBlendCoeff == dstCoeff ||
814 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000815 kISC_GrBlendCoeff == dstCoeff ||
816 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000817}
818
bsalomon@google.come79c8152012-03-29 19:07:12 +0000819bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000820 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000821
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000822 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000823 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000824 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000825 return false;
826 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000827 // Check if color filter could introduce an alpha
828 // (TODO: Consider being more aggressive with regards to detecting 0xff
829 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000830 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000831 return false;
832 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000833 int stageCnt;
834 // Check whether coverage is treated as color
835 if (drawState.isCoverageDrawing()) {
836 if (0xff != GrColorUnpackA(drawState.getCoverage())) {
837 return false;
838 }
839 stageCnt = GrDrawState::kNumStages;
840 } else {
841 stageCnt = drawState.getFirstCoverageStage();
842 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000843 // Check if a color stage could create a partial alpha
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000844 for (int s = 0; s < stageCnt; ++s) {
845 const GrEffect* effect = drawState.getStage(s).getEffect();
846 if (NULL != effect) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000847 // FIXME: The param indicates whether the texture is opaque or not. However, the effect
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000848 // already controls its textures. It really needs to know whether the incoming color
849 // (from a uni, per-vertex colors, or previous stage) is opaque or not.
bsalomon@google.com021fc732012-10-25 12:47:42 +0000850 if (!effect->isOpaque(true)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000851 return false;
852 }
853 }
854 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000855 return true;
856}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000857
bsalomon@google.come79c8152012-03-29 19:07:12 +0000858namespace {
859GrVertexLayout default_blend_opts_vertex_layout() {
860 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000861 return layout;
862}
863}
864
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000865GrDrawTarget::BlendOptFlags
866GrDrawTarget::getBlendOpts(bool forceCoverage,
867 GrBlendCoeff* srcCoeff,
868 GrBlendCoeff* dstCoeff) const {
869
bsalomon@google.come79c8152012-03-29 19:07:12 +0000870 GrVertexLayout layout;
871 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
872 layout = default_blend_opts_vertex_layout();
873 } else {
874 layout = this->getVertexLayout();
875 }
876
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000877 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000878
879 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
880 if (NULL == srcCoeff) {
881 srcCoeff = &bogusSrcCoeff;
882 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000883 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000884
885 if (NULL == dstCoeff) {
886 dstCoeff = &bogusDstCoeff;
887 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000888 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000889
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000890 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000891 *srcCoeff = kZero_GrBlendCoeff;
892 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000893 }
894
bsalomon@google.come79c8152012-03-29 19:07:12 +0000895 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000896 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
897 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
898 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
899 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000900
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000901 bool covIsZero = !drawState.isCoverageDrawing() &&
902 !(layout & kCoverage_VertexLayoutBit) &&
903 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000904 // When coeffs are (0,1) there is no reason to draw at all, unless
905 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000906 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000907 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000908 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000909 return kDisableBlend_BlendOptFlag |
910 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000911 } else {
912 return kSkipDraw_BlendOptFlag;
913 }
914 }
915
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000916 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000917 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000918 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000919 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000920 (layout & kCoverage_VertexLayoutBit) ||
921 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000922 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000923 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000924 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000925 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000926 hasCoverage = true;
927 }
928 }
929
930 // if we don't have coverage we can check whether the dst
931 // has to read at all. If not, we'll disable blending.
932 if (!hasCoverage) {
933 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000934 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000935 // if there is no coverage and coeffs are (1,0) then we
936 // won't need to read the dst at all, it gets replaced by src
937 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000938 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000939 // if the op is "clear" then we don't need to emit a color
940 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000941 *srcCoeff = kOne_GrBlendCoeff;
942 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000943 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000944 }
945 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000946 } else if (drawState.isCoverageDrawing()) {
947 // we have coverage but we aren't distinguishing it from alpha by request.
948 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000949 } else {
950 // check whether coverage can be safely rolled into alpha
951 // of if we can skip color computation and just emit coverage
952 if (this->canTweakAlphaForCoverage()) {
953 return kCoverageAsAlpha_BlendOptFlag;
954 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000955 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000956 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000957 // the source color is not included in the blend
958 // the dst coeff is effectively zero so blend works out to:
959 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000960 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000961 return kEmitCoverage_BlendOptFlag;
962 } else if (srcAIsOne) {
963 // the dst coeff is effectively zero so blend works out to:
964 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000965 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000966 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000967 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000968 return kCoverageAsAlpha_BlendOptFlag;
969 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000970 } else if (dstCoeffIsOne) {
971 // the dst coeff is effectively one so blend works out to:
972 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000973 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000974 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000975 }
976 }
977 return kNone_BlendOpt;
978}
979
980bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000981 // there is a conflict between using smooth lines and our use of
982 // premultiplied alpha. Smooth lines tweak the incoming alpha value
983 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000984 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000985 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000986 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000987 return false;
988 }
989 BlendOptFlags opts = this->getBlendOpts();
990 return (kDisableBlend_BlendOptFlag & opts) &&
991 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000992}
993
994bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000995 // we can correctly apply coverage if a) we have dual source blending
996 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000997 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000998 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +0000999}
1000
bsalomon@google.com934c5702012-03-20 21:17:58 +00001001////////////////////////////////////////////////////////////////////////////////
1002
1003void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1004 int instanceCount,
1005 int verticesPerInstance,
1006 int indicesPerInstance) {
1007 if (!verticesPerInstance || !indicesPerInstance) {
1008 return;
1009 }
1010
1011 int instancesPerDraw = this->indexCountInCurrentSource() /
1012 indicesPerInstance;
1013 if (!instancesPerDraw) {
1014 return;
1015 }
1016
1017 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1018 int startVertex = 0;
1019 while (instanceCount) {
1020 this->drawIndexed(type,
1021 startVertex,
1022 0,
1023 verticesPerInstance * instancesPerDraw,
1024 indicesPerInstance * instancesPerDraw);
1025 startVertex += verticesPerInstance;
1026 instanceCount -= instancesPerDraw;
1027 }
1028}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001029
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001030////////////////////////////////////////////////////////////////////////////////
1031
rmistry@google.comd6176b02012-08-23 18:14:13 +00001032void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001033 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001034 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001035 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001036 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001037
1038 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001039 if (!geo.succeeded()) {
1040 GrPrintf("Failed to get space for vertices!\n");
1041 return;
1042 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001043
rmistry@google.comd6176b02012-08-23 18:14:13 +00001044 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001045 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001046
bsalomon@google.com47059542012-06-06 20:51:20 +00001047 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001048}
1049
bsalomon@google.come3d32162012-07-20 13:37:06 +00001050GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
1051 if (NULL == srcRects) {
1052 return 0;
1053 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001054
bsalomon@google.come3d32162012-07-20 13:37:06 +00001055 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +00001056 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001057 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +00001058 if (NULL != srcRects[i]) {
1059 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1060 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001061 }
1062 }
1063 return layout;
1064}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001065
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001066// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001067// matrix - is applied to each vertex
1068// srcRects - provide the uvs for each vertex
1069// srcMatrices - are applied to the corresponding 'srcRect'
1070// color - vertex color (replicated in each vertex)
1071// layout - specifies which uvs and/or color are present
1072// vertices - storage for the resulting vertices
1073// Note: the color parameter will only be used when kColor_VertexLayoutBit
1074// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001075void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001076 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001077 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001078 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001079 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001080 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001081 void* vertices) {
1082#if GR_DEBUG
1083 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001084 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001085 if (VertexTexCoordsForStage(i, layout) >= 0) {
1086 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1087 } else {
1088 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1089 }
1090 }
1091#endif
1092
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001093 int stageOffsets[GrDrawState::kNumStages], colorOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +00001094 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001095 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001096
bsalomon@google.coma3108262011-10-10 14:08:47 +00001097 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001098 rect.fRight, rect.fBottom,
1099 vsize);
1100 if (NULL != matrix) {
1101 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1102 }
1103
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 (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001106 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001107 stageOffsets[i]);
1108 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001109 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001110 vsize);
1111 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1112 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1113 }
1114 }
1115 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001116
1117 if (layout & kColor_VertexLayoutBit) {
1118
1119 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
1120
1121 for (int i = 0; i < 4; ++i) {
1122 *vertCol = color;
1123 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
1124 }
1125 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001126}
1127
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001128////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001129
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001130GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1131 fDrawTarget = NULL;
1132}
reed@google.comac10a2d2010-12-22 21:39:39 +00001133
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001134GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1135 ASRInit init) {
1136 fDrawTarget = NULL;
1137 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001138}
1139
1140GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001141 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001142 fDrawTarget->setDrawState(fSavedState);
1143 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001144 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001145}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001146
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001147void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1148 GrAssert(NULL == fDrawTarget);
1149 fDrawTarget = target;
1150 fSavedState = target->drawState();
1151 GrAssert(fSavedState);
1152 fSavedState->ref();
1153 if (kReset_ASRInit == init) {
1154 // calls the default cons
1155 fTempState.init();
1156 } else {
1157 GrAssert(kPreserve_ASRInit == init);
1158 // calls the copy cons
1159 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001160 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001161 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001162}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001163
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001164////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001165
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001166GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1167 GrDrawTarget* target,
1168 GrVertexLayout vertexLayout,
1169 int vertexCount,
1170 int indexCount) {
1171 fTarget = NULL;
1172 this->set(target, vertexLayout, vertexCount, indexCount);
1173}
rmistry@google.comd6176b02012-08-23 18:14:13 +00001174
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001175GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1176 fTarget = NULL;
1177}
1178
1179GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1180 this->reset();
1181}
1182
1183bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1184 GrVertexLayout vertexLayout,
1185 int vertexCount,
1186 int indexCount) {
1187 this->reset();
1188 fTarget = target;
1189 bool success = true;
1190 if (NULL != fTarget) {
1191 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001192 success = target->reserveVertexAndIndexSpace(vertexLayout,
1193 vertexCount,
1194 indexCount,
1195 &fVertices,
1196 &fIndices);
1197 if (!success) {
1198 fTarget = NULL;
1199 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001200 }
1201 }
1202 GrAssert(success == (NULL != fTarget));
1203 return success;
1204}
1205
1206void GrDrawTarget::AutoReleaseGeometry::reset() {
1207 if (NULL != fTarget) {
1208 if (NULL != fVertices) {
1209 fTarget->resetVertexSource();
1210 }
1211 if (NULL != fIndices) {
1212 fTarget->resetIndexSource();
1213 }
1214 fTarget = NULL;
1215 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001216 fVertices = NULL;
1217 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001218}
1219
bsalomon@google.com8d67c072012-12-13 20:38:14 +00001220GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRect& newClip) {
1221 fTarget = target;
1222 fClip = fTarget->getClip();
1223 fStack.init();
1224 fStack.get()->clipDevRect(newClip, SkRegion::kReplace_Op);
1225 fReplacementClip.fClipStack = fStack.get();
1226 target->setClip(&fReplacementClip);
1227}
1228
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001229void GrDrawTarget::Caps::print() const {
1230 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +00001231 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
1232 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
1233 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
1234 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
1235 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
1236 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
1237 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
1238 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
1239 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
1240 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
1241 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
1242 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
1243 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001244}