blob: 5e515137dce76515345a1954274e425eb69f3694 [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
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000022// recursive helper for creating mask with all the tex coord bits set for
23// one stage
24template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000025int stage_mask_recur(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000026 return GrDrawTarget::StageTexCoordVertexLayoutBit(stage, N) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000027 stage_mask_recur<N+1>(stage);
28}
reed@google.comd728f6e2011-01-13 20:02:47 +000029template<> // linux build doesn't like static on specializations
30int stage_mask_recur<GrDrawTarget::kNumStages>(int) { return 0; }
reed@google.comac10a2d2010-12-22 21:39:39 +000031
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000032// mask of all tex coord indices for one stage
33static int stage_tex_coord_mask(int stage) {
34 return stage_mask_recur<0>(stage);
reed@google.comac10a2d2010-12-22 21:39:39 +000035}
36
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000037// mask of all bits relevant to one stage
38static int stage_mask(int stage) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000039 return stage_tex_coord_mask(stage) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000040 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(stage);
41}
42
43// recursive helper for creating mask of with all bits set relevant to one
44// texture coordinate index
45template <int N>
reed@google.com34cec242011-04-19 15:53:12 +000046int tex_coord_mask_recur(int texCoordIdx) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000047 return GrDrawTarget::StageTexCoordVertexLayoutBit(N, texCoordIdx) |
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000048 tex_coord_mask_recur<N+1>(texCoordIdx);
49}
reed@google.comd728f6e2011-01-13 20:02:47 +000050template<> // linux build doesn't like static on specializations
51int tex_coord_mask_recur<GrDrawTarget::kMaxTexCoords>(int) { return 0; }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000052
53// mask of all bits relevant to one texture coordinate index
54static int tex_coord_idx_mask(int texCoordIdx) {
55 return tex_coord_mask_recur<0>(texCoordIdx);
56}
57
58bool check_layout(GrVertexLayout layout) {
59 // can only have 1 or 0 bits set for each stage.
60 for (int s = 0; s < GrDrawTarget::kNumStages; ++s) {
61 int stageBits = layout & stage_mask(s);
62 if (stageBits && !GrIsPow2(stageBits)) {
63 return false;
64 }
65 }
66 return true;
67}
68
69size_t GrDrawTarget::VertexSize(GrVertexLayout vertexLayout) {
70 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +000071
72 size_t vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000073 sizeof(GrGpuTextVertex) :
74 sizeof(GrPoint);
75
76 size_t size = vecSize; // position
77 for (int t = 0; t < kMaxTexCoords; ++t) {
78 if (tex_coord_idx_mask(t) & vertexLayout) {
79 size += vecSize;
80 }
81 }
82 if (vertexLayout & kColor_VertexLayoutBit) {
83 size += sizeof(GrColor);
84 }
85 return size;
86}
87
88int GrDrawTarget::VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout) {
89 GrAssert(check_layout(vertexLayout));
90 if (StagePosAsTexCoordVertexLayoutBit(stage) & vertexLayout) {
reed@google.comac10a2d2010-12-22 21:39:39 +000091 return 0;
92 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000093 int tcIdx = VertexTexCoordsForStage(stage, vertexLayout);
94 if (tcIdx >= 0) {
bsalomon@google.com5782d712011-01-21 21:03:59 +000095
96 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +000097 sizeof(GrGpuTextVertex) :
98 sizeof(GrPoint);
99 int offset = vecSize; // position
100 // figure out how many tex coordinates are present and precede this one.
101 for (int t = 0; t < tcIdx; ++t) {
102 if (tex_coord_idx_mask(t) & vertexLayout) {
103 offset += vecSize;
104 }
105 }
106 return offset;
107 }
108
reed@google.comac10a2d2010-12-22 21:39:39 +0000109 return -1;
110}
111
112int GrDrawTarget::VertexColorOffset(GrVertexLayout vertexLayout) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000113 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000114
reed@google.comac10a2d2010-12-22 21:39:39 +0000115 if (vertexLayout & kColor_VertexLayoutBit) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000116 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000117 sizeof(GrGpuTextVertex) :
118 sizeof(GrPoint);
119 int offset = vecSize; // position
120 // figure out how many tex coordinates are present and precede this one.
121 for (int t = 0; t < kMaxTexCoords; ++t) {
122 if (tex_coord_idx_mask(t) & vertexLayout) {
123 offset += vecSize;
124 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000125 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000126 return offset;
reed@google.comac10a2d2010-12-22 21:39:39 +0000127 }
128 return -1;
129}
130
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000131int GrDrawTarget::VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
132 int texCoordOffsetsByIdx[kMaxTexCoords],
133 int* colorOffset) {
134 GrAssert(check_layout(vertexLayout));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000135
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000136 GrAssert(NULL != texCoordOffsetsByIdx);
reed@google.comac10a2d2010-12-22 21:39:39 +0000137 GrAssert(NULL != colorOffset);
138
bsalomon@google.com5782d712011-01-21 21:03:59 +0000139 int vecSize = (vertexLayout & kTextFormat_VertexLayoutBit) ?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000140 sizeof(GrGpuTextVertex) :
141 sizeof(GrPoint);
142 int size = vecSize; // position
bsalomon@google.com5782d712011-01-21 21:03:59 +0000143
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000144 for (int t = 0; t < kMaxTexCoords; ++t) {
145 if (tex_coord_idx_mask(t) & vertexLayout) {
146 texCoordOffsetsByIdx[t] = size;
147 size += vecSize;
reed@google.comac10a2d2010-12-22 21:39:39 +0000148 } else {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000149 texCoordOffsetsByIdx[t] = -1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000150 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000151 }
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000152 if (kColor_VertexLayoutBit & vertexLayout) {
153 *colorOffset = size;
154 size += sizeof(GrColor);
155 } else {
156 *colorOffset = -1;
157 }
158 return size;
reed@google.comac10a2d2010-12-22 21:39:39 +0000159}
160
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000161int GrDrawTarget::VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
162 int texCoordOffsetsByStage[kNumStages],
163 int* colorOffset) {
164 GrAssert(check_layout(vertexLayout));
165
166 GrAssert(NULL != texCoordOffsetsByStage);
167 GrAssert(NULL != colorOffset);
bsalomon@google.com5782d712011-01-21 21:03:59 +0000168
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000169 int texCoordOffsetsByIdx[kMaxTexCoords];
bsalomon@google.com5782d712011-01-21 21:03:59 +0000170 int size = VertexSizeAndOffsetsByIdx(vertexLayout,
171 texCoordOffsetsByIdx,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000172 colorOffset);
173 for (int s = 0; s < kNumStages; ++s) {
174 int tcIdx;
175 if (StagePosAsTexCoordVertexLayoutBit(s) & vertexLayout) {
176 texCoordOffsetsByStage[s] = 0;
177 } else if ((tcIdx = VertexTexCoordsForStage(s, vertexLayout)) >= 0) {
178 texCoordOffsetsByStage[s] = texCoordOffsetsByIdx[tcIdx];
179 } else {
180 texCoordOffsetsByStage[s] = -1;
181 }
182 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000183 return size;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000184}
185
186bool GrDrawTarget::VertexUsesStage(int stage, GrVertexLayout vertexLayout) {
187 GrAssert(stage < kNumStages);
188 GrAssert(check_layout(vertexLayout));
189 return !!(stage_mask(stage) & vertexLayout);
190}
191
bsalomon@google.com5782d712011-01-21 21:03:59 +0000192bool GrDrawTarget::VertexUsesTexCoordIdx(int coordIndex,
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000193 GrVertexLayout vertexLayout) {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000194 GrAssert(coordIndex < kMaxTexCoords);
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000195 GrAssert(check_layout(vertexLayout));
196 return !!(tex_coord_idx_mask(coordIndex) & vertexLayout);
197}
198
199int GrDrawTarget::VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout) {
200 GrAssert(stage < kNumStages);
201 GrAssert(check_layout(vertexLayout));
202 int bit = vertexLayout & stage_tex_coord_mask(stage);
203 if (bit) {
204 // figure out which set of texture coordates is used
205 // bits are ordered T0S0, T0S1, T0S2, ..., T1S0, T1S1, ...
206 // and start at bit 0.
207 GR_STATIC_ASSERT(sizeof(GrVertexLayout) <= sizeof(uint32_t));
208 return (32 - Gr_clz(bit) - 1) / kNumStages;
209 }
210 return -1;
211}
212
213void GrDrawTarget::VertexLayoutUnitTest() {
214 // not necessarily exhaustive
215 static bool run;
216 if (!run) {
217 run = true;
218 for (int s = 0; s < kNumStages; ++s) {
219
220 GrAssert(!VertexUsesStage(s, 0));
221 GrAssert(-1 == VertexStageCoordOffset(s, 0));
222 GrVertexLayout stageMask = 0;
223 for (int t = 0; t < kMaxTexCoords; ++t) {
224 stageMask |= StageTexCoordVertexLayoutBit(s,t);
225 }
bsalomon@google.com5782d712011-01-21 21:03:59 +0000226 GrAssert(1 == kMaxTexCoords || !check_layout(stageMask));
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000227 GrAssert(stage_tex_coord_mask(s) == stageMask);
228 stageMask |= StagePosAsTexCoordVertexLayoutBit(s);
229 GrAssert(stage_mask(s) == stageMask);
230 GrAssert(!check_layout(stageMask));
231 }
232 for (int t = 0; t < kMaxTexCoords; ++t) {
233 GrVertexLayout tcMask = 0;
234 GrAssert(!VertexUsesTexCoordIdx(t, 0));
235 for (int s = 0; s < kNumStages; ++s) {
236 tcMask |= StageTexCoordVertexLayoutBit(s,t);
237 GrAssert(VertexUsesStage(s, tcMask));
238 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
239 GrAssert(VertexUsesTexCoordIdx(t, tcMask));
240 GrAssert(2*sizeof(GrPoint) == VertexSize(tcMask));
241 GrAssert(t == VertexTexCoordsForStage(s, tcMask));
242 for (int s2 = s + 1; s2 < kNumStages; ++s2) {
243 GrAssert(-1 == VertexStageCoordOffset(s2, tcMask));
244 GrAssert(!VertexUsesStage(s2, tcMask));
245 GrAssert(-1 == VertexTexCoordsForStage(s2, tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000246
bsalomon@google.com19628322011-02-03 21:30:17 +0000247 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000248 GrVertexLayout posAsTex = tcMask | StagePosAsTexCoordVertexLayoutBit(s2);
bsalomon@google.com19628322011-02-03 21:30:17 +0000249 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000250 GrAssert(0 == VertexStageCoordOffset(s2, posAsTex));
251 GrAssert(VertexUsesStage(s2, posAsTex));
252 GrAssert(2*sizeof(GrPoint) == VertexSize(posAsTex));
253 GrAssert(-1 == VertexTexCoordsForStage(s2, posAsTex));
254 }
bsalomon@google.com19628322011-02-03 21:30:17 +0000255 #if GR_DEBUG
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000256 GrVertexLayout withColor = tcMask | kColor_VertexLayoutBit;
bsalomon@google.com19628322011-02-03 21:30:17 +0000257 #endif
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000258 GrAssert(2*sizeof(GrPoint) == VertexColorOffset(withColor));
259 GrAssert(2*sizeof(GrPoint) + sizeof(GrColor) == VertexSize(withColor));
260 }
261 GrAssert(tex_coord_idx_mask(t) == tcMask);
262 GrAssert(check_layout(tcMask));
bsalomon@google.com5782d712011-01-21 21:03:59 +0000263
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000264 int stageOffsets[kNumStages];
265 int colorOffset;
266 int size;
267 size = VertexSizeAndOffsetsByStage(tcMask, stageOffsets, &colorOffset);
268 GrAssert(2*sizeof(GrPoint) == size);
269 GrAssert(-1 == colorOffset);
270 for (int s = 0; s < kNumStages; ++s) {
271 GrAssert(VertexUsesStage(s, tcMask));
272 GrAssert(sizeof(GrPoint) == stageOffsets[s]);
273 GrAssert(sizeof(GrPoint) == VertexStageCoordOffset(s, tcMask));
274 }
275 }
276 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000277}
278
279////////////////////////////////////////////////////////////////////////////////
280
281GrDrawTarget::GrDrawTarget() {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000282#if GR_DEBUG
283 VertexLayoutUnitTest();
284#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000285 fReservedGeometry.fLocked = false;
286#if GR_DEBUG
287 fReservedGeometry.fVertexCount = ~0;
288 fReservedGeometry.fIndexCount = ~0;
289#endif
290 fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
291 fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
292}
293
294void GrDrawTarget::setClip(const GrClip& clip) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000295 clipWillBeSet(clip);
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 fClip = clip;
297}
298
299const GrClip& GrDrawTarget::getClip() const {
300 return fClip;
301}
302
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000303void GrDrawTarget::setTexture(int stage, GrTexture* tex) {
304 GrAssert(stage >= 0 && stage < kNumStages);
305 fCurrDrawState.fTextures[stage] = tex;
reed@google.comac10a2d2010-12-22 21:39:39 +0000306}
307
bsalomon@google.com5782d712011-01-21 21:03:59 +0000308const GrTexture* GrDrawTarget::getTexture(int stage) const {
309 GrAssert(stage >= 0 && stage < kNumStages);
310 return fCurrDrawState.fTextures[stage];
311}
312
313GrTexture* GrDrawTarget::getTexture(int stage) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000314 GrAssert(stage >= 0 && stage < kNumStages);
315 return fCurrDrawState.fTextures[stage];
reed@google.comac10a2d2010-12-22 21:39:39 +0000316}
317
318void GrDrawTarget::setRenderTarget(GrRenderTarget* target) {
319 fCurrDrawState.fRenderTarget = target;
320}
321
bsalomon@google.com5782d712011-01-21 21:03:59 +0000322const GrRenderTarget* GrDrawTarget::getRenderTarget() const {
323 return fCurrDrawState.fRenderTarget;
324}
325
326GrRenderTarget* GrDrawTarget::getRenderTarget() {
reed@google.comac10a2d2010-12-22 21:39:39 +0000327 return fCurrDrawState.fRenderTarget;
328}
329
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000330void GrDrawTarget::setViewMatrix(const GrMatrix& m) {
331 fCurrDrawState.fViewMatrix = m;
reed@google.comac10a2d2010-12-22 21:39:39 +0000332}
333
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000334void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) {
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000335 fCurrDrawState.fViewMatrix.preConcat(matrix);
336}
337
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000338void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) {
339 fCurrDrawState.fViewMatrix.postConcat(matrix);
340}
341
bsalomon@google.com5782d712011-01-21 21:03:59 +0000342const GrMatrix& GrDrawTarget::getViewMatrix() const {
343 return fCurrDrawState.fViewMatrix;
reed@google.comac10a2d2010-12-22 21:39:39 +0000344}
345
346bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const {
bsalomon@google.com5782d712011-01-21 21:03:59 +0000347 // Mike: Can we cache this somewhere?
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000348 // Brian: Sure, do we use it often?
reed@google.comac10a2d2010-12-22 21:39:39 +0000349
350 GrMatrix inverse;
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000351 if (fCurrDrawState.fViewMatrix.invert(&inverse)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000352 if (matrix) {
353 *matrix = inverse;
354 }
355 return true;
356 }
357 return false;
358}
359
bsalomon@google.com8531c1c2011-01-13 19:52:45 +0000360void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) {
361 GrAssert(stage >= 0 && stage < kNumStages);
362 fCurrDrawState.fSamplerStates[stage] = state;
363}
364
reed@google.comac10a2d2010-12-22 21:39:39 +0000365void GrDrawTarget::enableState(uint32_t bits) {
366 fCurrDrawState.fFlagBits |= bits;
367}
368
369void GrDrawTarget::disableState(uint32_t bits) {
370 fCurrDrawState.fFlagBits &= ~(bits);
371}
372
bsalomon@google.comffca4002011-02-22 20:34:01 +0000373void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoef,
374 GrBlendCoeff dstCoef) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000375 fCurrDrawState.fSrcBlend = srcCoef;
376 fCurrDrawState.fDstBlend = dstCoef;
377}
378
379void GrDrawTarget::setColor(GrColor c) {
380 fCurrDrawState.fColor = c;
381}
382
Scroggo97c88c22011-05-11 14:05:25 +0000383void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) {
384 fCurrDrawState.fColorFilterColor = c;
385 fCurrDrawState.fColorFilterXfermode = mode;
386}
387
reed@google.comac10a2d2010-12-22 21:39:39 +0000388void GrDrawTarget::setAlpha(uint8_t a) {
389 this->setColor((a << 24) | (a << 16) | (a << 8) | a);
390}
391
392void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
393 state->fState = fCurrDrawState;
394}
395
396void GrDrawTarget::restoreDrawState(const SavedDrawState& state) {
397 fCurrDrawState = state.fState;
398}
399
400void GrDrawTarget::copyDrawState(const GrDrawTarget& srcTarget) {
401 fCurrDrawState = srcTarget.fCurrDrawState;
402}
403
404
405bool GrDrawTarget::reserveAndLockGeometry(GrVertexLayout vertexLayout,
406 uint32_t vertexCount,
407 uint32_t indexCount,
408 void** vertices,
409 void** indices) {
410 GrAssert(!fReservedGeometry.fLocked);
411 fReservedGeometry.fVertexCount = vertexCount;
412 fReservedGeometry.fIndexCount = indexCount;
413
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000414 fReservedGeometry.fLocked = this->onAcquireGeometry(vertexLayout,
415 vertices,
416 indices);
reed@google.comac10a2d2010-12-22 21:39:39 +0000417 if (fReservedGeometry.fLocked) {
418 if (vertexCount) {
419 fGeometrySrc.fVertexSrc = kReserved_GeometrySrcType;
420 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000421 } else if (NULL != vertices) {
422 *vertices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000423 }
424 if (indexCount) {
425 fGeometrySrc.fIndexSrc = kReserved_GeometrySrcType;
bsalomon@google.comeaf6a5d2011-04-28 19:22:57 +0000426 } else if (NULL != indices) {
427 *indices = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000428 }
429 }
430 return fReservedGeometry.fLocked;
431}
432
433bool GrDrawTarget::geometryHints(GrVertexLayout vertexLayout,
434 int32_t* vertexCount,
435 int32_t* indexCount) const {
436 GrAssert(!fReservedGeometry.fLocked);
437 if (NULL != vertexCount) {
438 *vertexCount = -1;
439 }
440 if (NULL != indexCount) {
441 *indexCount = -1;
442 }
443 return false;
444}
445
446void GrDrawTarget::releaseReservedGeometry() {
447 GrAssert(fReservedGeometry.fLocked);
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000448 this->onReleaseGeometry();
reed@google.comac10a2d2010-12-22 21:39:39 +0000449 fReservedGeometry.fLocked = false;
450}
451
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000452void GrDrawTarget::setVertexSourceToArray(GrVertexLayout vertexLayout,
453 const void* vertexArray,
454 int vertexCount) {
455 fGeometrySrc.fVertexSrc = kArray_GeometrySrcType;
reed@google.comac10a2d2010-12-22 21:39:39 +0000456 fGeometrySrc.fVertexLayout = vertexLayout;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000457 this->onSetVertexSourceToArray(vertexArray, vertexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000458}
459
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000460void GrDrawTarget::setIndexSourceToArray(const void* indexArray,
461 int indexCount) {
462 fGeometrySrc.fIndexSrc = kArray_GeometrySrcType;
bsalomon@google.combcdbbe62011-04-12 15:40:00 +0000463 this->onSetIndexSourceToArray(indexArray, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000464}
465
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000466void GrDrawTarget::setVertexSourceToBuffer(GrVertexLayout vertexLayout,
467 const GrVertexBuffer* buffer) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000468 fGeometrySrc.fVertexSrc = kBuffer_GeometrySrcType;
469 fGeometrySrc.fVertexBuffer = buffer;
470 fGeometrySrc.fVertexLayout = vertexLayout;
471}
472
473void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) {
474 fGeometrySrc.fIndexSrc = kBuffer_GeometrySrcType;
475 fGeometrySrc.fIndexBuffer = buffer;
476}
477
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000478///////////////////////////////////////////////////////////////////////////////
479
480bool GrDrawTarget::canDisableBlend() const {
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000481 // If we're using edge antialiasing, we can't force blend off.
482 if (fCurrDrawState.fFlagBits & kAntialias_StateBit) {
483 return false;
484 }
485
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000486 if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
487 (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
488 return true;
489 }
490
491 // If we have vertex color without alpha then we can't force blend off
492 if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
493 0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
494 return false;
495 }
496
497 // If the src coef will always be 1...
498 if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
499 kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
500 return false;
501 }
502
503 // ...and the dst coef is always 0...
504 if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
505 kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
506 return false;
507 }
508
509 // ...and there isn't a texture with an alpha channel...
510 for (int s = 0; s < kNumStages; ++s) {
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000511 if (this->isStageEnabled(s)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000512 GrAssert(NULL != fCurrDrawState.fTextures[s]);
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000513
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000514 GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000515
bsalomon@google.coma47a48d2011-04-26 20:22:11 +0000516 if (!GrPixelConfigIsOpaque(config)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000517 return false;
518 }
519 }
520 }
521
Scroggo0bad6732011-05-11 20:25:01 +0000522 // ...and there isn't an interesting color filter...
523 // TODO: Consider being more aggressive with regards to disabling
524 // blending when a color filter is used.
525 if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
526 return false;
527 }
528
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000529 // ...then we disable blend.
530 return true;
531}
senorblanco@chromium.org92e0f222011-05-12 15:49:15 +0000532
533///////////////////////////////////////////////////////////////////////////////
534void GrDrawTarget::setEdgeAAData(const float edges[18]) {
535 memcpy(fCurrDrawState.fEdgeAAEdges, edges, sizeof(fCurrDrawState.fEdgeAAEdges));
536}
537
538
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000539///////////////////////////////////////////////////////////////////////////////
540void GrDrawTarget::drawRect(const GrRect& rect,
541 const GrMatrix* matrix,
bsalomon@google.comffca4002011-02-22 20:34:01 +0000542 StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000543 const GrRect* srcRects[],
544 const GrMatrix* srcMatrices[]) {
bsalomon@google.comffca4002011-02-22 20:34:01 +0000545 GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000546
547 AutoReleaseGeometry geo(this, layout, 4, 0);
548
549 SetRectVertices(rect, matrix, srcRects,
550 srcMatrices, layout, geo.vertices());
551
552 drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
553}
554
bsalomon@google.comffca4002011-02-22 20:34:01 +0000555GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageBitfield stageEnableBitfield,
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000556 const GrRect* srcRects[]) {
557 GrVertexLayout layout = 0;
558
559 for (int i = 0; i < kNumStages; ++i) {
560 int numTC = 0;
bsalomon@google.comffca4002011-02-22 20:34:01 +0000561 if (stageEnableBitfield & (1 << i)) {
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000562 if (NULL != srcRects && NULL != srcRects[i]) {
563 layout |= StageTexCoordVertexLayoutBit(i, numTC);
564 ++numTC;
565 } else {
566 layout |= StagePosAsTexCoordVertexLayoutBit(i);
567 }
568 }
569 }
570 return layout;
571}
572void GrDrawTarget::SetRectVertices(const GrRect& rect,
573 const GrMatrix* matrix,
574 const GrRect* srcRects[],
575 const GrMatrix* srcMatrices[],
576 GrVertexLayout layout,
577 void* vertices) {
578#if GR_DEBUG
579 // check that the layout and srcRects agree
580 for (int i = 0; i < kNumStages; ++i) {
581 if (VertexTexCoordsForStage(i, layout) >= 0) {
582 GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]);
583 } else {
584 GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]);
585 }
586 }
587#endif
588
589 int stageOffsets[kNumStages];
590 int colorOffset;
591 int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset);
592 GrAssert(-1 == colorOffset);
593
594 GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop,
595 rect.fRight, rect.fBottom,
596 vsize);
597 if (NULL != matrix) {
598 matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4);
599 }
600
601 for (int i = 0; i < kNumStages; ++i) {
602 if (stageOffsets[i] > 0) {
603 GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) +
604 stageOffsets[i]);
605 coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop,
606 srcRects[i]->fRight, srcRects[i]->fBottom,
607 vsize);
608 if (NULL != srcMatrices && NULL != srcMatrices[i]) {
609 srcMatrices[i]->mapPointsWithStride(coords, vsize, 4);
610 }
611 }
612 }
613}
614
615///////////////////////////////////////////////////////////////////////////////
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000616GrDrawTarget::AutoStateRestore::AutoStateRestore() {
617 fDrawTarget = NULL;
618}
reed@google.comac10a2d2010-12-22 21:39:39 +0000619
620GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) {
621 fDrawTarget = target;
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000622 if (NULL != fDrawTarget) {
623 fDrawTarget->saveCurrentDrawState(&fDrawState);
624 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000625}
626
627GrDrawTarget::AutoStateRestore::~AutoStateRestore() {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000628 if (NULL != fDrawTarget) {
629 fDrawTarget->restoreDrawState(fDrawState);
630 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000631}
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000632
bsalomon@google.com06afe7b2011-04-26 15:31:40 +0000633void GrDrawTarget::AutoStateRestore::set(GrDrawTarget* target) {
634 if (target != fDrawTarget) {
635 if (NULL != fDrawTarget) {
636 fDrawTarget->restoreDrawState(fDrawState);
637 }
638 if (NULL != target) {
639 fDrawTarget->saveCurrentDrawState(&fDrawState);
640 }
641 fDrawTarget = target;
642 }
643}