blob: efee91e399b0e74525f9ff5ff8293ec0b214a91c [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.comffca4002011-02-22 20:34:01 +0000377void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoef,
378 GrBlendCoeff dstCoef) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000379 fCurrDrawState.fSrcBlend = srcCoef;
380 fCurrDrawState.fDstBlend = dstCoef;
381}
382
383void GrDrawTarget::setColor(GrColor c) {
384 fCurrDrawState.fColor = c;
385}
386
Scroggo97c88c22011-05-11 14:05:25 +0000387void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
388 fCurrDrawState.fColorFilterColor = c;
389 fCurrDrawState.fColorFilterXfermode = mode;
390}
391
reed@google.comac10a2d2010-12-22 21:39:39 +0000392void GrDrawTarget::setAlpha(uint8_t a) {
393 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
394}
395
396void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
397 state->fState = fCurrDrawState;
398}
399
400void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
401 fCurrDrawState = state.fState;
402}
403
404void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
405 fCurrDrawState = srcTarget.fCurrDrawState;
406}
407
408
409bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout,
410 uint32_t vertexCount,
411 uint32_t indexCount,
412 void** vertices,
413 void** indices) {
414 GrAssert(!fReservedGeometry.fLocked);
415 fReservedGeometry.fVertexCount = vertexCount;
416 fReservedGeometry.fIndexCount = indexCount;
417
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000418 fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout,
419 vertices,
420 indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000421 if (fReservedGeometry.fLocked) {
422 if (vertexCount) {
423 fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
424 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000425 } else if (NULL != vertices) {
426 *vertices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000427 }
428 if (indexCount) {
429 fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000430 } else if (NULL != indices) {
431 *indices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000432 }
433 }
434 return fReservedGeometry.fLocked;
435}
436
437bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
438 int32_t* vertexCount,
439 int32_t* indexCount) const {
440 GrAssert(!fReservedGeometry.fLocked);
441 if (NULL != vertexCount) {
442 *vertexCount = -1;
443 }
444 if (NULL != indexCount) {
445 *indexCount = -1;
446 }
447 return false;
448}
449
450void GrDrawTarget::releaseReservedGeometry() {
451 GrAssert(fReservedGeometry.fLocked);
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000452 this->onReleaseGeometry();
reed@google.comac10a2d2010-12-22 21:39:39 +0000453 fReservedGeometry.fLocked = false;
454}
455
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000456void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
457 const void* vertexArray,
458 int vertexCount) {
459 fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000460 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000461 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000462}
463
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000464void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
465 int indexCount) {
466 fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000467 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000468}
469
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000470void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
471 const GrVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000472 fGeometrySrc.fVertexSrc = kBuffer_GeometrySrcType;
473 fGeometrySrc.fVertexBuffer = buffer;
474 fGeometrySrc.fVertexLayout = vertexLayout;
475}
476
477void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
478 fGeometrySrc.fIndexSrc = kBuffer_GeometrySrcType;
479 fGeometrySrc.fIndexBuffer = buffer;
480}
481
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000482///////////////////////////////////////////////////////////////////////////////
483
484bool GrDrawTarget::canDisableBlend() const {
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000485 // If we're using edge antialiasing, we can't force blend off.
bsalomon@google.com12ad3aa2011-05-12 20:34:19 +0000486 if (fCurrDrawState.fFlagBits & kEdgeAA_StateBit) {
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000487 return false;
488 }
489
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000490 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
491 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
492 return true;
493 }
494
495 // If we have vertex color without alpha then we can't force blend off
496 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
497 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
498 return false;
499 }
500
501 // If the src coef will always be 1...
502 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
503 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
504 return false;
505 }
506
507 // ...and the dst coef is always 0...
508 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
509 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
510 return false;
511 }
512
513 // ...and there isn't a texture with an alpha channel...
514 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000515 if (this->isStageEnabled(s)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000516 GrAssert(NULL != fCurrDrawState.fTextures[s]);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000517
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000518 GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000519
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000520 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000521 return false;
522 }
523 }
524 }
525
Scroggo0bad6732011-05-11 20:25:01 +0000526 // ...and there isn't an interesting color filter...
527 // TODO: Consider being more aggressive with regards to disabling
528 // blending when a color filter is used.
529 if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
530 return false;
531 }
532
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000533 // ...then we disable blend.
534 return true;
535}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000536
537///////////////////////////////////////////////////////////////////////////////
538void GrDrawTarget::setEdgeAAData(const float edges[18]) {
539 memcpy(fCurrDrawState.fEdgeAAEdges, edges, sizeof(fCurrDrawState.fEdgeAAEdges));
540}
541
542
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000543///////////////////////////////////////////////////////////////////////////////
544void GrDrawTarget::drawRect(const GrRect& rect,
545 const GrMatrix* matrix,
bsalomon@google.comffca4002011-02-22 20:34:01 +0000546 StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000547 const GrRect* srcRects[],
548 const GrMatrix* srcMatrices[]) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000549 GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000550
551 AutoReleaseGeometry geo(this, layout, 4, 0);
552
553 SetRectVertices(rect, matrix, srcRects,
554 srcMatrices, layout, geo.vertices());
555
556 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
557}
558
bsalomon@google.comffca4002011-02-22 20:34:01 +0000559GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000560 const GrRect* srcRects[]) {
561 GrVertexLayout layout = 0;
562
563 for (int i = 0; i < kNumStages; ++i) {
564 int numTC = 0;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000565 if (stageEnableBitfield & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000566 if (NULL != srcRects && NULL != srcRects[i]) {
567 layout |= StageTexCoordVertexLayoutBit(i, numTC);
568 ++numTC;
569 } else {
570 layout |= StagePosAsTexCoordVertexLayoutBit(i);
571 }
572 }
573 }
574 return layout;
575}
576void GrDrawTarget::SetRectVertices(const GrRect& rect,
577 const GrMatrix* matrix,
578 const GrRect* srcRects[],
579 const GrMatrix* srcMatrices[],
580 GrVertexLayout layout,
581 void* vertices) {
582#if GR_DEBUG
583 // check that the layout and srcRects agree
584 for (int i = 0; i < kNumStages; ++i) {
585 if (VertexTexCoordsForStage(i, layout) >= 0) {
586 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
587 } else {
588 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
589 }
590 }
591#endif
592
593 int stageOffsets[kNumStages];
594 int colorOffset;
595 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset);
596 GrAssert(-1 == colorOffset);
597
598 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
599 rect.fRight, rect.fBottom,
600 vsize);
601 if (NULL != matrix) {
602 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
603 }
604
605 for (int i = 0; i < kNumStages; ++i) {
606 if (stageOffsets[i] > 0) {
607 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
608 stageOffsets[i]);
609 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
610 srcRects[i]->fRight, srcRects[i]->fBottom,
611 vsize);
612 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
613 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
614 }
615 }
616 }
617}
618
619///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000620GrDrawTarget::AutoStateRestore::AutoStateRestore() {
621 fDrawTarget = NULL;
622}
reed@google.comac10a2d2010-12-22 21:39:39 +0000623
624GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
625 fDrawTarget = target;
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000626 if (NULL != fDrawTarget) {
627 fDrawTarget->saveCurrentDrawState(&fDrawState);
628 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000629}
630
631GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000632 if (NULL != fDrawTarget) {
633 fDrawTarget->restoreDrawState(fDrawState);
634 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000635}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000636
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000637void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
638 if (target != fDrawTarget) {
639 if (NULL != fDrawTarget) {
640 fDrawTarget->restoreDrawState(fDrawState);
641 }
642 if (NULL != target) {
643 fDrawTarget->saveCurrentDrawState(&fDrawState);
644 }
645 fDrawTarget = target;
646 }
647}