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/GrGpu.cpp b/gpu/src/GrGpu.cpp
new file mode 100644
index 0000000..c6340bd
--- /dev/null
+++ b/gpu/src/GrGpu.cpp
@@ -0,0 +1,343 @@
+/*
+    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 "GrGpu.h"
+#include "GrMemory.h"
+#include "GrTextStrike.h"
+#include "GrTextureCache.h"
+#include "GrClipIterator.h"
+#include "GrIndexBuffer.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+size_t GrTexture::BytesPerPixel(PixelConfig config) {
+    switch (config) {
+        case kAlpha_8_PixelConfig:
+        case kIndex_8_PixelConfig:
+            return 1;
+        case kRGB_565_PixelConfig:
+        case kRGBA_4444_PixelConfig:
+            return 2;
+        case kRGBA_8888_PixelConfig:
+        case kRGBX_8888_PixelConfig:
+            return 4;
+        default:
+            return 0;
+    }
+}
+
+bool GrTexture::PixelConfigIsOpaque(PixelConfig config) {
+    switch (config) {
+        case GrTexture::kRGB_565_PixelConfig:
+        case GrTexture::kRGBX_8888_PixelConfig:
+            return true;
+        default:
+            return false;
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern void gr_run_unittests();
+
+GrGpu::GrGpu() : f8bitPaletteSupport(false),
+                 fNPOTTextureSupport(kNone_NPOTTextureType),
+                 fQuadIndexBuffer(NULL) {
+#if GR_DEBUG
+//    gr_run_unittests();
+#endif
+    resetStats();
+}
+
+GrGpu::~GrGpu() {
+    if (NULL != fQuadIndexBuffer) {
+        fQuadIndexBuffer->unref();
+    }
+}
+
+void GrGpu::resetContext() {
+}
+
+void GrGpu::unimpl(const char msg[]) {
+//    GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool GrGpu::canDisableBlend() const {
+    if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
+        (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
+            return true;
+    }
+
+    // If we have vertex color without alpha then we can't force blend off
+    if ((fGeometrySrc.fVertexLayout & kColor_VertexLayoutBit) ||
+         0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
+        return false;
+    }
+
+    // If the src coef will always be 1...
+    bool fullSrc = kSA_BlendCoeff == fCurrDrawState.fSrcBlend ||
+                   kOne_BlendCoeff == fCurrDrawState.fSrcBlend;
+
+    // ...and the dst coef is always 0...
+    bool noDst = kISA_BlendCoeff == fCurrDrawState.fDstBlend ||
+                 kZero_BlendCoeff == fCurrDrawState.fDstBlend;
+
+    // ...and there isn't a texture with an alpha channel...
+    bool noTexAlpha = !VertexHasTexCoords(fGeometrySrc.fVertexLayout)  ||
+        fCurrDrawState.fTexture->config() == GrTexture::kRGB_565_PixelConfig ||
+        fCurrDrawState.fTexture->config() == GrTexture::kRGBX_8888_PixelConfig;
+
+    // ...then we disable blend.
+    return fullSrc && noDst && noTexAlpha;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static const int MAX_QUADS = 512; // max possible: (1 << 14) - 1;
+
+GR_STATIC_ASSERT(4 * MAX_QUADS <= UINT16_MAX);
+
+static inline void fillIndices(uint16_t* indices, int quadCount) {
+    for (int i = 0; i < quadCount; ++i) {
+        indices[6 * i + 0] = 4 * i + 0;
+        indices[6 * i + 1] = 4 * i + 1;
+        indices[6 * i + 2] = 4 * i + 2;
+        indices[6 * i + 3] = 4 * i + 0;
+        indices[6 * i + 4] = 4 * i + 2;
+        indices[6 * i + 5] = 4 * i + 3;
+    }
+}
+
+const GrIndexBuffer* GrGpu::quadIndexBuffer() const {
+    if (NULL == fQuadIndexBuffer) {
+        static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
+        GrGpu* me = const_cast<GrGpu*>(this);
+        fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
+        if (NULL != fQuadIndexBuffer) {
+            uint16_t* indices = (uint16_t*)fQuadIndexBuffer->lock();
+            if (NULL != indices) {
+                fillIndices(indices, MAX_QUADS);
+                fQuadIndexBuffer->unlock();
+            } else {
+                indices = (uint16_t*)GrMalloc(SIZE);
+                fillIndices(indices, MAX_QUADS);
+                if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
+                    fQuadIndexBuffer->unref();
+                    fQuadIndexBuffer = NULL;
+                    GrAssert(!"Can't get indices into buffer!");
+                }
+                GrFree(indices);
+            }
+        }
+    }
+
+    return fQuadIndexBuffer;
+}
+
+int GrGpu::maxQuadsInIndexBuffer() const {
+    return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrGpu::clipWillChange(const GrClip& clip) {
+    if (clip != fClip) {
+        fClipState.fClipIsDirty = true;
+    }
+}
+
+bool GrGpu::setupClipAndFlushState(PrimitiveType type) {
+    const GrIRect* r = NULL;
+
+    if (fCurrDrawState.fFlagBits & kClip_StateBit) {
+        fClipState.fClipInStencil = fClip.countRects() > 1;
+
+        if (fClipState.fClipInStencil &&
+            (fClipState.fClipIsDirty ||
+             fClipState.fStencilClipTarget != fCurrDrawState.fRenderTarget)) {
+
+            AutoStateRestore asr(this);
+            AutoGeometrySrcRestore agsr(this);
+            this->disableState(kClip_StateBit);
+            eraseStencilClip();
+
+            int rectTotal = fClip.countRects();
+            static const int PtsPerRect = 4;
+            // this may be called while geometry is already reserved by the
+            // client. So we use our own vertex array where we avoid malloc
+            // if we have 4 or fewer rects.
+            GrAutoSTMalloc<PtsPerRect * 4, GrPoint> vertices(PtsPerRect *
+                                                             rectTotal);
+            this->setVertexSourceToArray(vertices.get(), 0);
+            int currRect = 0;
+            while (currRect < rectTotal) {
+                int rectCount = GrMin(this->maxQuadsInIndexBuffer(),
+                                      rectTotal - currRect);
+
+                GrPoint* verts = (GrPoint*)vertices +
+                                 (currRect * PtsPerRect);
+
+                for (int i = 0; i < rectCount; i++) {
+                    GrRect r(fClip.getRects()[i + currRect]);
+                    verts = r.setRectFan(verts);
+                }
+                this->setIndexSourceToBuffer(quadIndexBuffer());
+
+                this->setViewMatrix(GrMatrix::I());
+                this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass);
+                this->drawIndexed(GrGpu::kTriangles_PrimitiveType,
+                                  currRect * PtsPerRect, 0,
+                                  rectCount * PtsPerRect, rectCount * 6);
+
+                currRect += rectCount;
+            }
+            fClipState.fStencilClipTarget = fCurrDrawState.fRenderTarget;
+        }
+        fClipState.fClipIsDirty = false;
+        if (!fClipState.fClipInStencil) {
+            r = &fClip.getBounds();
+        }
+    }
+    // Must flush the scissor after graphics state
+    if (!flushGraphicsState(type)) {
+        return false;
+    }
+    flushScissor(r);
+    return true;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrGpu::drawIndexed(PrimitiveType type,
+                        uint32_t startVertex,
+                        uint32_t startIndex,
+                        uint32_t vertexCount,
+                        uint32_t indexCount) {
+    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
+             fReservedGeometry.fLocked);
+    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fIndexSrc ||
+             fReservedGeometry.fLocked);
+
+    if (!setupClipAndFlushState(type)) {
+        return;
+    }
+
+#if GR_COLLECT_STATS
+    fStats.fVertexCnt += vertexCount;
+    fStats.fIndexCnt  += indexCount;
+    fStats.fDrawCnt   += 1;
+#endif
+
+    setupGeometry(startVertex, startIndex, vertexCount, indexCount);
+
+    drawIndexedHelper(type, startVertex, startIndex,
+                      vertexCount, indexCount);
+}
+
+void GrGpu::drawNonIndexed(PrimitiveType type,
+                           uint32_t startVertex,
+                           uint32_t vertexCount) {
+    GrAssert(kReserved_GeometrySrcType != fGeometrySrc.fVertexSrc ||
+             fReservedGeometry.fLocked);
+
+    if (!setupClipAndFlushState(type)) {
+        return;
+    }
+#if GR_COLLECT_STATS
+    fStats.fVertexCnt += vertexCount;
+    fStats.fDrawCnt   += 1;
+#endif
+
+    setupGeometry(startVertex, 0, vertexCount, 0);
+
+    drawNonIndexedHelper(type, startVertex, vertexCount);
+}
+
+bool GrGpu::acquireGeometryHelper(GrVertexLayout vertexLayout,
+                                  void**         vertices,
+                                  void**         indices) {
+    GrAssert((fReservedGeometry.fVertexCount == 0) ||
+             (NULL != vertices));
+    if (NULL != vertices) {
+        *vertices = fVertices.realloc(VertexSize(vertexLayout) *
+                                      fReservedGeometry.fVertexCount);
+        if (!*vertices && fReservedGeometry.fVertexCount) {
+            return false;
+        }
+    }
+    GrAssert((fReservedGeometry.fIndexCount == 0) ||
+             (NULL != indices));
+    if (NULL != indices) {
+        *indices =  fIndices.realloc(sizeof(uint16_t) *
+                                     fReservedGeometry.fIndexCount);
+        if (!*indices && fReservedGeometry.fIndexCount) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void GrGpu::releaseGeometryHelper() {
+    return;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+const GrGpu::Stats& GrGpu::getStats() const {
+    return fStats;
+}
+
+void GrGpu::resetStats() {
+    memset(&fStats, 0, sizeof(fStats));
+}
+
+void GrGpu::printStats() const {
+    if (GR_COLLECT_STATS) {
+     GrPrintf(
+     "-v-------------------------GPU STATS----------------------------v-\n"
+     "Stats collection is: %s\n"
+     "Draws: %04d, Verts: %04d, Indices: %04d\n"
+     "ProgChanges: %04d, TexChanges: %04d, RTChanges: %04d\n"
+     "TexCreates: %04d, RTCreates:%04d\n"
+     "-^--------------------------------------------------------------^-\n",
+     (GR_COLLECT_STATS ? "ON" : "OFF"),
+    fStats.fDrawCnt, fStats.fVertexCnt, fStats.fIndexCnt,
+    fStats.fProgChngCnt, fStats.fTextureChngCnt, fStats.fRenderTargetChngCnt,
+    fStats.fTextureCreateCnt, fStats.fRenderTargetCreateCnt);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrTexture::~GrTexture() {
+    // use this to set a break-point if needed
+//    Gr_clz(3);
+}
+
+const GrSamplerState GrSamplerState::gClampNoFilter(
+    GrSamplerState::kClamp_WrapMode,
+    GrSamplerState::kClamp_WrapMode,
+    GrSamplerState::kNormal_SampleMode,
+    false);
+
+
+
+