• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright 2011 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 "GrInOrderDrawBuffer.h"
19 #include "GrTexture.h"
20 #include "GrBufferAllocPool.h"
21 #include "GrIndexBuffer.h"
22 #include "GrVertexBuffer.h"
23 #include "GrGpu.h"
24 
GrInOrderDrawBuffer(GrVertexBufferAllocPool * vertexPool,GrIndexBufferAllocPool * indexPool)25 GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
26                                          GrIndexBufferAllocPool* indexPool) :
27         fDraws(&fDrawStorage),
28         fStates(&fStateStorage),
29         fClears(&fClearStorage),
30         fClips(&fClipStorage),
31         fClipSet(true),
32 
33         fLastRectVertexLayout(0),
34         fQuadIndexBuffer(NULL),
35         fMaxQuads(0),
36         fCurrQuad(0),
37 
38         fVertexPool(*vertexPool),
39         fCurrPoolVertexBuffer(NULL),
40         fCurrPoolStartVertex(0),
41         fIndexPool(*indexPool),
42         fCurrPoolIndexBuffer(NULL),
43         fCurrPoolStartIndex(0),
44         fReservedVertexBytes(0),
45         fReservedIndexBytes(0),
46         fUsedReservedVertexBytes(0),
47         fUsedReservedIndexBytes(0) {
48     GrAssert(NULL != vertexPool);
49     GrAssert(NULL != indexPool);
50 }
51 
~GrInOrderDrawBuffer()52 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
53     this->reset();
54     GrSafeUnref(fQuadIndexBuffer);
55 }
56 
initializeDrawStateAndClip(const GrDrawTarget & target)57 void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
58     this->copyDrawState(target);
59     this->setClip(target.getClip());
60 }
61 
setQuadIndexBuffer(const GrIndexBuffer * indexBuffer)62 void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) {
63     bool newIdxBuffer = fQuadIndexBuffer != indexBuffer;
64     if (newIdxBuffer) {
65         GrSafeUnref(fQuadIndexBuffer);
66         fQuadIndexBuffer = indexBuffer;
67         GrSafeRef(fQuadIndexBuffer);
68         fCurrQuad = 0;
69         fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads();
70     } else {
71         GrAssert((NULL == indexBuffer && 0 == fMaxQuads) ||
72                  (indexBuffer->maxQuads() == fMaxQuads));
73     }
74 }
75 
drawRect(const GrRect & rect,const GrMatrix * matrix,StageBitfield stageEnableBitfield,const GrRect * srcRects[],const GrMatrix * srcMatrices[])76 void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
77                                    const GrMatrix* matrix,
78                                    StageBitfield stageEnableBitfield,
79                                    const GrRect* srcRects[],
80                                    const GrMatrix* srcMatrices[]) {
81 
82     GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad));
83     GrAssert(!(fDraws.empty() && fCurrQuad));
84     GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer));
85 
86     // if we have a quad IB then either append to the previous run of
87     // rects or start a new run
88     if (fMaxQuads) {
89 
90         bool appendToPreviousDraw = false;
91         GrVertexLayout layout = GetRectVertexLayout(stageEnableBitfield, srcRects);
92         AutoReleaseGeometry geo(this, layout, 4, 0);
93         AutoViewMatrixRestore avmr(this);
94         GrMatrix combinedMatrix = this->getViewMatrix();
95         this->setViewMatrix(GrMatrix::I());
96         if (NULL != matrix) {
97             combinedMatrix.preConcat(*matrix);
98         }
99 
100         SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices());
101 
102         // we don't want to miss an opportunity to batch rects together
103         // simply because the clip has changed if the clip doesn't affect
104         // the rect.
105         bool disabledClip = false;
106         if (this->isClipState() && fClip.isRect()) {
107 
108             GrRect clipRect = fClip.getRect(0);
109             // If the clip rect touches the edge of the viewport, extended it
110             // out (close) to infinity to avoid bogus intersections.
111             // We might consider a more exact clip to viewport if this
112             // conservative test fails.
113             const GrRenderTarget* target = this->getRenderTarget();
114             if (0 >= clipRect.fLeft) {
115                 clipRect.fLeft = GR_ScalarMin;
116             }
117             if (target->width() <= clipRect.fRight) {
118                 clipRect.fRight = GR_ScalarMax;
119             }
120             if (0 >= clipRect.top()) {
121                 clipRect.fTop = GR_ScalarMin;
122             }
123             if (target->height() <= clipRect.fBottom) {
124                 clipRect.fBottom = GR_ScalarMax;
125             }
126             int stride = VertexSize(layout);
127             bool insideClip = true;
128             for (int v = 0; v < 4; ++v) {
129                 const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride);
130                 if (!clipRect.contains(p)) {
131                     insideClip = false;
132                     break;
133                 }
134             }
135             if (insideClip) {
136                 this->disableState(kClip_StateBit);
137                 disabledClip = true;
138             }
139         }
140         if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 &&
141             fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) {
142 
143             int vsize = VertexSize(layout);
144 
145             Draw& lastDraw = fDraws.back();
146 
147             GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer);
148             GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType);
149             GrAssert(0 == lastDraw.fVertexCount % 4);
150             GrAssert(0 == lastDraw.fIndexCount % 6);
151             GrAssert(0 == lastDraw.fStartIndex);
152 
153             bool clearSinceLastDraw =
154                             fClears.count() &&
155                             fClears.back().fBeforeDrawIdx == fDraws.count();
156 
157             appendToPreviousDraw =  !clearSinceLastDraw &&
158                                     lastDraw.fVertexBuffer == fCurrPoolVertexBuffer &&
159                                    (fCurrQuad * 4 + lastDraw.fStartVertex) == fCurrPoolStartVertex;
160             if (appendToPreviousDraw) {
161                 lastDraw.fVertexCount += 4;
162                 lastDraw.fIndexCount += 6;
163                 fCurrQuad += 1;
164                 GrAssert(0 == fUsedReservedVertexBytes);
165                 fUsedReservedVertexBytes = 4 * vsize;
166             }
167         }
168         if (!appendToPreviousDraw) {
169             this->setIndexSourceToBuffer(fQuadIndexBuffer);
170             drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6);
171             fCurrQuad = 1;
172             fLastRectVertexLayout = layout;
173         }
174         if (disabledClip) {
175             this->enableState(kClip_StateBit);
176         }
177     } else {
178         INHERITED::drawRect(rect, matrix, stageEnableBitfield, srcRects, srcMatrices);
179     }
180 }
181 
drawIndexed(GrPrimitiveType primitiveType,int startVertex,int startIndex,int vertexCount,int indexCount)182 void GrInOrderDrawBuffer::drawIndexed(GrPrimitiveType primitiveType,
183                                       int startVertex,
184                                       int startIndex,
185                                       int vertexCount,
186                                       int indexCount) {
187 
188     if (!vertexCount || !indexCount) {
189         return;
190     }
191 
192     fCurrQuad = 0;
193 
194     Draw& draw = fDraws.push_back();
195     draw.fPrimitiveType = primitiveType;
196     draw.fStartVertex   = startVertex;
197     draw.fStartIndex    = startIndex;
198     draw.fVertexCount   = vertexCount;
199     draw.fIndexCount    = indexCount;
200 
201     draw.fClipChanged = this->needsNewClip();
202     if (draw.fClipChanged) {
203        this->pushClip();
204     }
205 
206     draw.fStateChanged = this->needsNewState();
207     if (draw.fStateChanged) {
208         this->pushState();
209     }
210 
211     draw.fVertexLayout = fGeometrySrc.fVertexLayout;
212     switch (fGeometrySrc.fVertexSrc) {
213     case kBuffer_GeometrySrcType:
214         draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
215         break;
216     case kReserved_GeometrySrcType: {
217         size_t vertexBytes = (vertexCount + startVertex) *
218         VertexSize(fGeometrySrc.fVertexLayout);
219         fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes, vertexBytes);
220     } // fallthrough
221     case kArray_GeometrySrcType:
222         draw.fVertexBuffer = fCurrPoolVertexBuffer;
223         draw.fStartVertex += fCurrPoolStartVertex;
224         break;
225     default:
226         GrCrash("unknown geom src type");
227     }
228     draw.fVertexBuffer->ref();
229 
230     switch (fGeometrySrc.fIndexSrc) {
231     case kBuffer_GeometrySrcType:
232         draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
233         break;
234     case kReserved_GeometrySrcType: {
235         size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
236         fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
237     } // fallthrough
238     case kArray_GeometrySrcType:
239         draw.fIndexBuffer = fCurrPoolIndexBuffer;
240         draw.fStartIndex += fCurrPoolStartVertex;
241         break;
242     default:
243         GrCrash("unknown geom src type");
244     }
245     draw.fIndexBuffer->ref();
246 }
247 
drawNonIndexed(GrPrimitiveType primitiveType,int startVertex,int vertexCount)248 void GrInOrderDrawBuffer::drawNonIndexed(GrPrimitiveType primitiveType,
249                                          int startVertex,
250                                          int vertexCount) {
251     if (!vertexCount) {
252         return;
253     }
254 
255     fCurrQuad = 0;
256 
257     Draw& draw = fDraws.push_back();
258     draw.fPrimitiveType = primitiveType;
259     draw.fStartVertex   = startVertex;
260     draw.fStartIndex    = 0;
261     draw.fVertexCount   = vertexCount;
262     draw.fIndexCount    = 0;
263 
264     draw.fClipChanged = this->needsNewClip();
265     if (draw.fClipChanged) {
266         this->pushClip();
267     }
268 
269     draw.fStateChanged = this->needsNewState();
270     if (draw.fStateChanged) {
271         this->pushState();
272     }
273 
274     draw.fVertexLayout = fGeometrySrc.fVertexLayout;
275     switch (fGeometrySrc.fVertexSrc) {
276     case kBuffer_GeometrySrcType:
277         draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
278         break;
279     case kReserved_GeometrySrcType: {
280         size_t vertexBytes = (vertexCount + startVertex) *
281         VertexSize(fGeometrySrc.fVertexLayout);
282         fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
283                                          vertexBytes);
284     } // fallthrough
285     case kArray_GeometrySrcType:
286         draw.fVertexBuffer = fCurrPoolVertexBuffer;
287         draw.fStartVertex += fCurrPoolStartVertex;
288         break;
289     default:
290         GrCrash("unknown geom src type");
291     }
292     draw.fVertexBuffer->ref();
293     draw.fIndexBuffer = NULL;
294 }
295 
clear(const GrIRect * rect,GrColor color)296 void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) {
297     GrIRect r;
298     if (NULL == rect) {
299         // We could do something smart and remove previous draws and clears to
300         // the current render target. If we get that smart we have to make sure
301         // those draws aren't read before this clear (render-to-texture).
302         r.setLTRB(0, 0,
303                   this->getRenderTarget()->width(),
304                   this->getRenderTarget()->height());
305         rect = &r;
306     }
307     Clear& clr = fClears.push_back();
308     clr.fColor = color;
309     clr.fBeforeDrawIdx = fDraws.count();
310     clr.fRect = *rect;
311 }
312 
reset()313 void GrInOrderDrawBuffer::reset() {
314     GrAssert(!fReservedGeometry.fLocked);
315     uint32_t numStates = fStates.count();
316     for (uint32_t i = 0; i < numStates; ++i) {
317         const DrState& dstate = this->accessSavedDrawState(fStates[i]);
318         for (int s = 0; s < kNumStages; ++s) {
319             GrSafeUnref(dstate.fTextures[s]);
320         }
321         GrSafeUnref(dstate.fRenderTarget);
322     }
323     int numDraws = fDraws.count();
324     for (int d = 0; d < numDraws; ++d) {
325         // we always have a VB, but not always an IB
326         GrAssert(NULL != fDraws[d].fVertexBuffer);
327         fDraws[d].fVertexBuffer->unref();
328         GrSafeUnref(fDraws[d].fIndexBuffer);
329     }
330     fDraws.reset();
331     fStates.reset();
332 
333     fClears.reset();
334 
335     fVertexPool.reset();
336     fIndexPool.reset();
337 
338     fClips.reset();
339 
340     fCurrQuad = 0;
341 }
342 
playback(GrDrawTarget * target)343 void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
344     GrAssert(!fReservedGeometry.fLocked);
345     GrAssert(NULL != target);
346     GrAssert(target != this); // not considered and why?
347 
348     int numDraws = fDraws.count();
349     if (!numDraws) {
350         return;
351     }
352 
353     fVertexPool.unlock();
354     fIndexPool.unlock();
355 
356     GrDrawTarget::AutoStateRestore asr(target);
357     GrDrawTarget::AutoClipRestore acr(target);
358     // important to not mess with reserve/lock geometry in the target with this
359     // on the stack.
360     GrDrawTarget::AutoGeometrySrcRestore agsr(target);
361 
362     int currState = ~0;
363     int currClip  = ~0;
364     int currClear = 0;
365 
366     for (int i = 0; i < numDraws; ++i) {
367         while (currClear < fClears.count() &&
368                i == fClears[currClear].fBeforeDrawIdx) {
369             target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
370             ++currClear;
371         }
372 
373         const Draw& draw = fDraws[i];
374         if (draw.fStateChanged) {
375             ++currState;
376             target->restoreDrawState(fStates[currState]);
377         }
378         if (draw.fClipChanged) {
379             ++currClip;
380             target->setClip(fClips[currClip]);
381         }
382 
383         target->setVertexSourceToBuffer(draw.fVertexLayout, draw.fVertexBuffer);
384 
385         if (draw.fIndexCount) {
386             target->setIndexSourceToBuffer(draw.fIndexBuffer);
387         }
388 
389         if (draw.fIndexCount) {
390             target->drawIndexed(draw.fPrimitiveType,
391                                 draw.fStartVertex,
392                                 draw.fStartIndex,
393                                 draw.fVertexCount,
394                                 draw.fIndexCount);
395         } else {
396             target->drawNonIndexed(draw.fPrimitiveType,
397                                    draw.fStartVertex,
398                                    draw.fVertexCount);
399         }
400     }
401     while (currClear < fClears.count()) {
402         GrAssert(fDraws.count() == fClears[currClear].fBeforeDrawIdx);
403         target->clear(&fClears[currClear].fRect, fClears[currClear].fColor);
404         ++currClear;
405     }
406 }
407 
geometryHints(GrVertexLayout vertexLayout,int * vertexCount,int * indexCount) const408 bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
409                                         int* vertexCount,
410                                         int* indexCount) const {
411     // we will recommend a flush if the data could fit in a single
412     // preallocated buffer but none are left and it can't fit
413     // in the current buffer (which may not be prealloced).
414     bool flush = false;
415     if (NULL != indexCount) {
416         int32_t currIndices = fIndexPool.currentBufferIndices();
417         if (*indexCount > currIndices &&
418             (!fIndexPool.preallocatedBuffersRemaining() &&
419              *indexCount <= fIndexPool.preallocatedBufferIndices())) {
420 
421             flush = true;
422         }
423         *indexCount = currIndices;
424     }
425     if (NULL != vertexCount) {
426         int32_t currVertices = fVertexPool.currentBufferVertices(vertexLayout);
427         if (*vertexCount > currVertices &&
428             (!fVertexPool.preallocatedBuffersRemaining() &&
429              *vertexCount <= fVertexPool.preallocatedBufferVertices(vertexLayout))) {
430 
431             flush = true;
432         }
433         *vertexCount = currVertices;
434     }
435     return flush;
436 }
437 
onAcquireGeometry(GrVertexLayout vertexLayout,void ** vertices,void ** indices)438 bool GrInOrderDrawBuffer::onAcquireGeometry(GrVertexLayout vertexLayout,
439                                             void**         vertices,
440                                             void**         indices) {
441     GrAssert(!fReservedGeometry.fLocked);
442     if (fReservedGeometry.fVertexCount) {
443         GrAssert(NULL != vertices);
444         GrAssert(0 == fReservedVertexBytes);
445         GrAssert(0 == fUsedReservedVertexBytes);
446 
447         fReservedVertexBytes = VertexSize(vertexLayout) *
448                                fReservedGeometry.fVertexCount;
449         *vertices = fVertexPool.makeSpace(vertexLayout,
450                                           fReservedGeometry.fVertexCount,
451                                           &fCurrPoolVertexBuffer,
452                                           &fCurrPoolStartVertex);
453         if (NULL == *vertices) {
454             return false;
455         }
456     }
457     if (fReservedGeometry.fIndexCount) {
458         GrAssert(NULL != indices);
459         GrAssert(0 == fReservedIndexBytes);
460         GrAssert(0 == fUsedReservedIndexBytes);
461 
462         *indices = fIndexPool.makeSpace(fReservedGeometry.fIndexCount,
463                                         &fCurrPoolIndexBuffer,
464                                         &fCurrPoolStartIndex);
465         if (NULL == *indices) {
466             fVertexPool.putBack(fReservedVertexBytes);
467             fReservedVertexBytes = 0;
468             fCurrPoolVertexBuffer = NULL;
469             return false;
470         }
471     }
472     return true;
473 }
474 
onReleaseGeometry()475 void GrInOrderDrawBuffer::onReleaseGeometry() {
476     GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
477     GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
478 
479     size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
480     fVertexPool.putBack(vertexSlack);
481 
482     size_t indexSlack = fReservedIndexBytes - fUsedReservedIndexBytes;
483     fIndexPool.putBack(indexSlack);
484 
485     fReservedVertexBytes = 0;
486     fReservedIndexBytes  = 0;
487     fUsedReservedVertexBytes = 0;
488     fUsedReservedIndexBytes  = 0;
489     fCurrPoolVertexBuffer = 0;
490     fCurrPoolStartVertex = 0;
491 
492 }
493 
onSetVertexSourceToArray(const void * vertexArray,int vertexCount)494 void GrInOrderDrawBuffer::onSetVertexSourceToArray(const void* vertexArray,
495                                                    int vertexCount) {
496     GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fVertexCount);
497 #if GR_DEBUG
498     bool success =
499 #endif
500     fVertexPool.appendVertices(fGeometrySrc.fVertexLayout,
501                                vertexCount,
502                                vertexArray,
503                                &fCurrPoolVertexBuffer,
504                                &fCurrPoolStartVertex);
505     GR_DEBUGASSERT(success);
506 }
507 
onSetIndexSourceToArray(const void * indexArray,int indexCount)508 void GrInOrderDrawBuffer::onSetIndexSourceToArray(const void* indexArray,
509                                                   int indexCount) {
510     GrAssert(!fReservedGeometry.fLocked || !fReservedGeometry.fIndexCount);
511 #if GR_DEBUG
512     bool success =
513 #endif
514     fIndexPool.appendIndices(indexCount,
515                              indexArray,
516                              &fCurrPoolIndexBuffer,
517                              &fCurrPoolStartIndex);
518     GR_DEBUGASSERT(success);
519 }
520 
needsNewState() const521 bool GrInOrderDrawBuffer::needsNewState() const {
522      if (fStates.empty()) {
523         return true;
524      } else {
525          const DrState& old = this->accessSavedDrawState(fStates.back());
526         return old != fCurrDrawState;
527      }
528 }
529 
pushState()530 void GrInOrderDrawBuffer::pushState() {
531     for (int s = 0; s < kNumStages; ++s) {
532         GrSafeRef(fCurrDrawState.fTextures[s]);
533     }
534     GrSafeRef(fCurrDrawState.fRenderTarget);
535     this->saveCurrentDrawState(&fStates.push_back());
536  }
537 
needsNewClip() const538 bool GrInOrderDrawBuffer::needsNewClip() const {
539    if (fCurrDrawState.fFlagBits & kClip_StateBit) {
540        if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
541            return true;
542        }
543     }
544     return false;
545 }
546 
pushClip()547 void GrInOrderDrawBuffer::pushClip() {
548     fClips.push_back() = fClip;
549     fClipSet = false;
550 }
551 
clipWillBeSet(const GrClip & newClip)552 void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip)  {
553     fClipSet = true;
554 }
555