blob: f0f1864a556b250e310fef91bfc2e1489c2515f4 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#include "GrDrawTarget.h"
12#include "GrGpuVertex.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrIndexBuffer.h"
14#include "GrRenderTarget.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000015#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000016#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
reed@google.comfa35e3d2012-06-26 20:16:17 +000018SK_DEFINE_INST_COUNT(GrDrawTarget)
19
junov@google.com6acc9b32011-05-16 18:32:07 +000020namespace {
21
bsalomon@google.com35ff3842011-12-15 16:58:19 +000022/**
23 * This function generates some masks that we like to have known at compile
24 * time. When the number of stages or tex coords is bumped or the way bits
robertphillips@google.coma72eef32012-05-01 17:22:59 +000025 * are defined in GrDrawTarget.h changes this function should be rerun to
bsalomon@google.com35ff3842011-12-15 16:58:19 +000026 * generate the new masks. (We attempted to force the compiler to generate the
27 * masks using recursive templates but always wound up with static initializers
28 * under gcc, even if they were just a series of immediate->memory moves.)
29 *
30 */
31void gen_mask_arrays(GrVertexLayout* stageTexCoordMasks,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000032 GrVertexLayout* texCoordMasks) {
33 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
34 stageTexCoordMasks[s] = 0;
35 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
36 stageTexCoordMasks[s] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
37 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +000038 }
39 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
40 texCoordMasks[t] = 0;
41 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
42 texCoordMasks[t] |= GrDrawTarget::StageTexCoordVertexLayoutBit(s, t);
43 }
44 }
reed@google.comac10a2d2010-12-22 21:39:39 +000045}
46
bsalomon@google.com35ff3842011-12-15 16:58:19 +000047/**
48 * Run this function to generate the code that declares the global masks.
49 */
50void gen_globals() {
51 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +000052 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +000053 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +000054
55 GrPrintf("const GrVertexLayout gStageTexCoordMasks[] = {\n");
56 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
57 GrPrintf(" 0x%x,\n", stageTexCoordMasks[s]);
58 }
59 GrPrintf("};\n");
60 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));\n\n");
bsalomon@google.com35ff3842011-12-15 16:58:19 +000061 GrPrintf("const GrVertexLayout gTexCoordMasks[] = {\n");
62 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
63 GrPrintf(" 0x%x,\n", texCoordMasks[t]);
64 }
65 GrPrintf("};\n");
66 GrPrintf("GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));\n");
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000067}
68
bsalomon@google.com35ff3842011-12-15 16:58:19 +000069/* These values were generated by the above function */
twiz@google.com58071162012-07-18 21:41:50 +000070
bsalomon@google.com35ff3842011-12-15 16:58:19 +000071const GrVertexLayout gStageTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000072 0x108421,
73 0x210842,
74 0x421084,
75 0x842108,
76 0x1084210,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000077};
bsalomon@google.com35ff3842011-12-15 16:58:19 +000078GR_STATIC_ASSERT(GrDrawState::kNumStages == GR_ARRAY_COUNT(gStageTexCoordMasks));
bsalomon@google.com35ff3842011-12-15 16:58:19 +000079
bsalomon@google.com35ff3842011-12-15 16:58:19 +000080const GrVertexLayout gTexCoordMasks[] = {
twiz@google.com58071162012-07-18 21:41:50 +000081 0x1f,
82 0x3e0,
83 0x7c00,
84 0xf8000,
85 0x1f00000,
bsalomon@google.com35ff3842011-12-15 16:58:19 +000086};
87GR_STATIC_ASSERT(GrDrawState::kMaxTexCoords == GR_ARRAY_COUNT(gTexCoordMasks));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000088
89bool check_layout(GrVertexLayout layout) {
90 // can only have 1 or 0 bits set for each stage.
tomhudson@google.com93813632011-10-27 20:21:16 +000091 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com52544c72012-07-10 15:06:59 +000092 int stageBits = layout & gStageTexCoordMasks[s];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000093 if (stageBits && !GrIsPow2(stageBits)) {
94 return false;
95 }
96 }
97 return true;
98}
99
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000100int num_tex_coords(GrVertexLayout layout) {
101 int cnt = 0;
102 // figure out how many tex coordinates are present
tomhudson@google.com93813632011-10-27 20:21:16 +0000103 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000104 if (gTexCoordMasks[t] & layout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000105 ++cnt;
106 }
107 }
108 return cnt;
109}
110
junov@google.com6acc9b32011-05-16 18:32:07 +0000111} //unnamed namespace
112
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000113size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
114 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000115
116 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000117 sizeof(GrGpuTextVertex) :
118 sizeof(GrPoint);
119
120 size_t size = vecSize; // position
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000121 size += num_tex_coords(vertexLayout) * vecSize;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000122 if (vertexLayout & kColor_VertexLayoutBit) {
123 size += sizeof(GrColor);
124 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000125 if (vertexLayout & kCoverage_VertexLayoutBit) {
126 size += sizeof(GrColor);
127 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000128 if (vertexLayout & kEdge_VertexLayoutBit) {
129 size += 4 * sizeof(GrScalar);
130 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131 return size;
132}
133
bsalomon@google.coma3108262011-10-10 14:08:47 +0000134////////////////////////////////////////////////////////////////////////////////
135
136/**
137 * Functions for computing offsets of various components from the layout
138 * bitfield.
139 *
140 * Order of vertex components:
141 * Position
142 * Tex Coord 0
143 * ...
tomhudson@google.com93813632011-10-27 20:21:16 +0000144 * Tex Coord GrDrawState::kMaxTexCoords-1
bsalomon@google.coma3108262011-10-10 14:08:47 +0000145 * Color
146 * Coverage
147 */
148
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000149int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
150 GrAssert(check_layout(vertexLayout));
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000151
152 if (!StageUsesTexCoords(vertexLayout, stage)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 return 0;
154 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000155 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
156 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000157
158 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000159 sizeof(GrGpuTextVertex) :
160 sizeof(GrPoint);
161 int offset = vecSize; // position
162 // figure out how many tex coordinates are present and precede this one.
163 for (int t = 0; t < tcIdx; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000164 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000165 offset += vecSize;
166 }
167 }
168 return offset;
169 }
170
reed@google.comac10a2d2010-12-22 21:39:39 +0000171 return -1;
172}
173
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000174int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000175 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000176
reed@google.comac10a2d2010-12-22 21:39:39 +0000177 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000178 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000179 sizeof(GrGpuTextVertex) :
180 sizeof(GrPoint);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000181 return vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
182 }
183 return -1;
184}
185
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000186int GrDrawTarget::VertexCoverageOffset(GrVertexLayout vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000187 GrAssert(check_layout(vertexLayout));
188
189 if (vertexLayout & kCoverage_VertexLayoutBit) {
190 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
191 sizeof(GrGpuTextVertex) :
192 sizeof(GrPoint);
193
194 int offset = vecSize * (num_tex_coords(vertexLayout) + 1);
195 if (vertexLayout & kColor_VertexLayoutBit) {
196 offset += sizeof(GrColor);
197 }
198 return offset;
199 }
200 return -1;
201}
202
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000203int GrDrawTarget::VertexEdgeOffset(GrVertexLayout vertexLayout) {
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000204 GrAssert(check_layout(vertexLayout));
205
206 // edge pts are after the pos, tex coords, and color
207 if (vertexLayout & kEdge_VertexLayoutBit) {
208 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
209 sizeof(GrGpuTextVertex) :
210 sizeof(GrPoint);
211 int offset = vecSize * (num_tex_coords(vertexLayout) + 1); //+1 for pos
212 if (vertexLayout & kColor_VertexLayoutBit) {
213 offset += sizeof(GrColor);
reed@google.comac10a2d2010-12-22 21:39:39 +0000214 }
bsalomon@google.coma3108262011-10-10 14:08:47 +0000215 if (vertexLayout & kCoverage_VertexLayoutBit) {
216 offset += sizeof(GrColor);
217 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000218 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000219 }
220 return -1;
221}
222
tomhudson@google.com93813632011-10-27 20:21:16 +0000223int GrDrawTarget::VertexSizeAndOffsetsByIdx(
224 GrVertexLayout vertexLayout,
225 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords],
226 int* colorOffset,
227 int* coverageOffset,
228 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000229 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000230
bsalomon@google.com5782d712011-01-21 21:03:59 +0000231 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000232 sizeof(GrGpuTextVertex) :
233 sizeof(GrPoint);
234 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000235
tomhudson@google.com93813632011-10-27 20:21:16 +0000236 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000237 if (gTexCoordMasks[t] & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000238 if (NULL != texCoordOffsetsByIdx) {
239 texCoordOffsetsByIdx[t] = size;
240 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000241 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000243 if (NULL != texCoordOffsetsByIdx) {
244 texCoordOffsetsByIdx[t] = -1;
245 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000246 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000247 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248 if (kColor_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000249 if (NULL != colorOffset) {
250 *colorOffset = size;
251 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252 size += sizeof(GrColor);
253 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000254 if (NULL != colorOffset) {
255 *colorOffset = -1;
256 }
257 }
258 if (kCoverage_VertexLayoutBit & vertexLayout) {
259 if (NULL != coverageOffset) {
260 *coverageOffset = size;
261 }
262 size += sizeof(GrColor);
263 } else {
264 if (NULL != coverageOffset) {
265 *coverageOffset = -1;
266 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000267 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000268 if (kEdge_VertexLayoutBit & vertexLayout) {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000269 if (NULL != edgeOffset) {
270 *edgeOffset = size;
271 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000272 size += 4 * sizeof(GrScalar);
273 } else {
bsalomon@google.coma3108262011-10-10 14:08:47 +0000274 if (NULL != edgeOffset) {
275 *edgeOffset = -1;
276 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000277 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000278 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000279}
280
tomhudson@google.com93813632011-10-27 20:21:16 +0000281int GrDrawTarget::VertexSizeAndOffsetsByStage(
282 GrVertexLayout vertexLayout,
283 int texCoordOffsetsByStage[GrDrawState::kNumStages],
284 int* colorOffset,
285 int* coverageOffset,
286 int* edgeOffset) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000287 GrAssert(check_layout(vertexLayout));
288
tomhudson@google.com93813632011-10-27 20:21:16 +0000289 int texCoordOffsetsByIdx[GrDrawState::kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000290 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000291 (NULL == texCoordOffsetsByStage) ?
292 NULL :
293 texCoordOffsetsByIdx,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000294 colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000295 coverageOffset,
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000296 edgeOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000297 if (NULL != texCoordOffsetsByStage) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000298 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000299 int tcIdx = VertexTexCoordsForStage(s, vertexLayout);
300 texCoordOffsetsByStage[s] =
301 tcIdx < 0 ? 0 : texCoordOffsetsByIdx[tcIdx];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000302 }
303 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000304 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000305}
306
bsalomon@google.coma3108262011-10-10 14:08:47 +0000307////////////////////////////////////////////////////////////////////////////////
308
bsalomon@google.com5782d712011-01-21 21:03:59 +0000309bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000310 GrVertexLayout vertexLayout) {
tomhudson@google.com93813632011-10-27 20:21:16 +0000311 GrAssert(coordIndex < GrDrawState::kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000312 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000313 return !!(gTexCoordMasks[coordIndex] & vertexLayout);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000314}
315
tomhudson@google.com93813632011-10-27 20:21:16 +0000316int GrDrawTarget::VertexTexCoordsForStage(int stage,
317 GrVertexLayout vertexLayout) {
318 GrAssert(stage < GrDrawState::kNumStages);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000319 GrAssert(check_layout(vertexLayout));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000320 int bit = vertexLayout & gStageTexCoordMasks[stage];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000321 if (bit) {
322 // figure out which set of texture coordates is used
323 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
324 // and start at bit 0.
325 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
tomhudson@google.com93813632011-10-27 20:21:16 +0000326 return (32 - Gr_clz(bit) - 1) / GrDrawState::kNumStages;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000327 }
328 return -1;
329}
330
bsalomon@google.coma3108262011-10-10 14:08:47 +0000331////////////////////////////////////////////////////////////////////////////////
332
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000333void GrDrawTarget::VertexLayoutUnitTest() {
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000334 // Ensure that our globals mask arrays are correct
335 GrVertexLayout stageTexCoordMasks[GrDrawState::kNumStages];
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000336 GrVertexLayout texCoordMasks[GrDrawState::kMaxTexCoords];
bsalomon@google.com52544c72012-07-10 15:06:59 +0000337 gen_mask_arrays(stageTexCoordMasks, texCoordMasks);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000338 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
339 GrAssert(stageTexCoordMasks[s] == gStageTexCoordMasks[s]);
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000340 }
341 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
342 GrAssert(texCoordMasks[t] == gTexCoordMasks[t]);
343 }
344
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000345 // not necessarily exhaustive
346 static bool run;
347 if (!run) {
348 run = true;
tomhudson@google.com93813632011-10-27 20:21:16 +0000349 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000350
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000351 GrVertexLayout stageMask = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +0000352 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000353 stageMask |= StageTexCoordVertexLayoutBit(s,t);
354 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000355 GrAssert(1 == GrDrawState::kMaxTexCoords ||
356 !check_layout(stageMask));
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000357 GrAssert(gStageTexCoordMasks[s] == stageMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000358 GrAssert(!check_layout(stageMask));
359 }
tomhudson@google.com93813632011-10-27 20:21:16 +0000360 for (int t = 0; t < GrDrawState::kMaxTexCoords; ++t) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000361 GrVertexLayout tcMask = 0;
362 GrAssert(!VertexUsesTexCoordIdx(t, 0));
tomhudson@google.com93813632011-10-27 20:21:16 +0000363 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000364 tcMask |= StageTexCoordVertexLayoutBit(s,t);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000365 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
366 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
367 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
368 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
tomhudson@google.com93813632011-10-27 20:21:16 +0000369 for (int s2 = s + 1; s2 < GrDrawState::kNumStages; ++s2) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000370 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000371
bsalomon@google.com19628322011-02-03 21:30:17 +0000372 #if GR_DEBUG
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000373 GrVertexLayout posAsTex = tcMask;
bsalomon@google.com19628322011-02-03 21:30:17 +0000374 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000375 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000376 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
377 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000378 GrAssert(-1 == VertexEdgeOffset(posAsTex));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000379 }
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000380 GrAssert(-1 == VertexEdgeOffset(tcMask));
381 GrAssert(-1 == VertexColorOffset(tcMask));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000382 GrAssert(-1 == VertexCoverageOffset(tcMask));
bsalomon@google.com19628322011-02-03 21:30:17 +0000383 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000384 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000385 #endif
bsalomon@google.coma3108262011-10-10 14:08:47 +0000386 GrAssert(-1 == VertexCoverageOffset(withColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000387 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
388 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000389 #if GR_DEBUG
390 GrVertexLayout withEdge = tcMask | kEdge_VertexLayoutBit;
391 #endif
392 GrAssert(-1 == VertexColorOffset(withEdge));
393 GrAssert(2*sizeof(GrPoint) == VertexEdgeOffset(withEdge));
394 GrAssert(4*sizeof(GrPoint) == VertexSize(withEdge));
395 #if GR_DEBUG
396 GrVertexLayout withColorAndEdge = withColor | kEdge_VertexLayoutBit;
397 #endif
398 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColorAndEdge));
399 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexEdgeOffset(withColorAndEdge));
400 GrAssert(4*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColorAndEdge));
bsalomon@google.coma3108262011-10-10 14:08:47 +0000401 #if GR_DEBUG
402 GrVertexLayout withCoverage = tcMask | kCoverage_VertexLayoutBit;
403 #endif
404 GrAssert(-1 == VertexColorOffset(withCoverage));
405 GrAssert(2*sizeof(GrPoint) == VertexCoverageOffset(withCoverage));
406 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withCoverage));
407 #if GR_DEBUG
408 GrVertexLayout withCoverageAndColor = tcMask | kCoverage_VertexLayoutBit |
409 kColor_VertexLayoutBit;
410 #endif
411 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withCoverageAndColor));
412 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexCoverageOffset(withCoverageAndColor));
413 GrAssert(2*sizeof(GrPoint) + 2 * sizeof(GrColor) == VertexSize(withCoverageAndColor));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000414 }
bsalomon@google.com35ff3842011-12-15 16:58:19 +0000415 GrAssert(gTexCoordMasks[t] == tcMask);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000416 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000417
tomhudson@google.com93813632011-10-27 20:21:16 +0000418 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000419 int colorOffset;
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000420 int edgeOffset;
bsalomon@google.coma3108262011-10-10 14:08:47 +0000421 int coverageOffset;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000422 int size;
tomhudson@google.com93813632011-10-27 20:21:16 +0000423 size = VertexSizeAndOffsetsByStage(tcMask,
424 stageOffsets, &colorOffset,
bsalomon@google.coma3108262011-10-10 14:08:47 +0000425 &coverageOffset, &edgeOffset);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000426 GrAssert(2*sizeof(GrPoint) == size);
427 GrAssert(-1 == colorOffset);
bsalomon@google.coma3108262011-10-10 14:08:47 +0000428 GrAssert(-1 == coverageOffset);
bsalomon@google.comaeb21602011-08-30 18:13:44 +0000429 GrAssert(-1 == edgeOffset);
tomhudson@google.com93813632011-10-27 20:21:16 +0000430 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000431 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
432 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
433 }
434 }
435 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000436}
437
438////////////////////////////////////////////////////////////////////////////////
439
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000440#define DEBUG_INVAL_BUFFER 0xdeadcafe
441#define DEBUG_INVAL_START_IDX -1
442
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000443GrDrawTarget::GrDrawTarget() : fClip(NULL) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000444#if GR_DEBUG
445 VertexLayoutUnitTest();
446#endif
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000447 fDrawState = &fDefaultDrawState;
448 // We assume that fDrawState always owns a ref to the object it points at.
449 fDefaultDrawState.ref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000450 GeometrySrcState& geoSrc = fGeoSrcStateStack.push_back();
reed@google.comac10a2d2010-12-22 21:39:39 +0000451#if GR_DEBUG
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000452 geoSrc.fVertexCount = DEBUG_INVAL_START_IDX;
453 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
454 geoSrc.fIndexCount = DEBUG_INVAL_START_IDX;
455 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
reed@google.comac10a2d2010-12-22 21:39:39 +0000456#endif
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000457 geoSrc.fVertexSrc = kNone_GeometrySrcType;
458 geoSrc.fIndexSrc = kNone_GeometrySrcType;
459}
460
461GrDrawTarget::~GrDrawTarget() {
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000462 GrAssert(1 == fGeoSrcStateStack.count());
463 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
464 GrAssert(kNone_GeometrySrcType == geoSrc.fIndexSrc);
465 GrAssert(kNone_GeometrySrcType == geoSrc.fVertexSrc);
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000466 fDrawState->unref();
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000467}
468
469void GrDrawTarget::releaseGeometry() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000470 int popCnt = fGeoSrcStateStack.count() - 1;
471 while (popCnt) {
472 this->popGeometrySource();
473 --popCnt;
474 }
bsalomon@google.com4a018bb2011-10-28 19:50:21 +0000475 this->resetVertexSource();
476 this->resetIndexSource();
reed@google.comac10a2d2010-12-22 21:39:39 +0000477}
478
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000479void GrDrawTarget::setClip(const GrClipData* clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000480 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000481 fClip = clip;
482}
483
robertphillips@google.combeb1af72012-07-26 18:52:16 +0000484const GrClipData* GrDrawTarget::getClip() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000485 return fClip;
486}
487
bsalomon@google.coma5d056a2012-03-27 15:59:58 +0000488void GrDrawTarget::setDrawState(GrDrawState* drawState) {
489 GrAssert(NULL != fDrawState);
490 if (NULL == drawState) {
491 drawState = &fDefaultDrawState;
492 }
493 if (fDrawState != drawState) {
494 fDrawState->unref();
495 drawState->ref();
496 fDrawState = drawState;
497 }
498}
499
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000500bool GrDrawTarget::reserveVertexSpace(GrVertexLayout vertexLayout,
501 int vertexCount,
502 void** vertices) {
503 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
504 bool acquired = false;
505 if (vertexCount > 0) {
506 GrAssert(NULL != vertices);
507 this->releasePreviousVertexSource();
508 geoSrc.fVertexSrc = kNone_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000509
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000510 acquired = this->onReserveVertexSpace(vertexLayout,
511 vertexCount,
512 vertices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000513 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000514 if (acquired) {
515 geoSrc.fVertexSrc = kReserved_GeometrySrcType;
516 geoSrc.fVertexCount = vertexCount;
517 geoSrc.fVertexLayout = vertexLayout;
518 } else if (NULL != vertices) {
519 *vertices = NULL;
520 }
521 return acquired;
522}
523
524bool GrDrawTarget::reserveIndexSpace(int indexCount,
525 void** indices) {
526 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
527 bool acquired = false;
528 if (indexCount > 0) {
529 GrAssert(NULL != indices);
530 this->releasePreviousIndexSource();
531 geoSrc.fIndexSrc = kNone_GeometrySrcType;
532
533 acquired = this->onReserveIndexSpace(indexCount, indices);
534 }
535 if (acquired) {
536 geoSrc.fIndexSrc = kReserved_GeometrySrcType;
537 geoSrc.fIndexCount = indexCount;
538 } else if (NULL != indices) {
539 *indices = NULL;
540 }
541 return acquired;
542
reed@google.comac10a2d2010-12-22 21:39:39 +0000543}
544
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000545bool GrDrawTarget::StageUsesTexCoords(GrVertexLayout layout, int stage) {
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000546 return SkToBool(layout & gStageTexCoordMasks[stage]);
tomhudson@google.comb213ed82012-06-25 15:22:12 +0000547}
548
bsalomon@google.come3d70952012-03-13 12:40:53 +0000549bool GrDrawTarget::reserveVertexAndIndexSpace(GrVertexLayout vertexLayout,
550 int vertexCount,
551 int indexCount,
552 void** vertices,
553 void** indices) {
bsalomon@google.com97805382012-03-13 14:32:07 +0000554 this->willReserveVertexAndIndexSpace(vertexLayout, vertexCount, indexCount);
bsalomon@google.come3d70952012-03-13 12:40:53 +0000555 if (vertexCount) {
556 if (!this->reserveVertexSpace(vertexLayout, vertexCount, vertices)) {
557 if (indexCount) {
558 this->resetIndexSource();
559 }
560 return false;
561 }
562 }
563 if (indexCount) {
564 if (!this->reserveIndexSpace(indexCount, indices)) {
565 if (vertexCount) {
566 this->resetVertexSource();
567 }
568 return false;
569 }
570 }
571 return true;
572}
573
reed@google.comac10a2d2010-12-22 21:39:39 +0000574bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
575 int32_t* vertexCount,
576 int32_t* indexCount) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000577 if (NULL != vertexCount) {
578 *vertexCount = -1;
579 }
580 if (NULL != indexCount) {
581 *indexCount = -1;
582 }
583 return false;
584}
585
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000586void GrDrawTarget::releasePreviousVertexSource() {
587 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
588 switch (geoSrc.fVertexSrc) {
589 case kNone_GeometrySrcType:
590 break;
591 case kArray_GeometrySrcType:
592 this->releaseVertexArray();
593 break;
594 case kReserved_GeometrySrcType:
595 this->releaseReservedVertexSpace();
596 break;
597 case kBuffer_GeometrySrcType:
598 geoSrc.fVertexBuffer->unref();
599#if GR_DEBUG
600 geoSrc.fVertexBuffer = (GrVertexBuffer*)DEBUG_INVAL_BUFFER;
601#endif
602 break;
603 default:
604 GrCrash("Unknown Vertex Source Type.");
605 break;
606 }
607}
608
609void GrDrawTarget::releasePreviousIndexSource() {
610 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
611 switch (geoSrc.fIndexSrc) {
612 case kNone_GeometrySrcType: // these two don't require
613 break;
614 case kArray_GeometrySrcType:
615 this->releaseIndexArray();
616 break;
617 case kReserved_GeometrySrcType:
618 this->releaseReservedIndexSpace();
619 break;
620 case kBuffer_GeometrySrcType:
621 geoSrc.fIndexBuffer->unref();
622#if GR_DEBUG
623 geoSrc.fIndexBuffer = (GrIndexBuffer*)DEBUG_INVAL_BUFFER;
624#endif
625 break;
626 default:
627 GrCrash("Unknown Index Source Type.");
628 break;
629 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000630}
631
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000632void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
633 const void* vertexArray,
634 int vertexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000635 this->releasePreviousVertexSource();
636 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
637 geoSrc.fVertexSrc = kArray_GeometrySrcType;
638 geoSrc.fVertexLayout = vertexLayout;
639 geoSrc.fVertexCount = vertexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000640 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000641}
642
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000643void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
644 int indexCount) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000645 this->releasePreviousIndexSource();
646 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
647 geoSrc.fIndexSrc = kArray_GeometrySrcType;
648 geoSrc.fIndexCount = indexCount;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000649 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000650}
651
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000652void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
653 const GrVertexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000654 this->releasePreviousVertexSource();
655 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
656 geoSrc.fVertexSrc = kBuffer_GeometrySrcType;
657 geoSrc.fVertexBuffer = buffer;
658 buffer->ref();
659 geoSrc.fVertexLayout = vertexLayout;
reed@google.comac10a2d2010-12-22 21:39:39 +0000660}
661
662void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000663 this->releasePreviousIndexSource();
664 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
665 geoSrc.fIndexSrc = kBuffer_GeometrySrcType;
666 geoSrc.fIndexBuffer = buffer;
667 buffer->ref();
reed@google.comac10a2d2010-12-22 21:39:39 +0000668}
669
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000670void GrDrawTarget::resetVertexSource() {
671 this->releasePreviousVertexSource();
672 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
673 geoSrc.fVertexSrc = kNone_GeometrySrcType;
674}
675
676void GrDrawTarget::resetIndexSource() {
677 this->releasePreviousIndexSource();
678 GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
679 geoSrc.fIndexSrc = kNone_GeometrySrcType;
680}
681
682void GrDrawTarget::pushGeometrySource() {
683 this->geometrySourceWillPush();
684 GeometrySrcState& newState = fGeoSrcStateStack.push_back();
685 newState.fIndexSrc = kNone_GeometrySrcType;
686 newState.fVertexSrc = kNone_GeometrySrcType;
687#if GR_DEBUG
688 newState.fVertexCount = ~0;
689 newState.fVertexBuffer = (GrVertexBuffer*)~0;
690 newState.fIndexCount = ~0;
691 newState.fIndexBuffer = (GrIndexBuffer*)~0;
692#endif
693}
694
695void GrDrawTarget::popGeometrySource() {
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000696 // if popping last element then pops are unbalanced with pushes
697 GrAssert(fGeoSrcStateStack.count() > 1);
698
699 this->geometrySourceWillPop(fGeoSrcStateStack.fromBack(1));
700 this->releasePreviousVertexSource();
701 this->releasePreviousIndexSource();
702 fGeoSrcStateStack.pop_back();
703}
704
705////////////////////////////////////////////////////////////////////////////////
706
bsalomon@google.come8262622011-11-07 02:30:51 +0000707bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
708 int startIndex, int vertexCount,
709 int indexCount) const {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000710 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000711#if GR_DEBUG
bsalomon@google.come8262622011-11-07 02:30:51 +0000712 const GeometrySrcState& geoSrc = fGeoSrcStateStack.back();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000713 int maxVertex = startVertex + vertexCount;
714 int maxValidVertex;
715 switch (geoSrc.fVertexSrc) {
716 case kNone_GeometrySrcType:
bsalomon@google.come8262622011-11-07 02:30:51 +0000717 GrCrash("Attempting to draw without vertex src.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000718 case kReserved_GeometrySrcType: // fallthrough
719 case kArray_GeometrySrcType:
720 maxValidVertex = geoSrc.fVertexCount;
721 break;
722 case kBuffer_GeometrySrcType:
bsalomon@google.comf3ccda72012-07-11 14:56:33 +0000723 maxValidVertex = geoSrc.fVertexBuffer->sizeInBytes() / VertexSize(geoSrc.fVertexLayout);
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000724 break;
725 }
726 if (maxVertex > maxValidVertex) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000727 GrCrash("Drawing outside valid vertex range.");
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000728 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000729 if (indexCount > 0) {
730 int maxIndex = startIndex + indexCount;
731 int maxValidIndex;
732 switch (geoSrc.fIndexSrc) {
733 case kNone_GeometrySrcType:
734 GrCrash("Attempting to draw indexed geom without index src.");
735 case kReserved_GeometrySrcType: // fallthrough
736 case kArray_GeometrySrcType:
737 maxValidIndex = geoSrc.fIndexCount;
738 break;
739 case kBuffer_GeometrySrcType:
740 maxValidIndex = geoSrc.fIndexBuffer->sizeInBytes() / sizeof(uint16_t);
741 break;
742 }
743 if (maxIndex > maxValidIndex) {
744 GrCrash("Index reads outside valid index range.");
745 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000746 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000747
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000748 GrAssert(NULL != drawState.getRenderTarget());
749 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
750 if (drawState.isStageEnabled(s)) {
751 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
752 int numTextures = stage->numTextures();
753 for (int t = 0; t < numTextures; ++t) {
754 GrTexture* texture = stage->texture(t);
755 GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
756 }
bsalomon@google.comb4725b42012-03-30 17:24:17 +0000757 }
758 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000759#endif
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000760 if (NULL == drawState.getRenderTarget()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000761 return false;
762 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000763 if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000764 if (kOne_GrBlendCoeff != drawState.getSrcBlendCoeff() ||
765 kZero_GrBlendCoeff != drawState.getDstBlendCoeff()) {
bsalomon@google.com0ba52fc2011-11-10 22:16:06 +0000766 return false;
767 }
768 }
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000769 // We don't support using unpremultiplied textures with bilerp. Alpha-multiplication is not
770 // distributive with respect to filtering. We'd have to alpha-mul each texel before filtering.
771 // Until Skia itself supports unpremultiplied configs there is no pressure to implement this.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000772 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000773 if (drawState.isStageEnabled(s)) {
774 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
775 int numTextures = stage->numTextures();
776 for (int t = 0; t < numTextures; ++t) {
777 GrTexture* texture = stage->texture(t);
778 GrAssert(NULL != texture);
779 if (GrPixelConfigIsUnpremultiplied(texture->config()) &&
780 drawState.getSampler(s).getTextureParams().isBilerp()) {
781 return false;
782 }
783 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000784 }
785 }
bsalomon@google.come8262622011-11-07 02:30:51 +0000786 return true;
787}
788
789void GrDrawTarget::drawIndexed(GrPrimitiveType type, int startVertex,
790 int startIndex, int vertexCount,
791 int indexCount) {
792 if (indexCount > 0 &&
793 this->checkDraw(type, startVertex, startIndex,
794 vertexCount, indexCount)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000795 this->onDrawIndexed(type, startVertex, startIndex,
796 vertexCount, indexCount);
797 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000798}
799
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000800void GrDrawTarget::drawNonIndexed(GrPrimitiveType type,
801 int startVertex,
802 int vertexCount) {
bsalomon@google.come8262622011-11-07 02:30:51 +0000803 if (vertexCount > 0 &&
804 this->checkDraw(type, startVertex, -1, vertexCount, -1)) {
bsalomon@google.com82145872011-08-23 14:32:40 +0000805 this->onDrawNonIndexed(type, startVertex, vertexCount);
806 }
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000807}
808
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000809void GrDrawTarget::stencilPath(const GrPath* path, GrPathFill fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000810 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon@google.comded4f4b2012-06-28 18:48:06 +0000811 GrAssert(NULL != path);
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000812 GrAssert(fCaps.fPathStencilingSupport);
813 GrAssert(kHairLine_GrPathFill != fill);
814 GrAssert(!GrIsFillInverted(fill));
815 this->onStencilPath(path, fill);
816}
817
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000818////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000819
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000820// Some blend modes allow folding a partial coverage value into the color's
821// alpha channel, while others will blend incorrectly.
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000822bool GrDrawTarget::canTweakAlphaForCoverage() const {
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000823 /**
824 * The fractional coverage is f
825 * The src and dst coeffs are Cs and Cd
826 * The dst and src colors are S and D
827 * We want the blend to compute: f*Cs*S + (f*Cd + (1-f))D
828 * By tweaking the source color's alpha we're replacing S with S'=fS. It's
829 * obvious that that first term will always be ok. The second term can be
830 * rearranged as [1-(1-Cd)f]D. By substituing in the various possbilities
831 * for Cd we find that only 1, ISA, and ISC produce the correct depth
832 * coeffecient in terms of S' and D.
833 */
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000834 GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
bsalomon@google.com47059542012-06-06 20:51:20 +0000835 return kOne_GrBlendCoeff == dstCoeff ||
836 kISA_GrBlendCoeff == dstCoeff ||
837 kISC_GrBlendCoeff == dstCoeff;
bsalomon@google.comd46e2422011-09-23 17:40:07 +0000838}
839
bsalomon@google.come79c8152012-03-29 19:07:12 +0000840bool GrDrawTarget::srcAlphaWillBeOne(GrVertexLayout layout) const {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000841 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000842
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000843 // Check if per-vertex or constant color may have partial alpha
bsalomon@google.com471d4712011-08-23 15:45:25 +0000844 if ((layout & kColor_VertexLayoutBit) ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000845 0xff != GrColorUnpackA(drawState.getColor())) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000846 return false;
847 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000848 // Check if color filter could introduce an alpha
849 // (TODO: Consider being more aggressive with regards to detecting 0xff
850 // final alpha from color filter).
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000851 if (SkXfermode::kDst_Mode != drawState.getColorFilterMode()) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000852 return false;
853 }
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000854 // Check if a color stage could create a partial alpha
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000855 for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000856 if (this->isStageEnabled(s)) {
bsalomon@google.comcddaf342012-07-30 13:09:05 +0000857 const GrCustomStage* stage = drawState.getSampler(s).getCustomStage();
858 // FIXME: The param indicates whether the texture is opaque or not. However, the stage
859 // already controls its textures. It really needs to know whether the incoming color
860 // (from a uni, per-vertex colors, or previous stage) is opaque or not.
861 if (!stage->isOpaque(true)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000862 return false;
863 }
864 }
865 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000866 return true;
867}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000868
bsalomon@google.come79c8152012-03-29 19:07:12 +0000869namespace {
870GrVertexLayout default_blend_opts_vertex_layout() {
871 GrVertexLayout layout = 0;
bsalomon@google.come79c8152012-03-29 19:07:12 +0000872 return layout;
873}
874}
875
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000876GrDrawTarget::BlendOptFlags
877GrDrawTarget::getBlendOpts(bool forceCoverage,
878 GrBlendCoeff* srcCoeff,
879 GrBlendCoeff* dstCoeff) const {
880
bsalomon@google.come79c8152012-03-29 19:07:12 +0000881 GrVertexLayout layout;
882 if (kNone_GeometrySrcType == this->getGeomSrc().fVertexSrc) {
883 layout = default_blend_opts_vertex_layout();
884 } else {
885 layout = this->getVertexLayout();
886 }
887
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000888 const GrDrawState& drawState = this->getDrawState();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000889
890 GrBlendCoeff bogusSrcCoeff, bogusDstCoeff;
891 if (NULL == srcCoeff) {
892 srcCoeff = &bogusSrcCoeff;
893 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000894 *srcCoeff = drawState.getSrcBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000895
896 if (NULL == dstCoeff) {
897 dstCoeff = &bogusDstCoeff;
898 }
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000899 *dstCoeff = drawState.getDstBlendCoeff();
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000900
901 // We don't ever expect source coeffecients to reference the source
bsalomon@google.com47059542012-06-06 20:51:20 +0000902 GrAssert(kSA_GrBlendCoeff != *srcCoeff &&
903 kISA_GrBlendCoeff != *srcCoeff &&
904 kSC_GrBlendCoeff != *srcCoeff &&
905 kISC_GrBlendCoeff != *srcCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000906 // same for dst
bsalomon@google.com47059542012-06-06 20:51:20 +0000907 GrAssert(kDA_GrBlendCoeff != *dstCoeff &&
908 kIDA_GrBlendCoeff != *dstCoeff &&
909 kDC_GrBlendCoeff != *dstCoeff &&
910 kIDC_GrBlendCoeff != *dstCoeff);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000911
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000912 if (drawState.isColorWriteDisabled()) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000913 *srcCoeff = kZero_GrBlendCoeff;
914 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000915 }
916
bsalomon@google.come79c8152012-03-29 19:07:12 +0000917 bool srcAIsOne = this->srcAlphaWillBeOne(layout);
bsalomon@google.com47059542012-06-06 20:51:20 +0000918 bool dstCoeffIsOne = kOne_GrBlendCoeff == *dstCoeff ||
919 (kSA_GrBlendCoeff == *dstCoeff && srcAIsOne);
920 bool dstCoeffIsZero = kZero_GrBlendCoeff == *dstCoeff ||
921 (kISA_GrBlendCoeff == *dstCoeff && srcAIsOne);
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000922
923
924 // When coeffs are (0,1) there is no reason to draw at all, unless
925 // stenciling is enabled. Having color writes disabled is effectively
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000926 // (0,1). The same applies when coverage is known to be 0.
bsalomon@google.com47059542012-06-06 20:51:20 +0000927 if ((kZero_GrBlendCoeff == *srcCoeff && dstCoeffIsOne) ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000928 (!(layout & kCoverage_VertexLayoutBit) &&
929 0 == drawState.getCoverage())) {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000930 if (drawState.getStencil().doesWrite()) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000931 return kDisableBlend_BlendOptFlag |
932 kEmitTransBlack_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000933 } else {
934 return kSkipDraw_BlendOptFlag;
935 }
936 }
937
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000938 // check for coverage due to constant coverage, per-vertex coverage,
939 // edge aa or coverage texture stage
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000940 bool hasCoverage = forceCoverage ||
bsalomon@google.com2401ae82012-01-17 21:03:05 +0000941 0xffffffff != drawState.getCoverage() ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000942 (layout & kCoverage_VertexLayoutBit) ||
943 (layout & kEdge_VertexLayoutBit);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +0000944 for (int s = drawState.getFirstCoverageStage();
tomhudson@google.com93813632011-10-27 20:21:16 +0000945 !hasCoverage && s < GrDrawState::kNumStages;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000946 ++s) {
tomhudson@google.comf13f5882012-06-25 17:27:28 +0000947 if (this->isStageEnabled(s)) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000948 hasCoverage = true;
949 }
950 }
951
952 // if we don't have coverage we can check whether the dst
953 // has to read at all. If not, we'll disable blending.
954 if (!hasCoverage) {
955 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000956 if (kOne_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000957 // if there is no coverage and coeffs are (1,0) then we
958 // won't need to read the dst at all, it gets replaced by src
959 return kDisableBlend_BlendOptFlag;
bsalomon@google.com47059542012-06-06 20:51:20 +0000960 } else if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000961 // if the op is "clear" then we don't need to emit a color
962 // or blend, just write transparent black into the dst.
bsalomon@google.com47059542012-06-06 20:51:20 +0000963 *srcCoeff = kOne_GrBlendCoeff;
964 *dstCoeff = kZero_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000965 return kDisableBlend_BlendOptFlag |
966 kEmitTransBlack_BlendOptFlag;
967 }
968 }
969 } else {
970 // check whether coverage can be safely rolled into alpha
971 // of if we can skip color computation and just emit coverage
972 if (this->canTweakAlphaForCoverage()) {
973 return kCoverageAsAlpha_BlendOptFlag;
974 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000975 if (dstCoeffIsZero) {
bsalomon@google.com47059542012-06-06 20:51:20 +0000976 if (kZero_GrBlendCoeff == *srcCoeff) {
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000977 // the source color is not included in the blend
978 // the dst coeff is effectively zero so blend works out to:
979 // (c)(0)D + (1-c)D = (1-c)D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000980 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000981 return kEmitCoverage_BlendOptFlag;
982 } else if (srcAIsOne) {
983 // the dst coeff is effectively zero so blend works out to:
984 // cS + (c)(0)D + (1-c)D = cS + (1-c)D.
985 // If Sa is 1 then we can replace Sa with c
986 // and set dst coeff to 1-Sa.
bsalomon@google.com47059542012-06-06 20:51:20 +0000987 *dstCoeff = kISA_GrBlendCoeff;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000988 return kCoverageAsAlpha_BlendOptFlag;
989 }
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000990 } else if (dstCoeffIsOne) {
991 // the dst coeff is effectively one so blend works out to:
992 // cS + (c)(1)D + (1-c)D = cS + D.
bsalomon@google.com47059542012-06-06 20:51:20 +0000993 *dstCoeff = kOne_GrBlendCoeff;
bsalomon@google.comdafde9e2012-01-11 18:45:39 +0000994 return kCoverageAsAlpha_BlendOptFlag;
bsalomon@google.com86c1f712011-10-12 14:54:26 +0000995 }
996 }
997 return kNone_BlendOpt;
998}
999
1000bool GrDrawTarget::willUseHWAALines() const {
bsalomon@google.com471d4712011-08-23 15:45:25 +00001001 // there is a conflict between using smooth lines and our use of
1002 // premultiplied alpha. Smooth lines tweak the incoming alpha value
1003 // but not in a premul-alpha way. So we only use them when our alpha
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001004 // is 0xff and tweaking the color for partial coverage is OK
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001005 if (!fCaps.fHWAALineSupport ||
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001006 !this->getDrawState().isHWAntialiasState()) {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001007 return false;
1008 }
1009 BlendOptFlags opts = this->getBlendOpts();
1010 return (kDisableBlend_BlendOptFlag & opts) &&
1011 (kCoverageAsAlpha_BlendOptFlag & opts);
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001012}
1013
1014bool GrDrawTarget::canApplyCoverage() const {
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001015 // we can correctly apply coverage if a) we have dual source blending
1016 // or b) one of our blend optimizations applies.
bsalomon@google.comd46e2422011-09-23 17:40:07 +00001017 return this->getCaps().fDualSourceBlendingSupport ||
bsalomon@google.com86c1f712011-10-12 14:54:26 +00001018 kNone_BlendOpt != this->getBlendOpts(true);
bsalomon@google.com471d4712011-08-23 15:45:25 +00001019}
1020
bsalomon@google.com934c5702012-03-20 21:17:58 +00001021////////////////////////////////////////////////////////////////////////////////
1022
1023void GrDrawTarget::drawIndexedInstances(GrPrimitiveType type,
1024 int instanceCount,
1025 int verticesPerInstance,
1026 int indicesPerInstance) {
1027 if (!verticesPerInstance || !indicesPerInstance) {
1028 return;
1029 }
1030
1031 int instancesPerDraw = this->indexCountInCurrentSource() /
1032 indicesPerInstance;
1033 if (!instancesPerDraw) {
1034 return;
1035 }
1036
1037 instancesPerDraw = GrMin(instanceCount, instancesPerDraw);
1038 int startVertex = 0;
1039 while (instanceCount) {
1040 this->drawIndexed(type,
1041 startVertex,
1042 0,
1043 verticesPerInstance * instancesPerDraw,
1044 indicesPerInstance * instancesPerDraw);
1045 startVertex += verticesPerInstance;
1046 instanceCount -= instancesPerDraw;
1047 }
1048}
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001049
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001050////////////////////////////////////////////////////////////////////////////////
1051
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001052void GrDrawTarget::drawRect(const GrRect& rect,
1053 const GrMatrix* matrix,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001054 const GrRect* srcRects[],
1055 const GrMatrix* srcMatrices[]) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001056 GrVertexLayout layout = GetRectVertexLayout(srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001057
1058 AutoReleaseGeometry geo(this, layout, 4, 0);
bsalomon@google.com6513cd02011-08-05 20:12:30 +00001059 if (!geo.succeeded()) {
1060 GrPrintf("Failed to get space for vertices!\n");
1061 return;
1062 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001063
bsalomon@google.com3d0835b2011-12-08 16:12:03 +00001064 SetRectVertices(rect, matrix, srcRects,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001065 srcMatrices, layout, geo.vertices());
1066
bsalomon@google.com47059542012-06-06 20:51:20 +00001067 drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001068}
1069
bsalomon@google.come3d32162012-07-20 13:37:06 +00001070GrVertexLayout GrDrawTarget::GetRectVertexLayout(const GrRect* srcRects[]) {
1071 if (NULL == srcRects) {
1072 return 0;
1073 }
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001074
bsalomon@google.come3d32162012-07-20 13:37:06 +00001075 GrVertexLayout layout = 0;
tomhudson@google.com93813632011-10-27 20:21:16 +00001076 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001077 int numTC = 0;
bsalomon@google.come3d32162012-07-20 13:37:06 +00001078 if (NULL != srcRects[i]) {
1079 layout |= StageTexCoordVertexLayoutBit(i, numTC);
1080 ++numTC;
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001081 }
1082 }
1083 return layout;
1084}
bsalomon@google.comdea2f8d2011-08-01 15:51:05 +00001085
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001086void GrDrawTarget::SetRectVertices(const GrRect& rect,
1087 const GrMatrix* matrix,
1088 const GrRect* srcRects[],
1089 const GrMatrix* srcMatrices[],
1090 GrVertexLayout layout,
1091 void* vertices) {
1092#if GR_DEBUG
1093 // check that the layout and srcRects agree
tomhudson@google.com93813632011-10-27 20:21:16 +00001094 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001095 if (VertexTexCoordsForStage(i, layout) >= 0) {
1096 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
1097 } else {
1098 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
1099 }
1100 }
1101#endif
1102
tomhudson@google.com93813632011-10-27 20:21:16 +00001103 int stageOffsets[GrDrawState::kNumStages];
bsalomon@google.coma3108262011-10-10 14:08:47 +00001104 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets,
1105 NULL, NULL, NULL);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001106
bsalomon@google.coma3108262011-10-10 14:08:47 +00001107 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001108 rect.fRight, rect.fBottom,
1109 vsize);
1110 if (NULL != matrix) {
1111 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
1112 }
1113
tomhudson@google.com93813632011-10-27 20:21:16 +00001114 for (int i = 0; i < GrDrawState::kNumStages; ++i) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001115 if (stageOffsets[i] > 0) {
bsalomon@google.coma3108262011-10-10 14:08:47 +00001116 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001117 stageOffsets[i]);
1118 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
bsalomon@google.coma3108262011-10-10 14:08:47 +00001119 srcRects[i]->fRight, srcRects[i]->fBottom,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +00001120 vsize);
1121 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
1122 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
1123 }
1124 }
1125 }
1126}
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.come3d32162012-07-20 13:37:06 +00001166GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target,
1167 uint32_t explicitCoordStageMask) {
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001168 GrAssert(NULL != target);
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001169 GrDrawState* drawState = target->drawState();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001170
1171 fDrawTarget = target;
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001172 fViewMatrix = drawState->getViewMatrix();
bsalomon@google.come3d32162012-07-20 13:37:06 +00001173 fRestoreMask = 0;
1174 GrMatrix invVM;
1175 bool inverted = false;
1176
1177 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
1178 if (!(explicitCoordStageMask & (1 << s)) && drawState->isStageEnabled(s)) {
1179 if (!inverted && !fViewMatrix.invert(&invVM)) {
1180 // sad trombone sound
1181 fDrawTarget = NULL;
1182 return;
1183 } else {
1184 inverted = true;
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001185 }
bsalomon@google.come3d32162012-07-20 13:37:06 +00001186 fRestoreMask |= (1 << s);
1187 GrSamplerState* sampler = drawState->sampler(s);
1188 fSamplerMatrices[s] = sampler->getMatrix();
1189 sampler->preConcatMatrix(invVM);
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001190 }
1191 }
bsalomon@google.comb3e40c02012-03-20 15:36:32 +00001192 drawState->viewMatrix()->reset();
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001193}
1194
1195GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +00001196 GrDrawState* drawState = fDrawTarget->drawState();
1197 drawState->setViewMatrix(fViewMatrix);
tomhudson@google.com93813632011-10-27 20:21:16 +00001198 for (int s = 0; s < GrDrawState::kNumStages; ++s) {
bsalomon@google.come3d32162012-07-20 13:37:06 +00001199 if (fRestoreMask & (1 << s)) {
bsalomon@google.comaa814fe2011-12-12 18:45:07 +00001200 *drawState->sampler(s)->matrix() = fSamplerMatrices[s];
bsalomon@google.com7ac249b2011-06-14 18:46:24 +00001201 }
1202 }
1203}
1204
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001205////////////////////////////////////////////////////////////////////////////////
1206
1207GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry(
1208 GrDrawTarget* target,
1209 GrVertexLayout vertexLayout,
1210 int vertexCount,
1211 int indexCount) {
1212 fTarget = NULL;
1213 this->set(target, vertexLayout, vertexCount, indexCount);
1214}
1215
1216GrDrawTarget::AutoReleaseGeometry::AutoReleaseGeometry() {
1217 fTarget = NULL;
1218}
1219
1220GrDrawTarget::AutoReleaseGeometry::~AutoReleaseGeometry() {
1221 this->reset();
1222}
1223
1224bool GrDrawTarget::AutoReleaseGeometry::set(GrDrawTarget* target,
1225 GrVertexLayout vertexLayout,
1226 int vertexCount,
1227 int indexCount) {
1228 this->reset();
1229 fTarget = target;
1230 bool success = true;
1231 if (NULL != fTarget) {
1232 fTarget = target;
bsalomon@google.come3d70952012-03-13 12:40:53 +00001233 success = target->reserveVertexAndIndexSpace(vertexLayout,
1234 vertexCount,
1235 indexCount,
1236 &fVertices,
1237 &fIndices);
1238 if (!success) {
1239 fTarget = NULL;
1240 this->reset();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001241 }
1242 }
1243 GrAssert(success == (NULL != fTarget));
1244 return success;
1245}
1246
1247void GrDrawTarget::AutoReleaseGeometry::reset() {
1248 if (NULL != fTarget) {
1249 if (NULL != fVertices) {
1250 fTarget->resetVertexSource();
1251 }
1252 if (NULL != fIndices) {
1253 fTarget->resetIndexSource();
1254 }
1255 fTarget = NULL;
1256 }
bsalomon@google.comcb0c5ab2011-06-29 17:48:17 +00001257 fVertices = NULL;
1258 fIndices = NULL;
bsalomon@google.com25fb21f2011-06-21 18:17:25 +00001259}
1260
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001261void GrDrawTarget::Caps::print() const {
1262 static const char* gNY[] = {"NO", "YES"};
1263 GrPrintf("8 Bit Palette Support : %s\n", gNY[f8BitPaletteSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001264 GrPrintf("NPOT Texture Tile Support : %s\n", gNY[fNPOTTextureTileSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001265 GrPrintf("Two Sided Stencil Support : %s\n", gNY[fTwoSidedStencilSupport]);
1266 GrPrintf("Stencil Wrap Ops Support : %s\n", gNY[fStencilWrapOpsSupport]);
1267 GrPrintf("HW AA Lines Support : %s\n", gNY[fHWAALineSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001268 GrPrintf("Shader Derivative Support : %s\n", gNY[fShaderDerivativeSupport]);
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +00001269 GrPrintf("Geometry Shader Support : %s\n", gNY[fGeometryShaderSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001270 GrPrintf("FSAA Support : %s\n", gNY[fFSAASupport]);
1271 GrPrintf("Dual Source Blending Support: %s\n", gNY[fDualSourceBlendingSupport]);
1272 GrPrintf("Buffer Lock Support : %s\n", gNY[fBufferLockSupport]);
bsalomon@google.com18c9c192011-09-22 21:01:31 +00001273 GrPrintf("Max Texture Size : %d\n", fMaxTextureSize);
1274 GrPrintf("Max Render Target Size : %d\n", fMaxRenderTargetSize);
1275}
1276
robertphillips@google.comec05eaa2012-04-27 18:59:52 +00001277