• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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