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);
+
+
+
+