add gpu backend (not hooked up yet)



git-svn-id: http://skia.googlecode.com/svn/trunk@649 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
new file mode 100644
index 0000000..3f25f2f
--- /dev/null
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -0,0 +1,345 @@
+/*
+    Copyright 2010 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+
+#include "GrInOrderDrawBuffer.h"
+#include "GrTexture.h"
+#include "GrVertexBufferAllocPool.h"
+#include "GrGpu.h"
+
+GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* pool) :
+        fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage),
+        fStates(STATES_BLOCK_SIZE, fStatesStorage),
+        fClips(CLIPS_BLOCK_SIZE, fClipsStorage),
+        fClipChanged(true),
+        fCPUVertices((NULL == pool) ? 0 : VERTEX_BLOCK_SIZE),
+        fBufferVertices(pool),
+        fIndices(INDEX_BLOCK_SIZE),
+        fCurrReservedVertices(NULL),
+        fCurrReservedIndices(NULL),
+        fCurrVertexBuffer(NULL),
+        fReservedVertexBytes(0),
+        fReservedIndexBytes(0),
+        fUsedReservedVertexBytes(0),
+        fUsedReservedIndexBytes(0) {
+    GrAssert(NULL == pool || pool->getGpu()->supportsBufferLocking());
+}
+
+GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
+    reset();
+}
+
+void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
+    this->copyDrawState(target);
+    this->setClip(target.getClip());
+}
+
+void GrInOrderDrawBuffer::drawIndexed(PrimitiveType type,
+                                      uint32_t startVertex,
+                                      uint32_t startIndex,
+                                      uint32_t vertexCount,
+                                      uint32_t indexCount) {
+
+    if (!vertexCount || !indexCount) {
+        return;
+    }
+
+    Draw& draw = fDraws.push_back();
+    draw.fType          = type;
+    draw.fStartVertex   = startVertex;
+    draw.fStartIndex    = startIndex;
+    draw.fVertexCount   = vertexCount;
+    draw.fIndexCount    = indexCount;
+    draw.fClipChanged   = grabClip();
+    draw.fStateChange   = grabState();
+
+    draw.fVertexLayout = fGeometrySrc.fVertexLayout;
+    switch (fGeometrySrc.fVertexSrc) {
+    case kArray_GeometrySrcType:
+        draw.fUseVertexBuffer = false;
+        draw.fVertexArray = fGeometrySrc.fVertexArray;
+        break;
+    case kReserved_GeometrySrcType: {
+        draw.fUseVertexBuffer = NULL != fBufferVertices;
+        if (draw.fUseVertexBuffer) {
+            draw.fVertexBuffer = fCurrVertexBuffer;
+            draw.fStartVertex += fCurrStartVertex;
+        } else {
+            draw.fVertexArray = fCurrReservedVertices;
+        }
+        size_t vertexBytes = (vertexCount + startVertex) *
+                             VertexSize(fGeometrySrc.fVertexLayout);
+        fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
+                                         vertexBytes);
+        } break;
+    case kBuffer_GeometrySrcType:
+        draw.fUseVertexBuffer = true;
+        draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
+        break;
+    }
+
+    switch (fGeometrySrc.fIndexSrc) {
+    case kArray_GeometrySrcType:
+        draw.fUseIndexBuffer = false;
+        draw.fIndexArray = fGeometrySrc.fIndexArray;
+        break;
+    case kReserved_GeometrySrcType: {
+        draw.fUseIndexBuffer = false;
+        draw.fIndexArray = fCurrReservedIndices;
+        size_t indexBytes = (indexCount + startIndex) * sizeof(uint16_t);
+        fUsedReservedIndexBytes = GrMax(fUsedReservedIndexBytes, indexBytes);
+        } break;
+    case kBuffer_GeometrySrcType:
+        draw.fUseIndexBuffer = true;
+        draw.fIndexBuffer = fGeometrySrc.fIndexBuffer;
+        break;
+    }
+}
+
+void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType type,
+                                         uint32_t startVertex,
+                                         uint32_t vertexCount) {
+    if (!vertexCount) {
+        return;
+    }
+
+    Draw& draw = fDraws.push_back();
+    draw.fType          = type;
+    draw.fStartVertex   = startVertex;
+    draw.fStartIndex    = 0;
+    draw.fVertexCount   = vertexCount;
+    draw.fIndexCount    = 0;
+
+    draw.fClipChanged   = grabClip();
+    draw.fStateChange   = grabState();
+
+    draw.fVertexLayout = fGeometrySrc.fVertexLayout;
+    switch (fGeometrySrc.fVertexSrc) {
+    case kArray_GeometrySrcType:
+        draw.fUseVertexBuffer = false;
+        draw.fVertexArray = fGeometrySrc.fVertexArray;
+        break;
+    case kReserved_GeometrySrcType: {
+        draw.fUseVertexBuffer = NULL != fBufferVertices;
+        if (draw.fUseVertexBuffer) {
+            draw.fVertexBuffer = fCurrVertexBuffer;
+            draw.fStartVertex += fCurrStartVertex;
+        } else {
+            draw.fVertexArray = fCurrReservedVertices;
+        }
+        size_t vertexBytes = (vertexCount + startVertex) *
+                             VertexSize(fGeometrySrc.fVertexLayout);
+        fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes,
+                                         vertexBytes);
+        } break;
+    case kBuffer_GeometrySrcType:
+        draw.fUseVertexBuffer = true;
+        draw.fVertexBuffer = fGeometrySrc.fVertexBuffer;
+        break;
+    }
+}
+
+void GrInOrderDrawBuffer::reset() {
+    GrAssert(!fReservedGeometry.fLocked);
+    uint32_t numStates = fStates.count();
+    for (uint32_t i = 0; i < numStates; ++i) {
+        GrTexture* tex = accessSavedDrawState(fStates[i]).fTexture;
+        if (NULL != tex) {
+            tex->unref();
+        }
+    }
+    fDraws.reset();
+    fStates.reset();
+    if (NULL == fBufferVertices) {
+        fCPUVertices.reset();
+    } else {
+        fBufferVertices->reset();
+    }
+    fIndices.reset();
+    fClips.reset();
+}
+
+void GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
+    GrAssert(NULL != target);
+    GrAssert(target != this); // not considered and why?
+
+    uint32_t numDraws = fDraws.count();
+    if (!numDraws) {
+        return;
+    }
+
+    if (NULL != fBufferVertices) {
+        fBufferVertices->unlock();
+    }
+
+    GrDrawTarget::AutoStateRestore asr(target);
+    GrDrawTarget::AutoClipRestore acr(target);
+    // important to not mess with reserve/lock geometry in the target with this
+    // on the stack.
+    GrDrawTarget::AutoGeometrySrcRestore agsr(target);
+
+    uint32_t currState = ~0;
+    uint32_t currClip  = ~0;
+
+    for (uint32_t i = 0; i < numDraws; ++i) {
+        const Draw& draw = fDraws[i];
+        if (draw.fStateChange) {
+            ++currState;
+            target->restoreDrawState(fStates[currState]);
+        }
+        if (draw.fClipChanged) {
+            ++currClip;
+            target->setClip(fClips[currClip]);
+        }
+        if (draw.fUseVertexBuffer) {
+            target->setVertexSourceToBuffer(draw.fVertexBuffer, draw.fVertexLayout);
+        } else {
+            target->setVertexSourceToArray(draw.fVertexArray, draw.fVertexLayout);
+        }
+        if (draw.fIndexCount) {
+            if (draw.fUseIndexBuffer) {
+                target->setIndexSourceToBuffer(draw.fIndexBuffer);
+            } else {
+                target->setIndexSourceToArray(draw.fIndexArray);
+            }
+            target->drawIndexed(draw.fType,
+                                draw.fStartVertex,
+                                draw.fStartIndex,
+                                draw.fVertexCount,
+                                draw.fIndexCount);
+        } else {
+            target->drawNonIndexed(draw.fType,
+                                   draw.fStartVertex,
+                                   draw.fVertexCount);
+        }
+    }
+}
+
+bool GrInOrderDrawBuffer::geometryHints(GrVertexLayout vertexLayout,
+                                        int32_t* vertexCount,
+                                        int32_t* indexCount) const {
+    bool flush = false;
+    if (NULL != indexCount) {
+        *indexCount  = -1;
+    }
+    if (NULL != vertexCount) {
+        if (NULL != fBufferVertices) {
+            // we will recommend a flush if the verts could fit in a single
+            // preallocated vertex buffer but none are left and it can't fit
+            // in the current VB (which may not be prealloced).
+            if (*vertexCount > fBufferVertices->currentBufferVertices(vertexLayout) &&
+                (!fBufferVertices->preallocatedBuffersRemaining() &&
+                 *vertexCount <= fBufferVertices->preallocatedBufferVertices(vertexLayout))) {
+
+                flush = true;
+            }
+            *vertexCount = fBufferVertices->currentBufferVertices(vertexLayout);
+        } else {
+            *vertexCount = -1;
+        }
+    }
+    return flush;
+}
+
+bool GrInOrderDrawBuffer::acquireGeometryHelper(GrVertexLayout vertexLayout,
+                                                void**         vertices,
+                                                void**         indices) {
+    if (fReservedGeometry.fVertexCount) {
+        fReservedVertexBytes = VertexSize(vertexLayout) *
+                               fReservedGeometry.fVertexCount;
+        if (NULL == fBufferVertices) {
+            fCurrReservedVertices = fCPUVertices.alloc(fReservedVertexBytes);
+        } else {
+            fCurrReservedVertices = fBufferVertices->alloc(vertexLayout,
+                                                           fReservedGeometry.fVertexCount,
+                                                           &fCurrVertexBuffer,
+                                                           &fCurrStartVertex);
+        }
+        if (NULL != vertices) {
+            *vertices = fCurrReservedVertices;
+        }
+        if (NULL == fCurrReservedVertices) {
+            return false;
+        }
+    }
+    if (fReservedGeometry.fIndexCount) {
+        fReservedIndexBytes = sizeof(uint16_t) * fReservedGeometry.fIndexCount;
+        fCurrReservedIndices = fIndices.alloc(fReservedIndexBytes);
+        if (NULL != indices) {
+            *indices = fCurrReservedIndices;
+        }
+        if (NULL == fCurrReservedIndices) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void GrInOrderDrawBuffer::releaseGeometryHelper() {
+    GrAssert(fUsedReservedVertexBytes <= fReservedVertexBytes);
+    GrAssert(fUsedReservedIndexBytes <= fReservedIndexBytes);
+
+    size_t vertexSlack = fReservedVertexBytes - fUsedReservedVertexBytes;
+    if (NULL == fBufferVertices) {
+        fCPUVertices.release(vertexSlack);
+    } else {
+        fBufferVertices->release(vertexSlack);
+        GR_DEBUGCODE(fCurrVertexBuffer = NULL);
+        GR_DEBUGCODE(fCurrStartVertex  = 0);
+    }
+
+    fIndices.release(fReservedIndexBytes - fUsedReservedIndexBytes);
+
+    fCurrReservedVertices = NULL;
+    fCurrReservedIndices  = NULL;
+    fReservedVertexBytes = 0;
+    fReservedIndexBytes  = 0;
+    fUsedReservedVertexBytes = 0;
+    fUsedReservedIndexBytes  = 0;
+}
+
+bool GrInOrderDrawBuffer::grabState() {
+    bool newState;
+    if (fStates.empty()) {
+        newState = true;
+    } else {
+        const DrawState& old = accessSavedDrawState(fStates.back());
+        newState = old != fCurrDrawState;
+    }
+    if (newState) {
+        if (NULL != fCurrDrawState.fTexture) {
+            fCurrDrawState.fTexture->ref();
+        }
+        saveCurrentDrawState(&fStates.push_back());
+    }
+    return newState;
+}
+
+bool GrInOrderDrawBuffer::grabClip() {
+    if ((fCurrDrawState.fFlagBits & kClip_StateBit) &&
+        (fClipChanged || fClips.empty())) {
+
+        fClips.push_back() = fClip;
+        fClipChanged = false;
+        return true;
+    }
+    return false;
+}
+
+void GrInOrderDrawBuffer::clipWillChange(const GrClip& clip)  {
+    fClipChanged = true;
+}
+