blob: 4b52fd879c9441c551bc7209afdc9fa208a4f1db [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
reed@google.comac10a2d2010-12-22 21:39:39 +000017#include "GrGpu.h"
18#include "GrMemory.h"
19#include "GrTextStrike.h"
20#include "GrTextureCache.h"
21#include "GrClipIterator.h"
22#include "GrIndexBuffer.h"
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000023#include "GrVertexBuffer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000024#include "GrBufferAllocPool.h"
bsalomon@google.comd302f142011-03-03 13:54:13 +000025#include "GrPathRenderer.h"
bsalomon@google.com1c13c962011-02-14 16:51:21 +000026
27// probably makes no sense for this to be less than a page
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +000028static const size_t VERTEX_POOL_VB_SIZE = 1 << 12;
29static const int VERTEX_POOL_VB_COUNT = 1;
reed@google.comac10a2d2010-12-22 21:39:39 +000030
bsalomon@google.comd302f142011-03-03 13:54:13 +000031////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000032
33size_t GrTexture::BytesPerPixel(PixelConfig config) {
34 switch (config) {
35 case kAlpha_8_PixelConfig:
36 case kIndex_8_PixelConfig:
37 return 1;
38 case kRGB_565_PixelConfig:
39 case kRGBA_4444_PixelConfig:
40 return 2;
41 case kRGBA_8888_PixelConfig:
42 case kRGBX_8888_PixelConfig:
43 return 4;
44 default:
45 return 0;
46 }
47}
48
49bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
50 switch (config) {
51 case GrTexture::kRGB_565_PixelConfig:
52 case GrTexture::kRGBX_8888_PixelConfig:
53 return true;
54 default:
55 return false;
56 }
57}
58
bsalomon@google.com080773c2011-03-15 19:09:25 +000059bool GrTexture::PixelConfigIsAlphaOnly(PixelConfig config) {
60 switch (config) {
61 case GrTexture::kAlpha_8_PixelConfig:
62 return true;
63 default:
64 return false;
65 }
66}
reed@google.comac10a2d2010-12-22 21:39:39 +000067
bsalomon@google.comd302f142011-03-03 13:54:13 +000068////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +000069
70extern void gr_run_unittests();
71
72GrGpu::GrGpu() : f8bitPaletteSupport(false),
bsalomon@google.com1c13c962011-02-14 16:51:21 +000073 fCurrPoolVertexBuffer(NULL),
74 fCurrPoolStartVertex(0),
75 fCurrPoolIndexBuffer(NULL),
76 fCurrPoolStartIndex(0),
77 fVertexPool(NULL),
78 fIndexPool(NULL),
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000079 fQuadIndexBuffer(NULL),
bsalomon@google.comd302f142011-03-03 13:54:13 +000080 fUnitSquareVertexBuffer(NULL),
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000081 fDefaultPathRenderer(NULL),
82 fClientPathRenderer(NULL),
bsalomon@google.coma7f84e12011-03-10 14:13:19 +000083 fContextIsDirty(true),
bsalomon@google.comd302f142011-03-03 13:54:13 +000084 fVertexPoolInUse(false),
85 fIndexPoolInUse(false) {
reed@google.comac10a2d2010-12-22 21:39:39 +000086#if GR_DEBUG
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +000087 //gr_run_unittests();
reed@google.comac10a2d2010-12-22 21:39:39 +000088#endif
89 resetStats();
90}
91
92GrGpu::~GrGpu() {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +000093 GrSafeUnref(fQuadIndexBuffer);
94 GrSafeUnref(fUnitSquareVertexBuffer);
bsalomon@google.com1c13c962011-02-14 16:51:21 +000095 delete fVertexPool;
96 delete fIndexPool;
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +000097 GrSafeUnref(fClientPathRenderer);
98 GrSafeUnref(fDefaultPathRenderer);
reed@google.comac10a2d2010-12-22 21:39:39 +000099}
100
101void GrGpu::resetContext() {
102}
103
104void GrGpu::unimpl(const char msg[]) {
bsalomon@google.com7d34d2e2011-01-24 17:41:47 +0000105#if GR_DEBUG
106 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
107#endif
reed@google.comac10a2d2010-12-22 21:39:39 +0000108}
109
bsalomon@google.comd302f142011-03-03 13:54:13 +0000110////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000111
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000112GrTexture* GrGpu::createTexture(const TextureDesc& desc,
113 const void* srcData, size_t rowBytes) {
114 this->handleDirtyContext();
115 return this->createTextureHelper(desc, srcData, rowBytes);
116}
117
118GrRenderTarget* GrGpu::createPlatformRenderTarget(intptr_t platformRenderTarget,
119 int stencilBits,
120 int width, int height) {
121 this->handleDirtyContext();
122 return this->createPlatformRenderTargetHelper(platformRenderTarget,
123 stencilBits,
124 width, height);
125}
126
127GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
128 this->handleDirtyContext();
129 return this->createRenderTargetFrom3DApiStateHelper();
130}
131
132GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
133 this->handleDirtyContext();
134 return this->createVertexBufferHelper(size, dynamic);
135}
136
137GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
138 this->handleDirtyContext();
139 return this->createIndexBufferHelper(size, dynamic);
140}
141
142void GrGpu::eraseColor(GrColor color) {
143 this->handleDirtyContext();
144 this->eraseColorHelper(color);
145}
146
147void GrGpu::forceRenderTargetFlush() {
148 this->handleDirtyContext();
149 this->forceRenderTargetFlushHelper();
150}
151
152bool GrGpu::readPixels(int left, int top, int width, int height,
153 GrTexture::PixelConfig config, void* buffer) {
154 this->handleDirtyContext();
155 return this->readPixelsHelper(left, top, width, height, config, buffer);
156}
157
158////////////////////////////////////////////////////////////////////////////////
159
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000160static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
reed@google.comac10a2d2010-12-22 21:39:39 +0000161
reed@google.com8195f672011-01-12 18:14:28 +0000162GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
reed@google.comac10a2d2010-12-22 21:39:39 +0000163
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000164static inline void fill_indices(uint16_t* indices, int quadCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000165 for (int i = 0; i < quadCount; ++i) {
166 indices[6 * i + 0] = 4 * i + 0;
167 indices[6 * i + 1] = 4 * i + 1;
168 indices[6 * i + 2] = 4 * i + 2;
169 indices[6 * i + 3] = 4 * i + 0;
170 indices[6 * i + 4] = 4 * i + 2;
171 indices[6 * i + 5] = 4 * i + 3;
172 }
173}
174
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000175const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 if (NULL == fQuadIndexBuffer) {
177 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
178 GrGpu* me = const_cast<GrGpu*>(this);
179 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
180 if (NULL != fQuadIndexBuffer) {
181 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
182 if (NULL != indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000183 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 fQuadIndexBuffer->unlock();
185 } else {
186 indices = (uint16_t*)GrMalloc(SIZE);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000187 fill_indices(indices, MAX_QUADS);
reed@google.comac10a2d2010-12-22 21:39:39 +0000188 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
189 fQuadIndexBuffer->unref();
190 fQuadIndexBuffer = NULL;
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000191 GrCrash("Can't get indices into buffer!");
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 }
193 GrFree(indices);
194 }
195 }
196 }
197
198 return fQuadIndexBuffer;
199}
200
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000201const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
bsalomon@google.com6f7fbc92011-02-01 19:12:40 +0000202 if (NULL == fUnitSquareVertexBuffer) {
203
204 static const GrPoint DATA[] = {
205 GrPoint(0, 0),
206 GrPoint(GR_Scalar1,0),
207 GrPoint(GR_Scalar1,GR_Scalar1),
208 GrPoint(0, GR_Scalar1)
209 };
210 static const size_t SIZE = sizeof(DATA);
211
212 GrGpu* me = const_cast<GrGpu*>(this);
213 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
214 if (NULL != fUnitSquareVertexBuffer) {
215 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
216 fUnitSquareVertexBuffer->unref();
217 fUnitSquareVertexBuffer = NULL;
218 GrCrash("Can't get vertices into buffer!");
219 }
220 }
221 }
222
223 return fUnitSquareVertexBuffer;
224}
225
bsalomon@google.comd302f142011-03-03 13:54:13 +0000226////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000227
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000228void GrGpu::clipWillBeSet(const GrClip& newClip) {
229 if (newClip != fClip) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000230 fClipState.fClipIsDirty = true;
231 }
232}
233
bsalomon@google.comd302f142011-03-03 13:54:13 +0000234////////////////////////////////////////////////////////////////////////////////
235
236// stencil settings to use when clip is in stencil
237const GrStencilSettings GrGpu::gClipStencilSettings = {
238 kKeep_StencilOp, kKeep_StencilOp,
239 kKeep_StencilOp, kKeep_StencilOp,
240 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
241 0, 0,
242 0, 0,
243 0, 0
244};
245
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000246// mapping of clip-respecting stencil funcs to normal stencil funcs
247// mapping depends on whether stencil-clipping is in effect.
bsalomon@google.comd302f142011-03-03 13:54:13 +0000248static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = {
249 {// Stencil-Clipping is DISABLED, effectively always inside the clip
250 // In the Clip Funcs
251 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
252 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
253 kLess_StencilFunc, // kLessIfInClip_StencilFunc
254 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
255 // Special in the clip func that forces user's ref to be 0.
256 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc
257 // make ref 0 and do normal nequal.
258 },
259 {// Stencil-Clipping is ENABLED
260 // In the Clip Funcs
261 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc
262 // eq stencil clip bit, mask
263 // out user bits.
264
265 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
266 // add stencil bit to mask and ref
267
268 kLess_StencilFunc, // kLessIfInClip_StencilFunc
269 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
270 // for both of these we can add
271 // the clip bit to the mask and
272 // ref and compare as normal
273 // Special in the clip func that forces user's ref to be 0.
274 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc
275 // make ref have only the clip bit set
276 // and make comparison be less
277 // 10..0 < 1..user_bits..
278 }
279};
280
281GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) {
282 GrAssert(func >= 0);
283 if (func >= kBasicStencilFuncCount) {
284 GrAssert(func < kStencilFuncCount);
285 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount];
286 GrAssert(func >= 0 && func < kBasicStencilFuncCount);
287 }
288 return func;
289}
290
291void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func,
292 bool clipInStencil,
293 unsigned int clipBit,
294 unsigned int userBits,
295 unsigned int* ref,
296 unsigned int* mask) {
297 if (func < kBasicStencilFuncCount) {
298 *mask &= userBits;
299 *ref &= userBits;
300 } else {
301 if (clipInStencil) {
302 switch (func) {
303 case kAlwaysIfInClip_StencilFunc:
304 *mask = clipBit;
305 *ref = clipBit;
306 break;
307 case kEqualIfInClip_StencilFunc:
308 case kLessIfInClip_StencilFunc:
309 case kLEqualIfInClip_StencilFunc:
310 *mask = (*mask & userBits) | clipBit;
311 *ref = (*ref & userBits) | clipBit;
312 break;
313 case kNonZeroIfInClip_StencilFunc:
314 *mask = (*mask & userBits) | clipBit;
315 *ref = clipBit;
316 break;
317 default:
318 GrCrash("Unknown stencil func");
319 }
320 } else {
321 *mask &= userBits;
322 *ref &= userBits;
323 }
324 }
325}
326
327////////////////////////////////////////////////////////////////////////////////
328
329#define VISUALIZE_COMPLEX_CLIP 0
330
331#if VISUALIZE_COMPLEX_CLIP
332 #include "GrRandom.h"
333 GrRandom gRandom;
334 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU());
335#else
336 #define SET_RANDOM_COLOR
337#endif
338
bsalomon@google.comffca4002011-02-22 20:34:01 +0000339bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000340 const GrIRect* r = NULL;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000341 GrIRect clipRect;
reed@google.comac10a2d2010-12-22 21:39:39 +0000342
bsalomon@google.com2e7b43d2011-01-18 20:57:22 +0000343 // we check this early because we need a valid
344 // render target to setup stencil clipping
345 // before even going into flushGraphicsState
346 if (NULL == fCurrDrawState.fRenderTarget) {
347 GrAssert(!"No render target bound.");
348 return false;
349 }
350
reed@google.comac10a2d2010-12-22 21:39:39 +0000351 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000352 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
353
354 GrRect bounds;
355 GrRect rtRect;
356 rtRect.setLTRB(0, 0,
357 GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000358 if (fClip.hasConservativeBounds()) {
359 bounds = fClip.getConservativeBounds();
bsalomon@google.comd302f142011-03-03 13:54:13 +0000360 bounds.intersectWith(rtRect);
361 } else {
362 bounds = rtRect;
363 }
364
365 bounds.roundOut(&clipRect);
366 if (clipRect.isEmpty()) {
367 clipRect.setLTRB(0,0,0,0);
368 }
369 r = &clipRect;
370
371 fClipState.fClipInStencil = !fClip.isRect() &&
372 !fClip.isEmpty() &&
373 !bounds.isEmpty();
reed@google.comac10a2d2010-12-22 21:39:39 +0000374
375 if (fClipState.fClipInStencil &&
376 (fClipState.fClipIsDirty ||
bsalomon@google.comd302f142011-03-03 13:54:13 +0000377 fClip != rt.fLastStencilClip)) {
378
379 rt.fLastStencilClip = fClip;
380 // we set the current clip to the bounds so that our recursive
381 // draws are scissored to them. We use the copy of the complex clip
382 // in the rt to render
383 const GrClip& clip = rt.fLastStencilClip;
384 fClip.setFromRect(bounds);
reed@google.comac10a2d2010-12-22 21:39:39 +0000385
386 AutoStateRestore asr(this);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000387 AutoInternalDrawGeomRestore aidgr(this);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000388
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000389 this->setViewMatrix(GrMatrix::I());
bsalomon@google.comd302f142011-03-03 13:54:13 +0000390 this->eraseStencilClip(clipRect);
391 this->flushScissor(NULL);
392#if !VISUALIZE_COMPLEX_CLIP
393 this->enableState(kNoColorWrites_StateBit);
394#else
395 this->disableState(kNoColorWrites_StateBit);
396#endif
397 int count = clip.getElementCount();
398 int clipBit = rt.stencilBits();
399 clipBit = (1 << (clipBit-1));
400
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000401 // often we'll see the first two elements of the clip are
402 // the full rt size and another element intersected with it.
403 // We can skip the first full-size rect and save a big rect draw.
404 int firstElement = 0;
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000405 if (clip.getElementCount() > 1 &&
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000406 kRect_ClipType == clip.getElementType(0) &&
407 kIntersect_SetOp == clip.getOp(1)&&
408 clip.getRect(0).contains(bounds)) {
409 firstElement = 1;
410 }
bsalomon@google.com0b50b2e2011-03-08 21:07:21 +0000411
bsalomon@google.comd302f142011-03-03 13:54:13 +0000412 // walk through each clip element and perform its set op
413 // with the existing clip.
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000414 for (int c = firstElement; c < count; ++c) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000415 GrPathFill fill;
416 // enabled at bottom of loop
417 this->disableState(kModifyStencilClip_StateBit);
418
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000419 bool canRenderDirectToStencil; // can the clip element be drawn
420 // directly to the stencil buffer
421 // with a non-inverted fill rule
422 // without extra passes to
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000423 // resolve in/out status.
424
425 GrPathRenderer* pr = NULL;
426 GrPath::Iter pathIter;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000427 if (kRect_ClipType == clip.getElementType(c)) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000428 canRenderDirectToStencil = true;
bsalomon@google.comd302f142011-03-03 13:54:13 +0000429 fill = kEvenOdd_PathFill;
430 } else {
431 fill = clip.getPathFill(c);
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000432 const GrPath& path = clip.getPath(c);
433 pathIter.reset(path);
434 pr = this->getClipPathRenderer(&pathIter, NonInvertedFill(fill));
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000435 canRenderDirectToStencil =
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000436 !pr->requiresStencilPass(this, &pathIter,
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000437 NonInvertedFill(fill));
bsalomon@google.comd302f142011-03-03 13:54:13 +0000438 }
439
bsalomon@google.com5aaa69e2011-03-04 20:29:08 +0000440 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000441 int passes;
442 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
443
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000444 bool canDrawDirectToClip; // Given the renderer, the element,
445 // fill rule, and set operation can
446 // we render the element directly to
447 // stencil bit used for clipping.
448 canDrawDirectToClip =
449 GrStencilSettings::GetClipPasses(op,
450 canRenderDirectToStencil,
451 clipBit,
452 IsFillInverted(fill),
453 &passes, stencilSettings);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000454
455 // draw the element to the client stencil bits if necessary
456 if (!canDrawDirectToClip) {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000457 static const GrStencilSettings gDrawToStencil = {
458 kIncClamp_StencilOp, kIncClamp_StencilOp,
459 kIncClamp_StencilOp, kIncClamp_StencilOp,
460 kAlways_StencilFunc, kAlways_StencilFunc,
461 0xffffffff, 0xffffffff,
462 0x00000000, 0x00000000,
463 0xffffffff, 0xffffffff,
464 };
465 SET_RANDOM_COLOR
bsalomon@google.comd302f142011-03-03 13:54:13 +0000466 if (kRect_ClipType == clip.getElementType(c)) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000467 this->setStencil(gDrawToStencil);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000468 this->drawSimpleRect(clip.getRect(c), NULL, 0);
469 } else {
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000470 if (canRenderDirectToStencil) {
471 this->setStencil(gDrawToStencil);
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000472 pr->drawPath(this, 0,
473 &pathIter,
474 NonInvertedFill(fill),
475 NULL);
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000476 } else {
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000477 pr->drawPathToStencil(this, &pathIter,
478 NonInvertedFill(fill),
479 NULL);
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000480 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000481 }
482 }
483
484 // now we modify the clip bit by rendering either the clip
485 // element directly or a bounding rect of the entire clip.
486 this->enableState(kModifyStencilClip_StateBit);
487 for (int p = 0; p < passes; ++p) {
488 this->setStencil(stencilSettings[p]);
489 if (canDrawDirectToClip) {
490 if (kRect_ClipType == clip.getElementType(c)) {
491 SET_RANDOM_COLOR
492 this->drawSimpleRect(clip.getRect(c), NULL, 0);
493 } else {
494 SET_RANDOM_COLOR
bsalomon@google.com7f5875d2011-03-24 16:55:45 +0000495 GrAssert(!IsFillInverted(fill));
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000496 pr->drawPath(this, 0, &pathIter, fill, NULL);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000497 }
498 } else {
499 SET_RANDOM_COLOR
500 this->drawSimpleRect(bounds, 0, NULL);
501 }
502 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000503 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000504 fClip = clip;
505 // recusive draws would have disabled this.
506 fClipState.fClipInStencil = true;
reed@google.comac10a2d2010-12-22 21:39:39 +0000507 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000508
reed@google.comac10a2d2010-12-22 21:39:39 +0000509 fClipState.fClipIsDirty = false;
reed@google.comac10a2d2010-12-22 21:39:39 +0000510 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000511
reed@google.comac10a2d2010-12-22 21:39:39 +0000512 // Must flush the scissor after graphics state
bsalomon@google.comd302f142011-03-03 13:54:13 +0000513 if (!this->flushGraphicsState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000514 return false;
515 }
bsalomon@google.comd302f142011-03-03 13:54:13 +0000516 this->flushScissor(r);
reed@google.comac10a2d2010-12-22 21:39:39 +0000517 return true;
518}
519
bsalomon@google.comdfe75bc2011-03-25 12:31:16 +0000520GrPathRenderer* GrGpu::getClipPathRenderer(GrPathIter* path,
521 GrPathFill fill) {
522 if (NULL != fClientPathRenderer &&
523 fClientPathRenderer->canDrawPath(this, path, fill)) {
524 return fClientPathRenderer;
525 } else {
526 if (NULL == fDefaultPathRenderer) {
527 fDefaultPathRenderer =
528 new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
529 this->supportsStencilWrapOps());
530 }
531 GrAssert(fDefaultPathRenderer->canDrawPath(this, path, fill));
532 return fDefaultPathRenderer;
533 }
534}
535
536
bsalomon@google.comd302f142011-03-03 13:54:13 +0000537////////////////////////////////////////////////////////////////////////////////
reed@google.comac10a2d2010-12-22 21:39:39 +0000538
bsalomon@google.comffca4002011-02-22 20:34:01 +0000539void GrGpu::drawIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000540 int startVertex,
541 int startIndex,
542 int vertexCount,
543 int indexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000544 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
545 fReservedGeometry.fLocked);
546 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
547 fReservedGeometry.fLocked);
548
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000549 this->handleDirtyContext();
550
551 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000552 return;
553 }
554
555#if GR_COLLECT_STATS
556 fStats.fVertexCnt += vertexCount;
557 fStats.fIndexCnt += indexCount;
558 fStats.fDrawCnt += 1;
559#endif
560
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000561 int sVertex = startVertex;
562 int sIndex = startIndex;
563 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000564
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000565 drawIndexedHelper(type, sVertex, sIndex,
reed@google.comac10a2d2010-12-22 21:39:39 +0000566 vertexCount, indexCount);
567}
568
bsalomon@google.comffca4002011-02-22 20:34:01 +0000569void GrGpu::drawNonIndexed(GrPrimitiveType type,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000570 int startVertex,
571 int vertexCount) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000572 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
573 fReservedGeometry.fLocked);
574
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000575 this->handleDirtyContext();
576
577 if (!this->setupClipAndFlushState(type)) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000578 return;
579 }
580#if GR_COLLECT_STATS
581 fStats.fVertexCnt += vertexCount;
582 fStats.fDrawCnt += 1;
583#endif
584
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000585 int sVertex = startVertex;
586 setupGeometry(&sVertex, NULL, vertexCount, 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000587
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000588 drawNonIndexedHelper(type, sVertex, vertexCount);
589}
590
591void GrGpu::finalizeReservedVertices() {
592 GrAssert(NULL != fVertexPool);
593 fVertexPool->unlock();
594}
595
596void GrGpu::finalizeReservedIndices() {
597 GrAssert(NULL != fIndexPool);
598 fIndexPool->unlock();
599}
600
601void GrGpu::prepareVertexPool() {
602 if (NULL == fVertexPool) {
bsalomon@google.comd302f142011-03-03 13:54:13 +0000603 fVertexPool = new GrVertexBufferAllocPool(this, true,
604 VERTEX_POOL_VB_SIZE,
bsalomon@google.com7a5af8b2011-02-18 18:40:42 +0000605 VERTEX_POOL_VB_COUNT);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000606 } else if (!fVertexPoolInUse) {
607 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000608 fVertexPool->reset();
609 }
610}
611
612void GrGpu::prepareIndexPool() {
613 if (NULL == fVertexPool) {
614 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
bsalomon@google.comd302f142011-03-03 13:54:13 +0000615 } else if (!fIndexPoolInUse) {
616 // the client doesn't have valid data in the pool
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000617 fIndexPool->reset();
618 }
reed@google.comac10a2d2010-12-22 21:39:39 +0000619}
620
621bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
622 void** vertices,
623 void** indices) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000624 GrAssert(!fReservedGeometry.fLocked);
625 size_t reservedVertexSpace = 0;
626
627 if (fReservedGeometry.fVertexCount) {
628 GrAssert(NULL != vertices);
629
bsalomon@google.comd302f142011-03-03 13:54:13 +0000630 this->prepareVertexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000631
632 *vertices = fVertexPool->makeSpace(vertexLayout,
633 fReservedGeometry.fVertexCount,
634 &fCurrPoolVertexBuffer,
635 &fCurrPoolStartVertex);
636 if (NULL == *vertices) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000637 return false;
638 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000639 reservedVertexSpace = VertexSize(vertexLayout) *
640 fReservedGeometry.fVertexCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000641 }
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000642 if (fReservedGeometry.fIndexCount) {
643 GrAssert(NULL != indices);
644
bsalomon@google.comd302f142011-03-03 13:54:13 +0000645 this->prepareIndexPool();
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000646
647 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
648 &fCurrPoolIndexBuffer,
649 &fCurrPoolStartIndex);
650 if (NULL == *indices) {
651 fVertexPool->putBack(reservedVertexSpace);
652 fCurrPoolVertexBuffer = NULL;
reed@google.comac10a2d2010-12-22 21:39:39 +0000653 return false;
654 }
655 }
656 return true;
657}
658
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000659void GrGpu::releaseGeometryHelper() {}
660
661void GrGpu::setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) {
662 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
663 prepareVertexPool();
664#if GR_DEBUG
665 bool success =
666#endif
667 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
668 vertexCount,
669 vertexArray,
670 &fCurrPoolVertexBuffer,
671 &fCurrPoolStartVertex);
672 GR_DEBUGASSERT(success);
673}
674
675void GrGpu::setIndexSourceToArrayHelper(const void* indexArray, int indexCount) {
676 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
677 prepareIndexPool();
678#if GR_DEBUG
679 bool success =
680#endif
681 fIndexPool->appendIndices(indexCount,
682 indexArray,
683 &fCurrPoolIndexBuffer,
684 &fCurrPoolStartIndex);
685 GR_DEBUGASSERT(success);
reed@google.comac10a2d2010-12-22 21:39:39 +0000686}
687
bsalomon@google.comd302f142011-03-03 13:54:13 +0000688////////////////////////////////////////////////////////////////////////////////
689
reed@google.comac10a2d2010-12-22 21:39:39 +0000690const GrGpu::Stats& GrGpu::getStats() const {
691 return fStats;
692}
693
694void GrGpu::resetStats() {
695 memset(&fStats, 0, sizeof(fStats));
696}
697
698void GrGpu::printStats() const {
699 if (GR_COLLECT_STATS) {
700 GrPrintf(
701 "-v-------------------------GPU STATS----------------------------v-\n"
702 "Stats collection is: %s\n"
703 "Draws: %04d, Verts: %04d, Indices: %04d\n"
704 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
705 "TexCreates: %04d, RTCreates:%04d\n"
706 "-^--------------------------------------------------------------^-\n",
707 (GR_COLLECT_STATS ? "ON" : "OFF"),
708 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
709 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
710 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
711 }
712}
713
714////////////////////////////////////////////////////////////////////////////////
715
716GrTexture::~GrTexture() {
717 // use this to set a break-point if needed
718// Gr_clz(3);
719}
720
721const GrSamplerState GrSamplerState::gClampNoFilter(
722 GrSamplerState::kClamp_WrapMode,
723 GrSamplerState::kClamp_WrapMode,
724 GrSamplerState::kNormal_SampleMode,
bsalomon@google.comc6cf7232011-02-17 16:43:10 +0000725 GrMatrix::I(),
reed@google.comac10a2d2010-12-22 21:39:39 +0000726 false);
727
728
729
730