blob: 92b8a0335871beca9e039ddb4daade27068f86e7 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrDrawTarget.h"
12#include "GrGpuVertex.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrIndexBuffer.h"
14#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000015#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000016#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
sugoi@google.com12b4e272012-12-06 20:13:11 +000018#include "SkStroke.h"
19
reed@google.comfa35e3d2012-06-26 20:16:17 +000020SK_DEFINE_INST_COUNT(GrDrawTarget)
21
junov@google.com6acc9b32011-05-16 18:32:07 +000022namespace {
23
bsalomon@google.com35ff3842011-12-15 16:58:19 +000024/**
25 * This function generates some masks that we like to have known at compile
26 * time. When the number of stages or tex coords is bumped or the way bits
robertphillips@google.coma72eef32012-05-01 17:22:59 +000027 * are defined in GrDrawTarget.h changes this function should be rerun to
bsalomon@google.com35ff3842011-12-15 16:58:19 +000028 * generate the new masks. (We attempted to force the compiler to generate the
29 * masks using recursive templates but always wound up with static initializers
30 * under gcc, even if they were just a series of immediate->memory moves.)
rmistry@google.comd6176b02012-08-23 18:14:13 +000031 *
bsalomon@google.com35ff3842011-12-15 16:58:19 +000032 */
33void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000034 GrVertexLayout* texCoordMasks) {
35 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
36 stageTexCoordMasks[s] = 0;
37 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
38 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
39 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +000040 }
41 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
42 texCoordMasks[t] = 0;
43 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
44 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
45 }
46 }
reed@google.comac10a2d2010-12-22 21:39:39 +000047}
48
rmistry@google.comd6176b02012-08-23 18:14:13 +000049/**
bsalomon@google.com35ff3842011-12-15 16:58:19 +000050 * Run this function to generate the code that declares the global masks.
51 */
52void gen_globals() {
53 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000054 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +000055 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
rmistry@google.comd6176b02012-08-23 18:14:13 +000056
bsalomon@google.com35ff3842011-12-15 16:58:19 +000057 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
58 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
59 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
60 }
61 GrPrintf("};\n");
62 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
bsalomon@google.com35ff3842011-12-15 16:58:19 +000063 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
64 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
65 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
66 }
67 GrPrintf("};\n");
68 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000069}
70
bsalomon@google.com35ff3842011-12-15 16:58:19 +000071/* These values were generated by the above function */
twiz@google.com58071162012-07-18 21:41:50 +000072
bsalomon@google.com35ff3842011-12-15 16:58:19 +000073const GrVertexLayout gStageTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000074 0x108421,
75 0x210842,
76 0x421084,
77 0x842108,
78 0x1084210,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000079};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000080GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000081
bsalomon@google.com35ff3842011-12-15 16:58:19 +000082const GrVertexLayout gTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000083 0x1f,
84 0x3e0,
85 0x7c00,
86 0xf8000,
87 0x1f00000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000088};
89GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000090
91bool check_layout(GrVertexLayout layout) {
92 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000093 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +000094 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000095 if (stageBits && !GrIsPow2(stageBits)) {
96 return false;
97 }
98 }
99 return true;
100}
101
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000102int num_tex_coords(GrVertexLayout layout) {
103 int cnt = 0;
104 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000105 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000106 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000107 ++cnt;
108 }
109 }
110 return cnt;
111}
112
junov@google.com6acc9b32011-05-16 18:32:07 +0000113} //unnamed namespace
114
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000115size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
116 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000117
118 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000119 sizeof(GrGpuTextVertex) :
120 sizeof(GrPoint);
121
122 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000123 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000124 if (vertexLayout & kColor_VertexLayoutBit) {
125 size += sizeof(GrColor);
126 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000127 if (vertexLayout & kCoverage_VertexLayoutBit) {
128 size += sizeof(GrColor);
129 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000130 if (vertexLayout & kEdge_VertexLayoutBit) {
bsalomon@google.com81712882012-11-01 17:12:34 +0000131 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000132 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000133 return size;
134}
135
bsalomon@google.coma3108262011-10-10 14:08:47 +0000136////////////////////////////////////////////////////////////////////////////////
137
138/**
139 * Functions for computing offsets of various components from the layout
140 * bitfield.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000141 *
bsalomon@google.coma3108262011-10-10 14:08:47 +0000142 * Order of vertex components:
143 * Position
144 * Tex Coord 0
145 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000146 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000147 * Color
148 * Coverage
149 */
150
bsalomon@google.com08283af2012-10-26 13:01:20 +0000151int GrDrawTarget::VertexStageCoordOffset(int stageIdx, GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000152 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000153
bsalomon@google.com08283af2012-10-26 13:01:20 +0000154 if (!StageUsesTexCoords(vertexLayout, stageIdx)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 return 0;
156 }
bsalomon@google.com08283af2012-10-26 13:01:20 +0000157 int tcIdx = VertexTexCoordsForStage(stageIdx, vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000158 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000159
160 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000161 sizeof(GrGpuTextVertex) :
162 sizeof(GrPoint);
163 int offset = vecSize; // position
164 // figure out how many tex coordinates are present and precede this one.
165 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000166 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000167 offset += vecSize;
168 }
169 }
170 return offset;
171 }
172
reed@google.comac10a2d2010-12-22 21:39:39 +0000173 return -1;
174}
175
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000176int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000177 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000178
reed@google.comac10a2d2010-12-22 21:39:39 +0000179 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000180 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000181 sizeof(GrGpuTextVertex) :
182 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000183 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
184 }
185 return -1;
186}
187
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000188int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000189 GrAssert(check_layout(vertexLayout));
190
191 if (vertexLayout & kCoverage_VertexLayoutBit) {
192 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
193 sizeof(GrGpuTextVertex) :
194 sizeof(GrPoint);
195
196 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
197 if (vertexLayout & kColor_VertexLayoutBit) {
198 offset += sizeof(GrColor);
199 }
200 return offset;
201 }
202 return -1;
203}
204
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000205int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000206 GrAssert(check_layout(vertexLayout));
207
208 // edge pts are after the pos, tex coords, and color
209 if (vertexLayout & kEdge_VertexLayoutBit) {
210 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
211 sizeof(GrGpuTextVertex) :
212 sizeof(GrPoint);
213 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
214 if (vertexLayout & kColor_VertexLayoutBit) {
215 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000216 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000217 if (vertexLayout & kCoverage_VertexLayoutBit) {
218 offset += sizeof(GrColor);
219 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000220 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000221 }
222 return -1;
223}
224
tomhudson@google.com93813632011-10-27 20:21:16 +0000225int GrDrawTarget::VertexSizeAndOffsetsByIdx(
226 GrVertexLayout vertexLayout,
227 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
228 int* colorOffset,
229 int* coverageOffset,
230 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000231 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000232
bsalomon@google.com5782d712011-01-21 21:03:59 +0000233 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000234 sizeof(GrGpuTextVertex) :
235 sizeof(GrPoint);
236 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000237
tomhudson@google.com93813632011-10-27 20:21:16 +0000238 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000239 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000240 if (NULL != texCoordOffsetsByIdx) {
241 texCoordOffsetsByIdx[t] = size;
242 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000243 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000245 if (NULL != texCoordOffsetsByIdx) {
246 texCoordOffsetsByIdx[t] = -1;
247 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000250 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000251 if (NULL != colorOffset) {
252 *colorOffset = size;
253 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000254 size += sizeof(GrColor);
255 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000256 if (NULL != colorOffset) {
257 *colorOffset = -1;
258 }
259 }
260 if (kCoverage_VertexLayoutBit & vertexLayout) {
261 if (NULL != coverageOffset) {
262 *coverageOffset = size;
263 }
264 size += sizeof(GrColor);
265 } else {
266 if (NULL != coverageOffset) {
267 *coverageOffset = -1;
268 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000269 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000270 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000271 if (NULL != edgeOffset) {
272 *edgeOffset = size;
273 }
bsalomon@google.com81712882012-11-01 17:12:34 +0000274 size += 4 * sizeof(SkScalar);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000275 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000276 if (NULL != edgeOffset) {
277 *edgeOffset = -1;
278 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000279 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000280 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000281}
282
tomhudson@google.com93813632011-10-27 20:21:16 +0000283int GrDrawTarget::VertexSizeAndOffsetsByStage(
284 GrVertexLayout vertexLayout,
285 int texCoordOffsetsByStage[GrDrawState::kNumStages],
286 int* colorOffset,
287 int* coverageOffset,
288 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000289 GrAssert(check_layout(vertexLayout));
290
tomhudson@google.com93813632011-10-27 20:21:16 +0000291 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000292 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000293 (NULL == texCoordOffsetsByStage) ?
294 NULL :
295 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000296 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000297 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000298 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000299 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000300 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000301 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
302 texCoordOffsetsByStage[s] =
303 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000304 }
305 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000306 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000307}
308
bsalomon@google.coma3108262011-10-10 14:08:47 +0000309////////////////////////////////////////////////////////////////////////////////
310
bsalomon@google.com5782d712011-01-21 21:03:59 +0000311bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000312 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000313 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000314 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000315 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000316}
317
bsalomon@google.com08283af2012-10-26 13:01:20 +0000318int GrDrawTarget::VertexTexCoordsForStage(int stageIdx,
tomhudson@google.com93813632011-10-27 20:21:16 +0000319 GrVertexLayout vertexLayout) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000320 GrAssert(stageIdx < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000321 GrAssert(check_layout(vertexLayout));
bsalomon@google.com08283af2012-10-26 13:01:20 +0000322 int bit = vertexLayout & gStageTexCoordMasks[stageIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000323 if (bit) {
324 // figure out which set of texture coordates is used
325 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
326 // and start at bit 0.
327 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000328 return (32 - SkCLZ(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000329 }
330 return -1;
331}
332
bsalomon@google.coma3108262011-10-10 14:08:47 +0000333////////////////////////////////////////////////////////////////////////////////
334
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000335void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000336 // Ensure that our globals mask arrays are correct
337 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000338 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000339 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000340 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
341 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000342 }
343 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
344 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
345 }
346
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000347 // not necessarily exhaustive
348 static bool run;
349 if (!run) {
350 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000351 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000353 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000354 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000355 stageMask |= StageTexCoordVertexLayoutBit(s,t);
356 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000357 GrAssert(1 == GrDrawState::kMaxTexCoords ||
358 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000359 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000360 GrAssert(!check_layout(stageMask));
361 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000362 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000363 GrVertexLayout tcMask = 0;
364 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000365 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000366 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000367 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
368 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
369 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
370 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000371 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000372 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000373
bsalomon@google.com19628322011-02-03 21:30:17 +0000374 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000375 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000376 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000377 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000378 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
379 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000380 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000381 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000382 GrAssert(-1 == VertexEdgeOffset(tcMask));
383 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000384 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000385 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000386 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000387 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000388 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000389 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
390 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000391 #if GR_DEBUG
392 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
393 #endif
394 GrAssert(-1 == VertexColorOffset(withEdge));
395 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
396 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
397 #if GR_DEBUG
398 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
399 #endif
400 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
401 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
402 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000403 #if GR_DEBUG
404 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
405 #endif
406 GrAssert(-1 == VertexColorOffset(withCoverage));
407 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
408 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
409 #if GR_DEBUG
410 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
411 kColor_VertexLayoutBit;
412 #endif
413 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
414 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
415 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000416 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000417 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000418 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000419
tomhudson@google.com93813632011-10-27 20:21:16 +0000420 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000421 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000422 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000423 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000424 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000425 size = VertexSizeAndOffsetsByStage(tcMask,
426 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000427 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000428 GrAssert(2*sizeof(GrPoint) == size);
429 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000430 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000431 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000432 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000433 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
434 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
435 }
436 }
437 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000438}
439
440////////////////////////////////////////////////////////////////////////////////
441
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000442#define DEBUG_INVAL_BUFFER 0xdeadcafe
443#define DEBUG_INVAL_START_IDX -1
444
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000445GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000446#if GR_DEBUG
447 VertexLayoutUnitTest();
448#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000449 fDrawState = &fDefaultDrawState;
450 // We assume that fDrawState always owns a ref to the object it points at.
451 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000452 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000453#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000454 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
455 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
456 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
457 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000458#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000459 geoSrc.fVertexSrc = kNone_GeometrySrcType;
460 geoSrc.fIndexSrc = kNone_GeometrySrcType;
461}
462
463GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000464 GrAssert(1 == fGeoSrcStateStack.count());
465 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
466 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
467 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000468 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000469}
470
471void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000472 int popCnt = fGeoSrcStateStack.count() - 1;
473 while (popCnt) {
474 this->popGeometrySource();
475 --popCnt;
476 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000477 this->resetVertexSource();
478 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000479}
480
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000481void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000482 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000483 fClip = clip;
484}
485
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000486const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000487 return fClip;
488}
489
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000490void GrDrawTarget::setDrawState(GrDrawState* drawState) {
491 GrAssert(NULL != fDrawState);
492 if (NULL == drawState) {
493 drawState = &fDefaultDrawState;
494 }
495 if (fDrawState != drawState) {
496 fDrawState->unref();
497 drawState->ref();
498 fDrawState = drawState;
499 }
500}
501
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000502bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
503 int vertexCount,
504 void** vertices) {
505 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
506 bool acquired = false;
507 if (vertexCount > 0) {
508 GrAssert(NULL != vertices);
509 this->releasePreviousVertexSource();
510 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000511
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000512 acquired = this->onReserveVertexSpace(vertexLayout,
513 vertexCount,
514 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000515 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000516 if (acquired) {
517 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
518 geoSrc.fVertexCount = vertexCount;
519 geoSrc.fVertexLayout = vertexLayout;
520 } else if (NULL != vertices) {
521 *vertices = NULL;
522 }
523 return acquired;
524}
525
526bool GrDrawTarget::reserveIndexSpace(int indexCount,
527 void** indices) {
528 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
529 bool acquired = false;
530 if (indexCount > 0) {
531 GrAssert(NULL != indices);
532 this->releasePreviousIndexSource();
533 geoSrc.fIndexSrc = kNone_GeometrySrcType;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000534
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000535 acquired = this->onReserveIndexSpace(indexCount, indices);
536 }
537 if (acquired) {
538 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
539 geoSrc.fIndexCount = indexCount;
540 } else if (NULL != indices) {
541 *indices = NULL;
542 }
543 return acquired;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000544
reed@google.comac10a2d2010-12-22 21:39:39 +0000545}
546
bsalomon@google.com08283af2012-10-26 13:01:20 +0000547bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stageIdx) {
548 return SkToBool(layout & gStageTexCoordMasks[stageIdx]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000549}
550
bsalomon@google.come3d70952012-03-13 12:40:53 +0000551bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
552 int vertexCount,
553 int indexCount,
554 void** vertices,
555 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000556 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000557 if (vertexCount) {
558 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
559 if (indexCount) {
560 this->resetIndexSource();
561 }
562 return false;
563 }
564 }
565 if (indexCount) {
566 if (!this->reserveIndexSpace(indexCount, indices)) {
567 if (vertexCount) {
568 this->resetVertexSource();
569 }
570 return false;
571 }
572 }
573 return true;
574}
575
reed@google.comac10a2d2010-12-22 21:39:39 +0000576bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
577 int32_t* vertexCount,
578 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000579 if (NULL != vertexCount) {
580 *vertexCount = -1;
581 }
582 if (NULL != indexCount) {
583 *indexCount = -1;
584 }
585 return false;
586}
587
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000588void GrDrawTarget::releasePreviousVertexSource() {
589 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
590 switch (geoSrc.fVertexSrc) {
591 case kNone_GeometrySrcType:
592 break;
593 case kArray_GeometrySrcType:
594 this->releaseVertexArray();
595 break;
596 case kReserved_GeometrySrcType:
597 this->releaseReservedVertexSpace();
598 break;
599 case kBuffer_GeometrySrcType:
600 geoSrc.fVertexBuffer->unref();
601#if GR_DEBUG
602 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
603#endif
604 break;
605 default:
606 GrCrash("Unknown Vertex Source Type.");
607 break;
608 }
609}
610
611void GrDrawTarget::releasePreviousIndexSource() {
612 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
613 switch (geoSrc.fIndexSrc) {
614 case kNone_GeometrySrcType: // these two don't require
615 break;
616 case kArray_GeometrySrcType:
617 this->releaseIndexArray();
618 break;
619 case kReserved_GeometrySrcType:
620 this->releaseReservedIndexSpace();
621 break;
622 case kBuffer_GeometrySrcType:
623 geoSrc.fIndexBuffer->unref();
624#if GR_DEBUG
625 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
626#endif
627 break;
628 default:
629 GrCrash("Unknown Index Source Type.");
630 break;
631 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000632}
633
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000634void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
635 const void* vertexArray,
636 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000637 this->releasePreviousVertexSource();
638 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
639 geoSrc.fVertexSrc = kArray_GeometrySrcType;
640 geoSrc.fVertexLayout = vertexLayout;
641 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000642 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000643}
644
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000645void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
646 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000647 this->releasePreviousIndexSource();
648 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
649 geoSrc.fIndexSrc = kArray_GeometrySrcType;
650 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000651 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000652}
653
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000654void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
655 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000656 this->releasePreviousVertexSource();
657 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
658 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
659 geoSrc.fVertexBuffer = buffer;
660 buffer->ref();
661 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000662}
663
664void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000665 this->releasePreviousIndexSource();
666 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
667 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
668 geoSrc.fIndexBuffer = buffer;
669 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000670}
671
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000672void GrDrawTarget::resetVertexSource() {
673 this->releasePreviousVertexSource();
674 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
675 geoSrc.fVertexSrc = kNone_GeometrySrcType;
676}
677
678void GrDrawTarget::resetIndexSource() {
679 this->releasePreviousIndexSource();
680 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
681 geoSrc.fIndexSrc = kNone_GeometrySrcType;
682}
683
684void GrDrawTarget::pushGeometrySource() {
685 this->geometrySourceWillPush();
686 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
687 newState.fIndexSrc = kNone_GeometrySrcType;
688 newState.fVertexSrc = kNone_GeometrySrcType;
689#if GR_DEBUG
690 newState.fVertexCount = ~0;
691 newState.fVertexBuffer = (GrVertexBuffer*)~0;
692 newState.fIndexCount = ~0;
693 newState.fIndexBuffer = (GrIndexBuffer*)~0;
694#endif
695}
696
697void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000698 // if popping last element then pops are unbalanced with pushes
699 GrAssert(fGeoSrcStateStack.count() > 1);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000700
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000701 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
702 this->releasePreviousVertexSource();
703 this->releasePreviousIndexSource();
704 fGeoSrcStateStack.pop_back();
705}
706
707////////////////////////////////////////////////////////////////////////////////
708
bsalomon@google.come8262622011-11-07 02:30:51 +0000709bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
710 int startIndex, int vertexCount,
711 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000712 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000714 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000715 int maxVertex = startVertex + vertexCount;
716 int maxValidVertex;
717 switch (geoSrc.fVertexSrc) {
718 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000719 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000720 case kReserved_GeometrySrcType: // fallthrough
721 case kArray_GeometrySrcType:
722 maxValidVertex = geoSrc.fVertexCount;
723 break;
724 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000725 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000726 break;
727 }
728 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000729 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000730 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000731 if (indexCount > 0) {
732 int maxIndex = startIndex + indexCount;
733 int maxValidIndex;
734 switch (geoSrc.fIndexSrc) {
735 case kNone_GeometrySrcType:
736 GrCrash("Attempting to draw indexed geom without index src.");
737 case kReserved_GeometrySrcType: // fallthrough
738 case kArray_GeometrySrcType:
739 maxValidIndex = geoSrc.fIndexCount;
740 break;
741 case kBuffer_GeometrySrcType:
742 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
743 break;
744 }
745 if (maxIndex > maxValidIndex) {
746 GrCrash("Index reads outside valid index range.");
747 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000748 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000749
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000750 GrAssert(NULL != drawState.getRenderTarget());
751 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
752 if (drawState.isStageEnabled(s)) {
bsalomon@google.com08283af2012-10-26 13:01:20 +0000753 const GrEffect* effect = drawState.getStage(s).getEffect();
bsalomon@google.com021fc732012-10-25 12:47:42 +0000754 int numTextures = effect->numTextures();
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000755 for (int t = 0; t < numTextures; ++t) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000756 GrTexture* texture = effect->texture(t);
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000757 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
758 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000759 }
760 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000761#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000762 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000763 return false;
764 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000765 return true;
766}
767
768void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
769 int startIndex, int vertexCount,
770 int indexCount) {
771 if (indexCount > 0 &&
772 this->checkDraw(type, startVertex, startIndex,
773 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000774 this->onDrawIndexed(type, startVertex, startIndex,
775 vertexCount, indexCount);
776 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000777}
778
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000779void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
780 int startVertex,
781 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000782 if (vertexCount > 0 &&
783 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000784 this->onDrawNonIndexed(type, startVertex, vertexCount);
785 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000786}
787
sugoi@google.com12b4e272012-12-06 20:13:11 +0000788void GrDrawTarget::stencilPath(const GrPath* path, const SkStroke& stroke, SkPath::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000789 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000790 GrAssert(NULL != path);
bsalomon@google.comf6601872012-08-28 21:11:35 +0000791 GrAssert(fCaps.pathStencilingSupport());
sugoi@google.com12b4e272012-12-06 20:13:11 +0000792 GrAssert(0 != stroke.getWidthIfStroked());
793 GrAssert(!SkPath::IsInverseFill(fill));
794 this->onStencilPath(path, stroke, fill);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000795}
796
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000797////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000798
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000799// Some blend modes allow folding a partial coverage value into the color's
800// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000801bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000802 /**
803 * The fractional coverage is f
804 * The src and dst coeffs are Cs and Cd
805 * The dst and src colors are S and D
806 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
807 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
808 * obvious that that first term will always be ok. The second term can be
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000809 * rearranged as [1-(1-Cd)f]D. By substituting in the various possibilities
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000810 * for Cd we find that only 1, ISA, and ISC produce the correct depth
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000811 * coefficient in terms of S' and D.
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000812 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000813 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000814 return kOne_GrBlendCoeff == dstCoeff ||
815 kISA_GrBlendCoeff == dstCoeff ||
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000816 kISC_GrBlendCoeff == dstCoeff ||
817 this->getDrawState().isCoverageDrawing();
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000818}
819
bsalomon@google.come79c8152012-03-29 19:07:12 +0000820bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000821 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000822
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000823 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000824 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000825 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000826 return false;
827 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000828 // Check if color filter could introduce an alpha
829 // (TODO: Consider being more aggressive with regards to detecting 0xff
830 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000831 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000832 return false;
833 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000834 int stageCnt;
835 // Check whether coverage is treated as color
836 if (drawState.isCoverageDrawing()) {
837 if (0xff != GrColorUnpackA(drawState.getCoverage())) {
838 return false;
839 }
840 stageCnt = GrDrawState::kNumStages;
841 } else {
842 stageCnt = drawState.getFirstCoverageStage();
843 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000844 // Check if a color stage could create a partial alpha
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000845 for (int s = 0; s < stageCnt; ++s) {
846 const GrEffect* effect = drawState.getStage(s).getEffect();
847 if (NULL != effect) {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000848 // FIXME: The param indicates whether the texture is opaque or not. However, the effect
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000849 // already controls its textures. It really needs to know whether the incoming color
850 // (from a uni, per-vertex colors, or previous stage) is opaque or not.
bsalomon@google.com021fc732012-10-25 12:47:42 +0000851 if (!effect->isOpaque(true)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000852 return false;
853 }
854 }
855 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000856 return true;
857}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000858
bsalomon@google.come79c8152012-03-29 19:07:12 +0000859namespace {
860GrVertexLayout default_blend_opts_vertex_layout() {
861 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000862 return layout;
863}
864}
865
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000866GrDrawTarget::BlendOptFlags
867GrDrawTarget::getBlendOpts(bool forceCoverage,
868 GrBlendCoeff* srcCoeff,
869 GrBlendCoeff* dstCoeff) const {
870
bsalomon@google.come79c8152012-03-29 19:07:12 +0000871 GrVertexLayout layout;
872 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
873 layout = default_blend_opts_vertex_layout();
874 } else {
875 layout = this->getVertexLayout();
876 }
877
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000878 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000879
880 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
881 if (NULL == srcCoeff) {
882 srcCoeff = &bogusSrcCoeff;
883 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000884 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000885
886 if (NULL == dstCoeff) {
887 dstCoeff = &bogusDstCoeff;
888 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000889 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000890
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000891 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000892 *srcCoeff = kZero_GrBlendCoeff;
893 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000894 }
895
bsalomon@google.come79c8152012-03-29 19:07:12 +0000896 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000897 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
898 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
899 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
900 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000901
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000902 bool covIsZero = !drawState.isCoverageDrawing() &&
903 !(layout & kCoverage_VertexLayoutBit) &&
904 0 == drawState.getCoverage();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000905 // When coeffs are (0,1) there is no reason to draw at all, unless
906 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000907 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000908 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) || covIsZero) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000909 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000910 return kDisableBlend_BlendOptFlag |
911 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000912 } else {
913 return kSkipDraw_BlendOptFlag;
914 }
915 }
916
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000917 // check for coverage due to constant coverage, per-vertex coverage,
bsalomon@google.com021fc732012-10-25 12:47:42 +0000918 // edge aa or coverage stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000919 bool hasCoverage = forceCoverage ||
rmistry@google.comd6176b02012-08-23 18:14:13 +0000920 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000921 (layout & kCoverage_VertexLayoutBit) ||
922 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000923 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000924 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000925 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000926 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000927 hasCoverage = true;
928 }
929 }
930
931 // if we don't have coverage we can check whether the dst
932 // has to read at all. If not, we'll disable blending.
933 if (!hasCoverage) {
934 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000935 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000936 // if there is no coverage and coeffs are (1,0) then we
937 // won't need to read the dst at all, it gets replaced by src
938 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000939 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000940 // if the op is "clear" then we don't need to emit a color
941 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000942 *srcCoeff = kOne_GrBlendCoeff;
943 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000944 return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000945 }
946 }
bsalomon@google.comcf939ae2012-12-13 19:59:23 +0000947 } else if (drawState.isCoverageDrawing()) {
948 // we have coverage but we aren't distinguishing it from alpha by request.
949 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000950 } else {
951 // check whether coverage can be safely rolled into alpha
952 // of if we can skip color computation and just emit coverage
953 if (this->canTweakAlphaForCoverage()) {
954 return kCoverageAsAlpha_BlendOptFlag;
955 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000956 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000957 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000958 // the source color is not included in the blend
959 // the dst coeff is effectively zero so blend works out to:
960 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000961 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000962 return kEmitCoverage_BlendOptFlag;
963 } else if (srcAIsOne) {
964 // the dst coeff is effectively zero so blend works out to:
965 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000966 // If Sa is 1 then we can replace Sa with c
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000967 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000968 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000969 return kCoverageAsAlpha_BlendOptFlag;
970 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000971 } else if (dstCoeffIsOne) {
972 // the dst coeff is effectively one so blend works out to:
973 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000974 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000975 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000976 }
977 }
978 return kNone_BlendOpt;
979}
980
981bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +0000982 // there is a conflict between using smooth lines and our use of
983 // premultiplied alpha. Smooth lines tweak the incoming alpha value
984 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000985 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.comf6601872012-08-28 21:11:35 +0000986 if (!fCaps.hwAALineSupport() ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000987 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000988 return false;
989 }
990 BlendOptFlags opts = this->getBlendOpts();
991 return (kDisableBlend_BlendOptFlag & opts) &&
992 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000993}
994
995bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000996 // we can correctly apply coverage if a) we have dual source blending
997 // or b) one of our blend optimizations applies.
bsalomon@google.comf6601872012-08-28 21:11:35 +0000998 return this->getCaps().dualSourceBlendingSupport() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000999 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001000}
1001
bsalomon@google.com934c5702012-03-20 21:17:58 +00001002////////////////////////////////////////////////////////////////////////////////
1003
1004void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1005 int instanceCount,
1006 int verticesPerInstance,
1007 int indicesPerInstance) {
1008 if (!verticesPerInstance || !indicesPerInstance) {
1009 return;
1010 }
1011
1012 int instancesPerDraw = this->indexCountInCurrentSource() /
1013 indicesPerInstance;
1014 if (!instancesPerDraw) {
1015 return;
1016 }
1017
1018 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1019 int startVertex = 0;
1020 while (instanceCount) {
1021 this->drawIndexed(type,
1022 startVertex,
1023 0,
1024 verticesPerInstance * instancesPerDraw,
1025 indicesPerInstance * instancesPerDraw);
1026 startVertex += verticesPerInstance;
1027 instanceCount -= instancesPerDraw;
1028 }
1029}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001030
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001031////////////////////////////////////////////////////////////////////////////////
1032
rmistry@google.comd6176b02012-08-23 18:14:13 +00001033void GrDrawTarget::drawRect(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001034 const SkMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001035 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001036 const SkMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001037 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001038
1039 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001040 if (!geo.succeeded()) {
1041 GrPrintf("Failed to get space for vertices!\n");
1042 return;
1043 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001044
rmistry@google.comd6176b02012-08-23 18:14:13 +00001045 SetRectVertices(rect, matrix, srcRects,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001046 srcMatrices, SK_ColorBLACK, layout, geo.vertices());
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001047
bsalomon@google.com47059542012-06-06 20:51:20 +00001048 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001049}
1050
bsalomon@google.come3d32162012-07-20 13:37:06 +00001051GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
1052 if (NULL == srcRects) {
1053 return 0;
1054 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001055
bsalomon@google.come3d32162012-07-20 13:37:06 +00001056 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +00001057 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001058 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +00001059 if (NULL != srcRects[i]) {
1060 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1061 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001062 }
1063 }
1064 return layout;
1065}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001066
skia.committer@gmail.coma18ed032012-10-06 02:05:26 +00001067// This method fills int the four vertices for drawing 'rect'.
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001068// matrix - is applied to each vertex
1069// srcRects - provide the uvs for each vertex
1070// srcMatrices - are applied to the corresponding 'srcRect'
1071// color - vertex color (replicated in each vertex)
1072// layout - specifies which uvs and/or color are present
1073// vertices - storage for the resulting vertices
1074// Note: the color parameter will only be used when kColor_VertexLayoutBit
1075// is present in 'layout'
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001076void GrDrawTarget::SetRectVertices(const GrRect& rect,
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001077 const SkMatrix* matrix,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001078 const GrRect* srcRects[],
bsalomon@google.comb9086a02012-11-01 18:02:54 +00001079 const SkMatrix* srcMatrices[],
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001080 GrColor color,
rmistry@google.comd6176b02012-08-23 18:14:13 +00001081 GrVertexLayout layout,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001082 void* vertices) {
1083#if GR_DEBUG
1084 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001085 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001086 if (VertexTexCoordsForStage(i, layout) >= 0) {
1087 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1088 } else {
1089 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1090 }
1091 }
1092#endif
1093
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001094 int stageOffsets[GrDrawState::kNumStages], colorOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +00001095 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001096 &colorOffset, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001097
bsalomon@google.coma3108262011-10-10 14:08:47 +00001098 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001099 rect.fRight, rect.fBottom,
1100 vsize);
1101 if (NULL != matrix) {
1102 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1103 }
1104
tomhudson@google.com93813632011-10-27 20:21:16 +00001105 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001106 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001107 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001108 stageOffsets[i]);
1109 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001110 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001111 vsize);
1112 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1113 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1114 }
1115 }
1116 }
robertphillips@google.com8b129aa2012-10-05 15:37:00 +00001117
1118 if (layout & kColor_VertexLayoutBit) {
1119
1120 GrColor* vertCol = GrTCast<GrColor*>(GrTCast<intptr_t>(vertices) + colorOffset);
1121
1122 for (int i = 0; i < 4; ++i) {
1123 *vertCol = color;
1124 vertCol = (GrColor*) ((intptr_t) vertCol + vsize);
1125 }
1126 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001127}
1128
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001129////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001130
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001131GrDrawTarget::AutoStateRestore::AutoStateRestore() {
1132 fDrawTarget = NULL;
1133}
reed@google.comac10a2d2010-12-22 21:39:39 +00001134
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001135GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target,
1136 ASRInit init) {
1137 fDrawTarget = NULL;
1138 this->set(target, init);
reed@google.comac10a2d2010-12-22 21:39:39 +00001139}
1140
1141GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001142 if (NULL != fDrawTarget) {
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001143 fDrawTarget->setDrawState(fSavedState);
1144 fSavedState->unref();
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001145 }
reed@google.comac10a2d2010-12-22 21:39:39 +00001146}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +00001147
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001148void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target, ASRInit init) {
1149 GrAssert(NULL == fDrawTarget);
1150 fDrawTarget = target;
1151 fSavedState = target->drawState();
1152 GrAssert(fSavedState);
1153 fSavedState->ref();
1154 if (kReset_ASRInit == init) {
1155 // calls the default cons
1156 fTempState.init();
1157 } else {
1158 GrAssert(kPreserve_ASRInit == init);
1159 // calls the copy cons
1160 fTempState.set(*fSavedState);
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001161 }
bsalomon@google.com873ea0c2012-03-30 15:55:32 +00001162 target->setDrawState(fTempState.get());
bsalomon@google.com06afe7b2011-04-26 15:31:40 +00001163}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001164
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001165////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001166
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001167GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1168 GrDrawTarget* target,
1169 GrVertexLayout vertexLayout,
1170 int vertexCount,
1171 int indexCount) {
1172 fTarget = NULL;
1173 this->set(target, vertexLayout, vertexCount, indexCount);
1174}
rmistry@google.comd6176b02012-08-23 18:14:13 +00001175
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001176GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1177 fTarget = NULL;
1178}
1179
1180GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1181 this->reset();
1182}
1183
1184bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1185 GrVertexLayout vertexLayout,
1186 int vertexCount,
1187 int indexCount) {
1188 this->reset();
1189 fTarget = target;
1190 bool success = true;
1191 if (NULL != fTarget) {
1192 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001193 success = target->reserveVertexAndIndexSpace(vertexLayout,
1194 vertexCount,
1195 indexCount,
1196 &fVertices,
1197 &fIndices);
1198 if (!success) {
1199 fTarget = NULL;
1200 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001201 }
1202 }
1203 GrAssert(success == (NULL != fTarget));
1204 return success;
1205}
1206
1207void GrDrawTarget::AutoReleaseGeometry::reset() {
1208 if (NULL != fTarget) {
1209 if (NULL != fVertices) {
1210 fTarget->resetVertexSource();
1211 }
1212 if (NULL != fIndices) {
1213 fTarget->resetIndexSource();
1214 }
1215 fTarget = NULL;
1216 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001217 fVertices = NULL;
1218 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001219}
1220
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001221void GrDrawTarget::Caps::print() const {
1222 static const char* gNY[] = {"NO", "YES"};
bsalomon@google.comf6601872012-08-28 21:11:35 +00001223 GrPrintf("8 Bit Palette Support : %s\n", gNY[fInternals.f8BitPaletteSupport]);
1224 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fInternals.fNPOTTextureTileSupport]);
1225 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fInternals.fTwoSidedStencilSupport]);
1226 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fInternals.fStencilWrapOpsSupport]);
1227 GrPrintf("HW AA Lines Support : %s\n", gNY[fInternals.fHWAALineSupport]);
1228 GrPrintf("Shader Derivative Support : %s\n", gNY[fInternals.fShaderDerivativeSupport]);
1229 GrPrintf("Geometry Shader Support : %s\n", gNY[fInternals.fGeometryShaderSupport]);
1230 GrPrintf("FSAA Support : %s\n", gNY[fInternals.fFSAASupport]);
1231 GrPrintf("Dual Source Blending Support: %s\n", gNY[fInternals.fDualSourceBlendingSupport]);
1232 GrPrintf("Buffer Lock Support : %s\n", gNY[fInternals.fBufferLockSupport]);
1233 GrPrintf("Path Stenciling Support : %s\n", gNY[fInternals.fPathStencilingSupport]);
1234 GrPrintf("Max Texture Size : %d\n", fInternals.fMaxTextureSize);
1235 GrPrintf("Max Render Target Size : %d\n", fInternals.fMaxRenderTargetSize);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001236}