1 /*
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 #include "GrGpu.h"
18 #include "GrMemory.h"
19 #include "GrTextStrike.h"
20 #include "GrTextureCache.h"
21 #include "GrClipIterator.h"
22 #include "GrIndexBuffer.h"
23 #include "GrVertexBuffer.h"
24 #include "GrBufferAllocPool.h"
25 #include "GrPathRenderer.h"
26
27 // probably makes no sense for this to be less than a page
28 static const size_t VERTEX_POOL_VB_SIZE = 1 << 12;
29 static const int VERTEX_POOL_VB_COUNT = 1;
30
31
32 ////////////////////////////////////////////////////////////////////////////////
33
34 extern void gr_run_unittests();
35
GrGpu()36 GrGpu::GrGpu()
37 : f8bitPaletteSupport(false)
38 , fCurrPoolVertexBuffer(NULL)
39 , fCurrPoolStartVertex(0)
40 , fCurrPoolIndexBuffer(NULL)
41 , fCurrPoolStartIndex(0)
42 , fContext(NULL)
43 , fVertexPool(NULL)
44 , fIndexPool(NULL)
45 , fQuadIndexBuffer(NULL)
46 , fUnitSquareVertexBuffer(NULL)
47 , fDefaultPathRenderer(NULL)
48 , fClientPathRenderer(NULL)
49 , fContextIsDirty(true)
50 , fVertexPoolInUse(false)
51 , fIndexPoolInUse(false)
52 , fResourceHead(NULL) {
53
54 #if GR_DEBUG
55 //gr_run_unittests();
56 #endif
57 resetStats();
58 }
59
~GrGpu()60 GrGpu::~GrGpu() {
61 releaseResources();
62 }
63
abandonResources()64 void GrGpu::abandonResources() {
65
66 while (NULL != fResourceHead) {
67 fResourceHead->abandon();
68 }
69
70 GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
71 GrAssert(NULL == fUnitSquareVertexBuffer ||
72 !fUnitSquareVertexBuffer->isValid());
73 GrSafeSetNull(fQuadIndexBuffer);
74 GrSafeSetNull(fUnitSquareVertexBuffer);
75 delete fVertexPool;
76 fVertexPool = NULL;
77 delete fIndexPool;
78 fIndexPool = NULL;
79 }
80
releaseResources()81 void GrGpu::releaseResources() {
82
83 while (NULL != fResourceHead) {
84 fResourceHead->release();
85 }
86
87 GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid());
88 GrAssert(NULL == fUnitSquareVertexBuffer ||
89 !fUnitSquareVertexBuffer->isValid());
90 GrSafeSetNull(fQuadIndexBuffer);
91 GrSafeSetNull(fUnitSquareVertexBuffer);
92 delete fVertexPool;
93 fVertexPool = NULL;
94 delete fIndexPool;
95 fIndexPool = NULL;
96 }
97
insertResource(GrResource * resource)98 void GrGpu::insertResource(GrResource* resource) {
99 GrAssert(NULL != resource);
100 GrAssert(this == resource->getGpu());
101 GrAssert(NULL == resource->fNext);
102 GrAssert(NULL == resource->fPrevious);
103
104 resource->fNext = fResourceHead;
105 if (NULL != fResourceHead) {
106 GrAssert(NULL == fResourceHead->fPrevious);
107 fResourceHead->fPrevious = resource;
108 }
109 fResourceHead = resource;
110 }
111
removeResource(GrResource * resource)112 void GrGpu::removeResource(GrResource* resource) {
113 GrAssert(NULL != resource);
114 GrAssert(NULL != fResourceHead);
115
116 if (fResourceHead == resource) {
117 GrAssert(NULL == resource->fPrevious);
118 fResourceHead = resource->fNext;
119 } else {
120 GrAssert(NULL != fResourceHead);
121 resource->fPrevious->fNext = resource->fNext;
122 }
123 if (NULL != resource->fNext) {
124 resource->fNext->fPrevious = resource->fPrevious;
125 }
126 resource->fNext = NULL;
127 resource->fPrevious = NULL;
128 }
129
130
unimpl(const char msg[])131 void GrGpu::unimpl(const char msg[]) {
132 #if GR_DEBUG
133 GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
134 #endif
135 }
136
137 ////////////////////////////////////////////////////////////////////////////////
138
createTexture(const GrTextureDesc & desc,const void * srcData,size_t rowBytes)139 GrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
140 const void* srcData, size_t rowBytes) {
141 this->handleDirtyContext();
142 return this->onCreateTexture(desc, srcData, rowBytes);
143 }
144
createRenderTargetFrom3DApiState()145 GrRenderTarget* GrGpu::createRenderTargetFrom3DApiState() {
146 this->handleDirtyContext();
147 return this->onCreateRenderTargetFrom3DApiState();
148 }
149
createPlatformSurface(const GrPlatformSurfaceDesc & desc)150 GrResource* GrGpu::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
151 this->handleDirtyContext();
152 return this->onCreatePlatformSurface(desc);
153 }
154
createVertexBuffer(uint32_t size,bool dynamic)155 GrVertexBuffer* GrGpu::createVertexBuffer(uint32_t size, bool dynamic) {
156 this->handleDirtyContext();
157 return this->onCreateVertexBuffer(size, dynamic);
158 }
159
createIndexBuffer(uint32_t size,bool dynamic)160 GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) {
161 this->handleDirtyContext();
162 return this->onCreateIndexBuffer(size, dynamic);
163 }
164
clear(const GrIRect * rect,GrColor color)165 void GrGpu::clear(const GrIRect* rect, GrColor color) {
166 this->handleDirtyContext();
167 this->onClear(rect, color);
168 }
169
forceRenderTargetFlush()170 void GrGpu::forceRenderTargetFlush() {
171 this->handleDirtyContext();
172 this->onForceRenderTargetFlush();
173 }
174
readPixels(GrRenderTarget * target,int left,int top,int width,int height,GrPixelConfig config,void * buffer)175 bool GrGpu::readPixels(GrRenderTarget* target,
176 int left, int top, int width, int height,
177 GrPixelConfig config, void* buffer) {
178
179 this->handleDirtyContext();
180 return this->onReadPixels(target, left, top, width, height, config, buffer);
181 }
182
183 ////////////////////////////////////////////////////////////////////////////////
184
185 static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1;
186
187 GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535);
188
fill_indices(uint16_t * indices,int quadCount)189 static inline void fill_indices(uint16_t* indices, int quadCount) {
190 for (int i = 0; i < quadCount; ++i) {
191 indices[6 * i + 0] = 4 * i + 0;
192 indices[6 * i + 1] = 4 * i + 1;
193 indices[6 * i + 2] = 4 * i + 2;
194 indices[6 * i + 3] = 4 * i + 0;
195 indices[6 * i + 4] = 4 * i + 2;
196 indices[6 * i + 5] = 4 * i + 3;
197 }
198 }
199
getQuadIndexBuffer() const200 const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
201 if (NULL == fQuadIndexBuffer) {
202 static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
203 GrGpu* me = const_cast<GrGpu*>(this);
204 fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
205 if (NULL != fQuadIndexBuffer) {
206 uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
207 if (NULL != indices) {
208 fill_indices(indices, MAX_QUADS);
209 fQuadIndexBuffer->unlock();
210 } else {
211 indices = (uint16_t*)GrMalloc(SIZE);
212 fill_indices(indices, MAX_QUADS);
213 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
214 fQuadIndexBuffer->unref();
215 fQuadIndexBuffer = NULL;
216 GrCrash("Can't get indices into buffer!");
217 }
218 GrFree(indices);
219 }
220 }
221 }
222
223 return fQuadIndexBuffer;
224 }
225
getUnitSquareVertexBuffer() const226 const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const {
227 if (NULL == fUnitSquareVertexBuffer) {
228
229 static const GrPoint DATA[] = {
230 { 0, 0 },
231 { GR_Scalar1, 0 },
232 { GR_Scalar1, GR_Scalar1 },
233 { 0, GR_Scalar1 }
234 #if 0
235 GrPoint(0, 0),
236 GrPoint(GR_Scalar1,0),
237 GrPoint(GR_Scalar1,GR_Scalar1),
238 GrPoint(0, GR_Scalar1)
239 #endif
240 };
241 static const size_t SIZE = sizeof(DATA);
242
243 GrGpu* me = const_cast<GrGpu*>(this);
244 fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
245 if (NULL != fUnitSquareVertexBuffer) {
246 if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
247 fUnitSquareVertexBuffer->unref();
248 fUnitSquareVertexBuffer = NULL;
249 GrCrash("Can't get vertices into buffer!");
250 }
251 }
252 }
253
254 return fUnitSquareVertexBuffer;
255 }
256
257 ////////////////////////////////////////////////////////////////////////////////
258
clipWillBeSet(const GrClip & newClip)259 void GrGpu::clipWillBeSet(const GrClip& newClip) {
260 if (newClip != fClip) {
261 fClipState.fClipIsDirty = true;
262 }
263 }
264
265 ////////////////////////////////////////////////////////////////////////////////
266
267 // stencil settings to use when clip is in stencil
268 const GrStencilSettings GrGpu::gClipStencilSettings = {
269 kKeep_StencilOp, kKeep_StencilOp,
270 kKeep_StencilOp, kKeep_StencilOp,
271 kAlwaysIfInClip_StencilFunc, kAlwaysIfInClip_StencilFunc,
272 0, 0,
273 0, 0,
274 0, 0
275 };
276
277 // mapping of clip-respecting stencil funcs to normal stencil funcs
278 // mapping depends on whether stencil-clipping is in effect.
279 static const GrStencilFunc gGrClipToNormalStencilFunc[2][kClipStencilFuncCount] = {
280 {// Stencil-Clipping is DISABLED, effectively always inside the clip
281 // In the Clip Funcs
282 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc
283 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
284 kLess_StencilFunc, // kLessIfInClip_StencilFunc
285 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
286 // Special in the clip func that forces user's ref to be 0.
287 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc
288 // make ref 0 and do normal nequal.
289 },
290 {// Stencil-Clipping is ENABLED
291 // In the Clip Funcs
292 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc
293 // eq stencil clip bit, mask
294 // out user bits.
295
296 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc
297 // add stencil bit to mask and ref
298
299 kLess_StencilFunc, // kLessIfInClip_StencilFunc
300 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc
301 // for both of these we can add
302 // the clip bit to the mask and
303 // ref and compare as normal
304 // Special in the clip func that forces user's ref to be 0.
305 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc
306 // make ref have only the clip bit set
307 // and make comparison be less
308 // 10..0 < 1..user_bits..
309 }
310 };
311
ConvertStencilFunc(bool stencilInClip,GrStencilFunc func)312 GrStencilFunc GrGpu::ConvertStencilFunc(bool stencilInClip, GrStencilFunc func) {
313 GrAssert(func >= 0);
314 if (func >= kBasicStencilFuncCount) {
315 GrAssert(func < kStencilFuncCount);
316 func = gGrClipToNormalStencilFunc[stencilInClip ? 1 : 0][func - kBasicStencilFuncCount];
317 GrAssert(func >= 0 && func < kBasicStencilFuncCount);
318 }
319 return func;
320 }
321
ConvertStencilFuncAndMask(GrStencilFunc func,bool clipInStencil,unsigned int clipBit,unsigned int userBits,unsigned int * ref,unsigned int * mask)322 void GrGpu::ConvertStencilFuncAndMask(GrStencilFunc func,
323 bool clipInStencil,
324 unsigned int clipBit,
325 unsigned int userBits,
326 unsigned int* ref,
327 unsigned int* mask) {
328 if (func < kBasicStencilFuncCount) {
329 *mask &= userBits;
330 *ref &= userBits;
331 } else {
332 if (clipInStencil) {
333 switch (func) {
334 case kAlwaysIfInClip_StencilFunc:
335 *mask = clipBit;
336 *ref = clipBit;
337 break;
338 case kEqualIfInClip_StencilFunc:
339 case kLessIfInClip_StencilFunc:
340 case kLEqualIfInClip_StencilFunc:
341 *mask = (*mask & userBits) | clipBit;
342 *ref = (*ref & userBits) | clipBit;
343 break;
344 case kNonZeroIfInClip_StencilFunc:
345 *mask = (*mask & userBits) | clipBit;
346 *ref = clipBit;
347 break;
348 default:
349 GrCrash("Unknown stencil func");
350 }
351 } else {
352 *mask &= userBits;
353 *ref &= userBits;
354 }
355 }
356 }
357
358 ////////////////////////////////////////////////////////////////////////////////
359
360 #define VISUALIZE_COMPLEX_CLIP 0
361
362 #if VISUALIZE_COMPLEX_CLIP
363 #include "GrRandom.h"
364 GrRandom gRandom;
365 #define SET_RANDOM_COLOR this->setColor(0xff000000 | gRandom.nextU());
366 #else
367 #define SET_RANDOM_COLOR
368 #endif
369
setupClipAndFlushState(GrPrimitiveType type)370 bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
371 const GrIRect* r = NULL;
372 GrIRect clipRect;
373
374 // we check this early because we need a valid
375 // render target to setup stencil clipping
376 // before even going into flushGraphicsState
377 if (NULL == fCurrDrawState.fRenderTarget) {
378 GrAssert(!"No render target bound.");
379 return false;
380 }
381
382 if (fCurrDrawState.fFlagBits & kClip_StateBit) {
383 GrRenderTarget& rt = *fCurrDrawState.fRenderTarget;
384
385 GrRect bounds;
386 GrRect rtRect;
387 rtRect.setLTRB(0, 0,
388 GrIntToScalar(rt.width()), GrIntToScalar(rt.height()));
389 if (fClip.hasConservativeBounds()) {
390 bounds = fClip.getConservativeBounds();
391 if (!bounds.intersect(rtRect)) {
392 bounds.setEmpty();
393 }
394 } else {
395 bounds = rtRect;
396 }
397
398 bounds.roundOut(&clipRect);
399 if (clipRect.isEmpty()) {
400 clipRect.setLTRB(0,0,0,0);
401 }
402 r = &clipRect;
403
404 fClipState.fClipInStencil = !fClip.isRect() &&
405 !fClip.isEmpty() &&
406 !bounds.isEmpty();
407
408 if (fClipState.fClipInStencil &&
409 (fClipState.fClipIsDirty ||
410 fClip != rt.fLastStencilClip)) {
411
412 rt.fLastStencilClip = fClip;
413 // we set the current clip to the bounds so that our recursive
414 // draws are scissored to them. We use the copy of the complex clip
415 // in the rt to render
416 const GrClip& clip = rt.fLastStencilClip;
417 fClip.setFromRect(bounds);
418
419 AutoStateRestore asr(this);
420 AutoInternalDrawGeomRestore aidgr(this);
421
422 this->setViewMatrix(GrMatrix::I());
423 this->clearStencilClip(clipRect);
424 this->flushScissor(NULL);
425 #if !VISUALIZE_COMPLEX_CLIP
426 this->enableState(kNoColorWrites_StateBit);
427 #else
428 this->disableState(kNoColorWrites_StateBit);
429 #endif
430 int count = clip.getElementCount();
431 int clipBit = rt.stencilBits();
432 clipBit = (1 << (clipBit-1));
433
434 // often we'll see the first two elements of the clip are
435 // the full rt size and another element intersected with it.
436 // We can skip the first full-size rect and save a big rect draw.
437 int firstElement = 0;
438 if (clip.getElementCount() > 1 &&
439 kRect_ClipType == clip.getElementType(0) &&
440 kIntersect_SetOp == clip.getOp(1)&&
441 clip.getRect(0).contains(bounds)) {
442 firstElement = 1;
443 }
444
445 // walk through each clip element and perform its set op
446 // with the existing clip.
447 for (int c = firstElement; c < count; ++c) {
448 GrPathFill fill;
449 // enabled at bottom of loop
450 this->disableState(kModifyStencilClip_StateBit);
451
452 bool canRenderDirectToStencil; // can the clip element be drawn
453 // directly to the stencil buffer
454 // with a non-inverted fill rule
455 // without extra passes to
456 // resolve in/out status.
457
458 GrPathRenderer* pr = NULL;
459 const GrPath* clipPath = NULL;
460 if (kRect_ClipType == clip.getElementType(c)) {
461 canRenderDirectToStencil = true;
462 fill = kEvenOdd_PathFill;
463 } else {
464 fill = clip.getPathFill(c);
465 clipPath = &clip.getPath(c);
466 pr = this->getClipPathRenderer(*clipPath, NonInvertedFill(fill));
467 canRenderDirectToStencil =
468 !pr->requiresStencilPass(this, *clipPath,
469 NonInvertedFill(fill));
470 }
471
472 GrSetOp op = firstElement == c ? kReplace_SetOp : clip.getOp(c);
473 int passes;
474 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
475
476 bool canDrawDirectToClip; // Given the renderer, the element,
477 // fill rule, and set operation can
478 // we render the element directly to
479 // stencil bit used for clipping.
480 canDrawDirectToClip =
481 GrStencilSettings::GetClipPasses(op,
482 canRenderDirectToStencil,
483 clipBit,
484 IsFillInverted(fill),
485 &passes, stencilSettings);
486
487 // draw the element to the client stencil bits if necessary
488 if (!canDrawDirectToClip) {
489 static const GrStencilSettings gDrawToStencil = {
490 kIncClamp_StencilOp, kIncClamp_StencilOp,
491 kIncClamp_StencilOp, kIncClamp_StencilOp,
492 kAlways_StencilFunc, kAlways_StencilFunc,
493 0xffffffff, 0xffffffff,
494 0x00000000, 0x00000000,
495 0xffffffff, 0xffffffff,
496 };
497 SET_RANDOM_COLOR
498 if (kRect_ClipType == clip.getElementType(c)) {
499 this->setStencil(gDrawToStencil);
500 this->drawSimpleRect(clip.getRect(c), NULL, 0);
501 } else {
502 if (canRenderDirectToStencil) {
503 this->setStencil(gDrawToStencil);
504 pr->drawPath(this, 0, *clipPath, NonInvertedFill(fill),
505 NULL);
506 } else {
507 pr->drawPathToStencil(this, *clipPath,
508 NonInvertedFill(fill),
509 NULL);
510 }
511 }
512 }
513
514 // now we modify the clip bit by rendering either the clip
515 // element directly or a bounding rect of the entire clip.
516 this->enableState(kModifyStencilClip_StateBit);
517 for (int p = 0; p < passes; ++p) {
518 this->setStencil(stencilSettings[p]);
519 if (canDrawDirectToClip) {
520 if (kRect_ClipType == clip.getElementType(c)) {
521 SET_RANDOM_COLOR
522 this->drawSimpleRect(clip.getRect(c), NULL, 0);
523 } else {
524 SET_RANDOM_COLOR
525 GrAssert(!IsFillInverted(fill));
526 pr->drawPath(this, 0, *clipPath, fill, NULL);
527 }
528 } else {
529 SET_RANDOM_COLOR
530 this->drawSimpleRect(bounds, NULL, 0);
531 }
532 }
533 }
534 fClip = clip;
535 // recusive draws would have disabled this.
536 fClipState.fClipInStencil = true;
537 }
538
539 fClipState.fClipIsDirty = false;
540 }
541
542 // Must flush the scissor after graphics state
543 if (!this->flushGraphicsState(type)) {
544 return false;
545 }
546 this->flushScissor(r);
547 return true;
548 }
549
getClipPathRenderer(const GrPath & path,GrPathFill fill)550 GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
551 GrPathFill fill) {
552 if (NULL != fClientPathRenderer &&
553 fClientPathRenderer->canDrawPath(this, path, fill)) {
554 return fClientPathRenderer;
555 } else {
556 if (NULL == fDefaultPathRenderer) {
557 fDefaultPathRenderer =
558 new GrDefaultPathRenderer(this->supportsTwoSidedStencil(),
559 this->supportsStencilWrapOps());
560 }
561 GrAssert(fDefaultPathRenderer->canDrawPath(this, path, fill));
562 return fDefaultPathRenderer;
563 }
564 }
565
566
567 ////////////////////////////////////////////////////////////////////////////////
568
drawIndexed(GrPrimitiveType type,int startVertex,int startIndex,int vertexCount,int indexCount)569 void GrGpu::drawIndexed(GrPrimitiveType type,
570 int startVertex,
571 int startIndex,
572 int vertexCount,
573 int indexCount) {
574 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
575 fReservedGeometry.fLocked);
576 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
577 fReservedGeometry.fLocked);
578
579 this->handleDirtyContext();
580
581 if (!this->setupClipAndFlushState(type)) {
582 return;
583 }
584
585 #if GR_COLLECT_STATS
586 fStats.fVertexCnt += vertexCount;
587 fStats.fIndexCnt += indexCount;
588 fStats.fDrawCnt += 1;
589 #endif
590
591 int sVertex = startVertex;
592 int sIndex = startIndex;
593 setupGeometry(&sVertex, &sIndex, vertexCount, indexCount);
594
595 this->onDrawIndexed(type, sVertex, sIndex,
596 vertexCount, indexCount);
597 }
598
drawNonIndexed(GrPrimitiveType type,int startVertex,int vertexCount)599 void GrGpu::drawNonIndexed(GrPrimitiveType type,
600 int startVertex,
601 int vertexCount) {
602 GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
603 fReservedGeometry.fLocked);
604
605 this->handleDirtyContext();
606
607 if (!this->setupClipAndFlushState(type)) {
608 return;
609 }
610 #if GR_COLLECT_STATS
611 fStats.fVertexCnt += vertexCount;
612 fStats.fDrawCnt += 1;
613 #endif
614
615 int sVertex = startVertex;
616 setupGeometry(&sVertex, NULL, vertexCount, 0);
617
618 this->onDrawNonIndexed(type, sVertex, vertexCount);
619 }
620
finalizeReservedVertices()621 void GrGpu::finalizeReservedVertices() {
622 GrAssert(NULL != fVertexPool);
623 fVertexPool->unlock();
624 }
625
finalizeReservedIndices()626 void GrGpu::finalizeReservedIndices() {
627 GrAssert(NULL != fIndexPool);
628 fIndexPool->unlock();
629 }
630
prepareVertexPool()631 void GrGpu::prepareVertexPool() {
632 if (NULL == fVertexPool) {
633 fVertexPool = new GrVertexBufferAllocPool(this, true,
634 VERTEX_POOL_VB_SIZE,
635 VERTEX_POOL_VB_COUNT);
636 fVertexPool->releaseGpuRef();
637 } else if (!fVertexPoolInUse) {
638 // the client doesn't have valid data in the pool
639 fVertexPool->reset();
640 }
641 }
642
prepareIndexPool()643 void GrGpu::prepareIndexPool() {
644 if (NULL == fIndexPool) {
645 fIndexPool = new GrIndexBufferAllocPool(this, true, 0, 1);
646 fIndexPool->releaseGpuRef();
647 } else if (!fIndexPoolInUse) {
648 // the client doesn't have valid data in the pool
649 fIndexPool->reset();
650 }
651 }
652
onAcquireGeometry(GrVertexLayout vertexLayout,void ** vertices,void ** indices)653 bool GrGpu::onAcquireGeometry(GrVertexLayout vertexLayout,
654 void** vertices,
655 void** indices) {
656 GrAssert(!fReservedGeometry.fLocked);
657 size_t reservedVertexSpace = 0;
658
659 if (fReservedGeometry.fVertexCount) {
660 GrAssert(NULL != vertices);
661
662 this->prepareVertexPool();
663
664 *vertices = fVertexPool->makeSpace(vertexLayout,
665 fReservedGeometry.fVertexCount,
666 &fCurrPoolVertexBuffer,
667 &fCurrPoolStartVertex);
668 if (NULL == *vertices) {
669 return false;
670 }
671 reservedVertexSpace = VertexSize(vertexLayout) *
672 fReservedGeometry.fVertexCount;
673 }
674 if (fReservedGeometry.fIndexCount) {
675 GrAssert(NULL != indices);
676
677 this->prepareIndexPool();
678
679 *indices = fIndexPool->makeSpace(fReservedGeometry.fIndexCount,
680 &fCurrPoolIndexBuffer,
681 &fCurrPoolStartIndex);
682 if (NULL == *indices) {
683 fVertexPool->putBack(reservedVertexSpace);
684 fCurrPoolVertexBuffer = NULL;
685 return false;
686 }
687 }
688 return true;
689 }
690
onReleaseGeometry()691 void GrGpu::onReleaseGeometry() {}
692
onSetVertexSourceToArray(const void * vertexArray,int vertexCount)693 void GrGpu::onSetVertexSourceToArray(const void* vertexArray, int vertexCount) {
694 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
695 this->prepareVertexPool();
696 #if GR_DEBUG
697 bool success =
698 #endif
699 fVertexPool->appendVertices(fGeometrySrc.fVertexLayout,
700 vertexCount,
701 vertexArray,
702 &fCurrPoolVertexBuffer,
703 &fCurrPoolStartVertex);
704 GR_DEBUGASSERT(success);
705 }
706
onSetIndexSourceToArray(const void * indexArray,int indexCount)707 void GrGpu::onSetIndexSourceToArray(const void* indexArray, int indexCount) {
708 GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
709 this->prepareIndexPool();
710 #if GR_DEBUG
711 bool success =
712 #endif
713 fIndexPool->appendIndices(indexCount,
714 indexArray,
715 &fCurrPoolIndexBuffer,
716 &fCurrPoolStartIndex);
717 GR_DEBUGASSERT(success);
718 }
719
720 ////////////////////////////////////////////////////////////////////////////////
721
getStats() const722 const GrGpuStats& GrGpu::getStats() const {
723 return fStats;
724 }
725
resetStats()726 void GrGpu::resetStats() {
727 memset(&fStats, 0, sizeof(fStats));
728 }
729
printStats() const730 void GrGpu::printStats() const {
731 if (GR_COLLECT_STATS) {
732 GrPrintf(
733 "-v-------------------------GPU STATS----------------------------v-\n"
734 "Stats collection is: %s\n"
735 "Draws: %04d, Verts: %04d, Indices: %04d\n"
736 "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
737 "TexCreates: %04d, RTCreates:%04d\n"
738 "-^--------------------------------------------------------------^-\n",
739 (GR_COLLECT_STATS ? "ON" : "OFF"),
740 fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
741 fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
742 fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
743 }
744 }
745
746 ////////////////////////////////////////////////////////////////////////////////
747 const GrSamplerState GrSamplerState::gClampNoFilter(
748 GrSamplerState::kClamp_WrapMode,
749 GrSamplerState::kClamp_WrapMode,
750 GrSamplerState::kNormal_SampleMode,
751 GrMatrix::I(),
752 GrSamplerState::kNearest_Filter);
753
754
755
756
757