blob: b5f92598e1318f70d0f10c0b1273e8178ed23803 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "GrDrawTarget.h"
19#include "GrGpuVertex.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000020#include "GrTexture.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000021
junov@google.com6acc9b32011-05-16 18:32:07 +000022namespace {
23
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000024// recursive helper for creating mask with all the tex coord bits set for
25// one stage
26template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000027int stage_mask_recur(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000028 return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000029 stage_mask_recur<N+1>(stage);
30}
junov@google.com6acc9b32011-05-16 18:32:07 +000031template<>
reed@google.comd728f6e2011-01-13 20:02:47 +000032int stage_mask_recur<GrDrawTarget::kNumStages>(int) { return 0; }
reed@google.comac10a2d2010-12-22 21:39:39 +000033
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000034// mask of all tex coord indices for one stage
junov@google.com6acc9b32011-05-16 18:32:07 +000035int stage_tex_coord_mask(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000036 return stage_mask_recur<0>(stage);
reed@google.comac10a2d2010-12-22 21:39:39 +000037}
38
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000039// mask of all bits relevant to one stage
junov@google.com6acc9b32011-05-16 18:32:07 +000040int stage_mask(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000041 return stage_tex_coord_mask(stage) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000042 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage);
43}
44
45// recursive helper for creating mask of with all bits set relevant to one
46// texture coordinate index
47template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000048int tex_coord_mask_recur(int texCoordIdx) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000049 return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000050 tex_coord_mask_recur<N+1>(texCoordIdx);
51}
junov@google.com6acc9b32011-05-16 18:32:07 +000052template<>
reed@google.comd728f6e2011-01-13 20:02:47 +000053int tex_coord_mask_recur<GrDrawTarget::kMaxTexCoords>(int) { return 0; }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000054
55// mask of all bits relevant to one texture coordinate index
junov@google.com6acc9b32011-05-16 18:32:07 +000056int tex_coord_idx_mask(int texCoordIdx) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000057 return tex_coord_mask_recur<0>(texCoordIdx);
58}
59
60bool check_layout(GrVertexLayout layout) {
61 // can only have 1 or 0 bits set for each stage.
62 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
63 int stageBits = layout & stage_mask(s);
64 if (stageBits && !GrIsPow2(stageBits)) {
65 return false;
66 }
67 }
68 return true;
69}
70
junov@google.com6acc9b32011-05-16 18:32:07 +000071} //unnamed namespace
72
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000073size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
74 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +000075
76 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000077 sizeof(GrGpuTextVertex) :
78 sizeof(GrPoint);
79
80 size_t size = vecSize; // position
81 for (int t = 0; t < kMaxTexCoords; ++t) {
82 if (tex_coord_idx_mask(t) & vertexLayout) {
83 size += vecSize;
84 }
85 }
86 if (vertexLayout & kColor_VertexLayoutBit) {
87 size += sizeof(GrColor);
88 }
89 return size;
90}
91
92int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
93 GrAssert(check_layout(vertexLayout));
94 if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
reed@google.comac10a2d2010-12-22 21:39:39 +000095 return 0;
96 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
98 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000099
100 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000101 sizeof(GrGpuTextVertex) :
102 sizeof(GrPoint);
103 int offset = vecSize; // position
104 // figure out how many tex coordinates are present and precede this one.
105 for (int t = 0; t < tcIdx; ++t) {
106 if (tex_coord_idx_mask(t) & vertexLayout) {
107 offset += vecSize;
108 }
109 }
110 return offset;
111 }
112
reed@google.comac10a2d2010-12-22 21:39:39 +0000113 return -1;
114}
115
116int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000117 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000118
reed@google.comac10a2d2010-12-22 21:39:39 +0000119 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000120 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000121 sizeof(GrGpuTextVertex) :
122 sizeof(GrPoint);
123 int offset = vecSize; // position
124 // figure out how many tex coordinates are present and precede this one.
125 for (int t = 0; t < kMaxTexCoords; ++t) {
126 if (tex_coord_idx_mask(t) & vertexLayout) {
127 offset += vecSize;
128 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000129 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000130 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000131 }
132 return -1;
133}
134
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000135int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
136 int texCoordOffsetsByIdx[kMaxTexCoords],
137 int* colorOffset) {
138 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000139
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000140 GrAssert(NULL != texCoordOffsetsByIdx);
reed@google.comac10a2d2010-12-22 21:39:39 +0000141 GrAssert(NULL != colorOffset);
142
bsalomon@google.com5782d712011-01-21 21:03:59 +0000143 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000144 sizeof(GrGpuTextVertex) :
145 sizeof(GrPoint);
146 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000147
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000148 for (int t = 0; t < kMaxTexCoords; ++t) {
149 if (tex_coord_idx_mask(t) & vertexLayout) {
150 texCoordOffsetsByIdx[t] = size;
151 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000152 } else {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000153 texCoordOffsetsByIdx[t] = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000156 if (kColor_VertexLayoutBit & vertexLayout) {
157 *colorOffset = size;
158 size += sizeof(GrColor);
159 } else {
160 *colorOffset = -1;
161 }
162 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000163}
164
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000165int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
166 int texCoordOffsetsByStage[kNumStages],
167 int* colorOffset) {
168 GrAssert(check_layout(vertexLayout));
169
170 GrAssert(NULL != texCoordOffsetsByStage);
171 GrAssert(NULL != colorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000172
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000173 int texCoordOffsetsByIdx[kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000174 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
175 texCoordOffsetsByIdx,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000176 colorOffset);
177 for (int s = 0; s < kNumStages; ++s) {
178 int tcIdx;
179 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
180 texCoordOffsetsByStage[s] = 0;
181 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
182 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
183 } else {
184 texCoordOffsetsByStage[s] = -1;
185 }
186 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000187 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000188}
189
190bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
191 GrAssert(stage < kNumStages);
192 GrAssert(check_layout(vertexLayout));
193 return !!(stage_mask(stage) & vertexLayout);
194}
195
bsalomon@google.com5782d712011-01-21 21:03:59 +0000196bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000197 GrVertexLayout vertexLayout) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000198 GrAssert(coordIndex < kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000199 GrAssert(check_layout(vertexLayout));
200 return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
201}
202
203int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
204 GrAssert(stage < kNumStages);
205 GrAssert(check_layout(vertexLayout));
206 int bit = vertexLayout & stage_tex_coord_mask(stage);
207 if (bit) {
208 // figure out which set of texture coordates is used
209 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
210 // and start at bit 0.
211 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
212 return (32 - Gr_clz(bit) - 1) / kNumStages;
213 }
214 return -1;
215}
216
217void GrDrawTarget::VertexLayoutUnitTest() {
218 // not necessarily exhaustive
219 static bool run;
220 if (!run) {
221 run = true;
222 for (int s = 0; s < kNumStages; ++s) {
223
224 GrAssert(!VertexUsesStage(s, 0));
225 GrAssert(-1 == VertexStageCoordOffset(s, 0));
226 GrVertexLayout stageMask = 0;
227 for (int t = 0; t < kMaxTexCoords; ++t) {
228 stageMask |= StageTexCoordVertexLayoutBit(s,t);
229 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000230 GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000231 GrAssert(stage_tex_coord_mask(s) == stageMask);
232 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
233 GrAssert(stage_mask(s) == stageMask);
234 GrAssert(!check_layout(stageMask));
235 }
236 for (int t = 0; t < kMaxTexCoords; ++t) {
237 GrVertexLayout tcMask = 0;
238 GrAssert(!VertexUsesTexCoordIdx(t, 0));
239 for (int s = 0; s < kNumStages; ++s) {
240 tcMask |= StageTexCoordVertexLayoutBit(s,t);
241 GrAssert(VertexUsesStage(s, tcMask));
242 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
243 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
244 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
245 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
246 for (int s2 = s + 1; s2 < kNumStages; ++s2) {
247 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
248 GrAssert(!VertexUsesStage(s2, tcMask));
249 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000250
bsalomon@google.com19628322011-02-03 21:30:17 +0000251 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000252 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000253 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000254 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
255 GrAssert(VertexUsesStage(s2, posAsTex));
256 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
257 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
258 }
bsalomon@google.com19628322011-02-03 21:30:17 +0000259 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000260 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000261 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000262 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
263 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
264 }
265 GrAssert(tex_coord_idx_mask(t) == tcMask);
266 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000267
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000268 int stageOffsets[kNumStages];
269 int colorOffset;
270 int size;
271 size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset);
272 GrAssert(2*sizeof(GrPoint) == size);
273 GrAssert(-1 == colorOffset);
274 for (int s = 0; s < kNumStages; ++s) {
275 GrAssert(VertexUsesStage(s, tcMask));
276 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
277 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
278 }
279 }
280 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000281}
282
283////////////////////////////////////////////////////////////////////////////////
284
285GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000286#if GR_DEBUG
287 VertexLayoutUnitTest();
288#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000289 fReservedGeometry.fLocked = false;
290#if GR_DEBUG
291 fReservedGeometry.fVertexCount = ~0;
292 fReservedGeometry.fIndexCount = ~0;
293#endif
294 fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
295 fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
296}
297
298void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000299 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000300 fClip = clip;
301}
302
303const GrClip& GrDrawTarget::getClip() const {
304 return fClip;
305}
306
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000307void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
308 GrAssert(stage >= 0 && stage < kNumStages);
309 fCurrDrawState.fTextures[stage] = tex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000310}
311
bsalomon@google.com5782d712011-01-21 21:03:59 +0000312const GrTexture* GrDrawTarget::getTexture(int stage) const {
313 GrAssert(stage >= 0 && stage < kNumStages);
314 return fCurrDrawState.fTextures[stage];
315}
316
317GrTexture* GrDrawTarget::getTexture(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000318 GrAssert(stage >= 0 && stage < kNumStages);
319 return fCurrDrawState.fTextures[stage];
reed@google.comac10a2d2010-12-22 21:39:39 +0000320}
321
322void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
323 fCurrDrawState.fRenderTarget = target;
324}
325
bsalomon@google.com5782d712011-01-21 21:03:59 +0000326const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
327 return fCurrDrawState.fRenderTarget;
328}
329
330GrRenderTarget* GrDrawTarget::getRenderTarget() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000331 return fCurrDrawState.fRenderTarget;
332}
333
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000334void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
335 fCurrDrawState.fViewMatrix = m;
reed@google.comac10a2d2010-12-22 21:39:39 +0000336}
337
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000338void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000339 fCurrDrawState.fViewMatrix.preConcat(matrix);
340}
341
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000342void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
343 fCurrDrawState.fViewMatrix.postConcat(matrix);
344}
345
bsalomon@google.com5782d712011-01-21 21:03:59 +0000346const GrMatrix& GrDrawTarget::getViewMatrix() const {
347 return fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000348}
349
350bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000351 // Mike: Can we cache this somewhere?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000352 // Brian: Sure, do we use it often?
reed@google.comac10a2d2010-12-22 21:39:39 +0000353
354 GrMatrix inverse;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000355 if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000356 if (matrix) {
357 *matrix = inverse;
358 }
359 return true;
360 }
361 return false;
362}
363
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000364void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
365 GrAssert(stage >= 0 && stage < kNumStages);
366 fCurrDrawState.fSamplerStates[stage] = state;
367}
368
reed@google.comac10a2d2010-12-22 21:39:39 +0000369void GrDrawTarget::enableState(uint32_t bits) {
370 fCurrDrawState.fFlagBits |= bits;
371}
372
373void GrDrawTarget::disableState(uint32_t bits) {
374 fCurrDrawState.fFlagBits &= ~(bits);
375}
376
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000377void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff,
378 GrBlendCoeff dstCoeff) {
379 fCurrDrawState.fSrcBlend = srcCoeff;
380 fCurrDrawState.fDstBlend = dstCoeff;
381#if GR_DEBUG
382 switch (dstCoeff) {
383 case kDC_BlendCoeff:
384 case kIDC_BlendCoeff:
385 case kDA_BlendCoeff:
386 case kIDA_BlendCoeff:
387 GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
388 "coverage stages.\n");
389 break;
390 default:
391 break;
392 }
393 switch (srcCoeff) {
394 case kSC_BlendCoeff:
395 case kISC_BlendCoeff:
396 case kSA_BlendCoeff:
397 case kISA_BlendCoeff:
398 GrPrintf("Unexpected src blend coeff. Won't work correctly with"
399 "coverage stages.\n");
400 break;
401 default:
402 break;
403 }
404#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000405}
406
407void GrDrawTarget::setColor(GrColor c) {
408 fCurrDrawState.fColor = c;
409}
410
Scroggo97c88c22011-05-11 14:05:25 +0000411void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
412 fCurrDrawState.fColorFilterColor = c;
413 fCurrDrawState.fColorFilterXfermode = mode;
414}
415
reed@google.comac10a2d2010-12-22 21:39:39 +0000416void GrDrawTarget::setAlpha(uint8_t a) {
417 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
418}
419
420void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
421 state->fState = fCurrDrawState;
422}
423
424void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
425 fCurrDrawState = state.fState;
426}
427
428void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
429 fCurrDrawState = srcTarget.fCurrDrawState;
430}
431
432
433bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout,
434 uint32_t vertexCount,
435 uint32_t indexCount,
436 void** vertices,
437 void** indices) {
438 GrAssert(!fReservedGeometry.fLocked);
439 fReservedGeometry.fVertexCount = vertexCount;
440 fReservedGeometry.fIndexCount = indexCount;
441
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000442 fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout,
443 vertices,
444 indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000445 if (fReservedGeometry.fLocked) {
446 if (vertexCount) {
447 fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
448 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000449 } else if (NULL != vertices) {
450 *vertices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000451 }
452 if (indexCount) {
453 fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000454 } else if (NULL != indices) {
455 *indices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 }
457 }
458 return fReservedGeometry.fLocked;
459}
460
461bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
462 int32_t* vertexCount,
463 int32_t* indexCount) const {
464 GrAssert(!fReservedGeometry.fLocked);
465 if (NULL != vertexCount) {
466 *vertexCount = -1;
467 }
468 if (NULL != indexCount) {
469 *indexCount = -1;
470 }
471 return false;
472}
473
474void GrDrawTarget::releaseReservedGeometry() {
475 GrAssert(fReservedGeometry.fLocked);
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000476 this->onReleaseGeometry();
reed@google.comac10a2d2010-12-22 21:39:39 +0000477 fReservedGeometry.fLocked = false;
478}
479
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000480void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
481 const void* vertexArray,
482 int vertexCount) {
483 fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000484 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000485 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000486}
487
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000488void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
489 int indexCount) {
490 fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000491 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000492}
493
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000494void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
495 const GrVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000496 fGeometrySrc.fVertexSrc = kBuffer_GeometrySrcType;
497 fGeometrySrc.fVertexBuffer = buffer;
498 fGeometrySrc.fVertexLayout = vertexLayout;
499}
500
501void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
502 fGeometrySrc.fIndexSrc = kBuffer_GeometrySrcType;
503 fGeometrySrc.fIndexBuffer = buffer;
504}
505
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000506///////////////////////////////////////////////////////////////////////////////
507
508bool GrDrawTarget::canDisableBlend() const {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000509 // If we compute a coverage value (using edge AA or a coverage stage) then
510 // we can't force blending off.
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000511 if (fCurrDrawState.fEdgeAANumEdges > 0) {
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000512 return false;
513 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000514 for (int s = fCurrDrawState.fFirstCoverageStage; s < kNumStages; ++s) {
515 if (this->isStageEnabled(s)) {
516 return false;
517 }
518 }
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000519
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000520 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
521 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
522 return true;
523 }
524
525 // If we have vertex color without alpha then we can't force blend off
526 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
527 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
528 return false;
529 }
530
531 // If the src coef will always be 1...
532 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
533 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
534 return false;
535 }
536
537 // ...and the dst coef is always 0...
538 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
539 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
540 return false;
541 }
542
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000543 // ...and there isn't a texture stage with an alpha channel...
544 for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000545 if (this->isStageEnabled(s)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000546 GrAssert(NULL != fCurrDrawState.fTextures[s]);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000547
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000548 GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000549
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000550 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000551 return false;
552 }
553 }
554 }
555
Scroggo0bad6732011-05-11 20:25:01 +0000556 // ...and there isn't an interesting color filter...
557 // TODO: Consider being more aggressive with regards to disabling
558 // blending when a color filter is used.
559 if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
560 return false;
561 }
562
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000563 // ...then we disable blend.
564 return true;
565}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000566
567///////////////////////////////////////////////////////////////////////////////
senorblanco@chromium.orgef3913b2011-05-19 17:11:07 +0000568void GrDrawTarget::setEdgeAAData(const Edge* edges, int numEdges) {
569 GrAssert(numEdges <= kMaxEdges);
570 memcpy(fCurrDrawState.fEdgeAAEdges, edges, numEdges * sizeof(Edge));
571 fCurrDrawState.fEdgeAANumEdges = numEdges;
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000572}
573
574
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000575///////////////////////////////////////////////////////////////////////////////
576void GrDrawTarget::drawRect(const GrRect& rect,
577 const GrMatrix* matrix,
bsalomon@google.comffca4002011-02-22 20:34:01 +0000578 StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000579 const GrRect* srcRects[],
580 const GrMatrix* srcMatrices[]) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000581 GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000582
583 AutoReleaseGeometry geo(this, layout, 4, 0);
584
585 SetRectVertices(rect, matrix, srcRects,
586 srcMatrices, layout, geo.vertices());
587
588 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
589}
590
bsalomon@google.comffca4002011-02-22 20:34:01 +0000591GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000592 const GrRect* srcRects[]) {
593 GrVertexLayout layout = 0;
594
595 for (int i = 0; i < kNumStages; ++i) {
596 int numTC = 0;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000597 if (stageEnableBitfield & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000598 if (NULL != srcRects && NULL != srcRects[i]) {
599 layout |= StageTexCoordVertexLayoutBit(i, numTC);
600 ++numTC;
601 } else {
602 layout |= StagePosAsTexCoordVertexLayoutBit(i);
603 }
604 }
605 }
606 return layout;
607}
608void GrDrawTarget::SetRectVertices(const GrRect& rect,
609 const GrMatrix* matrix,
610 const GrRect* srcRects[],
611 const GrMatrix* srcMatrices[],
612 GrVertexLayout layout,
613 void* vertices) {
614#if GR_DEBUG
615 // check that the layout and srcRects agree
616 for (int i = 0; i < kNumStages; ++i) {
617 if (VertexTexCoordsForStage(i, layout) >= 0) {
618 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
619 } else {
620 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
621 }
622 }
623#endif
624
625 int stageOffsets[kNumStages];
626 int colorOffset;
627 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset);
628 GrAssert(-1 == colorOffset);
629
630 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
631 rect.fRight, rect.fBottom,
632 vsize);
633 if (NULL != matrix) {
634 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
635 }
636
637 for (int i = 0; i < kNumStages; ++i) {
638 if (stageOffsets[i] > 0) {
639 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
640 stageOffsets[i]);
641 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
642 srcRects[i]->fRight, srcRects[i]->fBottom,
643 vsize);
644 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
645 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
646 }
647 }
648 }
649}
650
651///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000652
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000653GrDrawTarget::AutoStateRestore::AutoStateRestore() {
654 fDrawTarget = NULL;
655}
reed@google.comac10a2d2010-12-22 21:39:39 +0000656
657GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
658 fDrawTarget = target;
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000659 if (NULL != fDrawTarget) {
660 fDrawTarget->saveCurrentDrawState(&fDrawState);
661 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000662}
663
664GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000665 if (NULL != fDrawTarget) {
666 fDrawTarget->restoreDrawState(fDrawState);
667 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000668}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000669
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000670void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
671 if (target != fDrawTarget) {
672 if (NULL != fDrawTarget) {
673 fDrawTarget->restoreDrawState(fDrawState);
674 }
675 if (NULL != target) {
676 fDrawTarget->saveCurrentDrawState(&fDrawState);
677 }
678 fDrawTarget = target;
679 }
680}
bsalomon@google.com7ac249b2011-06-14 18:46:24 +0000681
682///////////////////////////////////////////////////////////////////////////////
683
684GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(GrDrawTarget* target,
685 int stageMask) {
686 GrAssert(NULL != target);
687
688 fDrawTarget = target;
689 fViewMatrix = target->getViewMatrix();
690 fStageMask = stageMask;
691 if (fStageMask) {
692 GrMatrix invVM;
693 if (fViewMatrix.invert(&invVM)) {
694 for (int s = 0; s < kNumStages; ++s) {
695 if (fStageMask & (1 << s)) {
696 fSamplerMatrices[s] = target->getSamplerMatrix(s);
697 }
698 }
699 target->preConcatSamplerMatrices(fStageMask, invVM);
700 } else {
701 // sad trombone sound
702 fStageMask = 0;
703 }
704 }
705 target->setViewMatrix(GrMatrix::I());
706}
707
708GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
709 fDrawTarget->setViewMatrix(fViewMatrix);
710 for (int s = 0; s < kNumStages; ++s) {
711 if (fStageMask & (1 << s)) {
712 fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]);
713 }
714 }
715}
716