Batch consecutive draw rects.
Review URL: http://codereview.appspot.com/4178057/
git-svn-id: http://skia.googlecode.com/svn/trunk@800 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index c11d02f..ad7f776 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -27,11 +27,18 @@
#define DEFER_TEXT_RENDERING 1
+#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
+
static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
-static const uint32_t TEXT_POOL_VB_SIZE = 1 << 18; // enough to draw 4K untextured glyphs
-static const uint32_t NUM_TEXT_POOL_VBS = 4;
+static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
+static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
+
+// We are currently only batching Text and drawRectToRect, both
+// of which use the quad index buffer.
+static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
+static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
GrContext* GrContext::Create(GrGpu::Engine engine,
GrGpu::Platform3DContext context3D) {
@@ -52,9 +59,9 @@
fGpu->unref();
delete fTextureCache;
delete fFontCache;
- delete fTextDrawBuffer;
- delete fTextVBAllocPool;
- delete fTextIBAllocPool;
+ delete fDrawBuffer;
+ delete fDrawBufferVBAllocPool;
+ delete fDrawBufferVBAllocPool;
}
void GrContext::abandonAllTextures() {
@@ -331,18 +338,18 @@
const GrMatrix* matrix) {
bool textured = NULL != paint.getTexture();
- GrVertexLayout layout = (textured) ?
- GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
- 0;
- this->prepareToDraw(paint);
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
if (width >= 0) {
// TODO: consider making static vertex buffers for these cases.
// Hairline could be done by just adding closing vertex to
// unitSquareVertexBuffer()
+ GrVertexLayout layout = (textured) ?
+ GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
+ 0;
static const int worstCaseVertCount = 10;
- GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, worstCaseVertCount, 0);
+ GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
if (!geo.succeeded()) {
return;
@@ -369,16 +376,20 @@
GrDrawTarget::AutoViewMatrixRestore avmr;
if (NULL != matrix) {
- avmr.set(fGpu);
- fGpu->concatViewMatrix(*matrix);
- fGpu->concatTextureMatrix(0, *matrix);
+ avmr.set(target);
+ target->concatViewMatrix(*matrix);
+ target->concatTextureMatrix(0, *matrix);
}
- fGpu->drawNonIndexed(primType, 0, vertCount);
+ target->drawNonIndexed(primType, 0, vertCount);
} else {
#if GR_STATIC_RECT_VB
- fGpu->setVertexSourceToBuffer(layout, fGpu->unitSquareVertexBuffer());
- GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);
+ GrVertexLayout layout = (textured) ?
+ GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
+ 0;
+ target->setVertexSourceToBuffer(layout,
+ fGpu->getUnitSquareVertexBuffer());
+ GrDrawTarget::AutoViewMatrixRestore avmr(target);
GrMatrix m;
m.setAll(rect.width(), 0, rect.fLeft,
0, rect.height(), rect.fTop,
@@ -388,25 +399,15 @@
m.postConcat(*matrix);
}
- fGpu->concatViewMatrix(m);
+ target->concatViewMatrix(m);
if (textured) {
- fGpu->concatTextureMatrix(0, m);
+ target->concatTextureMatrix(0, m);
}
+ target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
#else
- GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);
- GrPoint* vertex = geo.positions();
- vertex->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
-
- GrDrawTarget::AutoViewMatrixRestore avmr;
- if (NULL != matrix) {
- avmr.set(fGpu);
- fGpu->concatViewMatrix(*matrix);
- fGpu->concatTextureMatrix(0, *matrix);
- }
+ target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
#endif
-
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
}
}
@@ -420,12 +421,14 @@
drawRect(paint, dstRect, -1, dstMatrix);
return;
}
-
- this->prepareToDraw(paint);
+
+ GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
#if GR_STATIC_RECT_VB
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
- GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);
+ GrDrawTarget::AutoViewMatrixRestore avmr(target);
GrMatrix m;
@@ -435,7 +438,7 @@
if (NULL != dstMatrix) {
m.postConcat(*dstMatrix);
}
- fGpu->concatViewMatrix(m);
+ target->concatViewMatrix(m);
m.setAll(srcRect.width(), 0, srcRect.fLeft,
0, srcRect.height(), srcRect.fTop,
@@ -443,34 +446,26 @@
if (NULL != srcMatrix) {
m.postConcat(*srcMatrix);
}
- fGpu->concatTextureMatrix(0, m);
+ target->concatTextureMatrix(0, m);
- fGpu->setVertexSourceToBuffer(layout, fGpu->unitSquareVertexBuffer());
+ target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
+ target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
#else
- GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
- GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);
- GrPoint* pos = geo.positions();
- GrPoint* tex = pos + 1;
- static const size_t stride = 2 * sizeof(GrPoint);
- pos[0].setRectFan(dstRect.fLeft, dstRect.fTop,
- dstRect.fRight, dstRect.fBottom,
- stride);
- tex[0].setRectFan(srcRect.fLeft, srcRect.fTop,
- srcRect.fRight, srcRect.fBottom,
- stride);
-
- GrDrawTarget::AutoViewMatrixRestore avmr;
- if (NULL != dstMatrix) {
- avmr.set(fGpu);
- fGpu->concatViewMatrix(*dstMatrix);
- }
- if (NULL != srcMatrix) {
- fGpu->concatTextureMatrix(0, *srcMatrix);
- }
-
+ GrDrawTarget* target;
+#if BATCH_RECT_TO_RECT
+ target = this->prepareToDraw(paint, kBuffered_DrawCategory);
+#else
+ target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
#endif
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
+
+ const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
+ const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
+ srcRects[0] = &srcRect;
+ srcMatrices[0] = srcMatrix;
+
+ target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
+#endif
}
void GrContext::drawVertices(const GrPaint& paint,
@@ -486,7 +481,7 @@
GrDrawTarget::AutoReleaseGeometry geo;
- this->prepareToDraw(paint);
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
if (NULL != paint.getTexture()) {
if (NULL == texCoords) {
@@ -503,7 +498,7 @@
}
if (sizeof(GrPoint) != vertexSize) {
- if (!geo.set(fGpu, layout, vertexCount, 0)) {
+ if (!geo.set(target, layout, vertexCount, 0)) {
GrPrintf("Failed to get space for vertices!");
return;
}
@@ -526,14 +521,14 @@
curVertex = (void*)((intptr_t)curVertex + vsize);
}
} else {
- fGpu->setVertexSourceToArray(layout, positions, vertexCount);
+ target->setVertexSourceToArray(layout, positions, vertexCount);
}
if (NULL != indices) {
- fGpu->setIndexSourceToArray(indices, indexCount);
- fGpu->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ target->setIndexSourceToArray(indices, indexCount);
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
} else {
- fGpu->drawNonIndexed(primitiveType, 0, vertexCount);
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
}
}
@@ -666,7 +661,7 @@
static inline bool single_pass_path(const GrPathIter& path,
GrContext::PathFills fill,
- const GrGpu& gpu) {
+ const GrDrawTarget& target) {
#if STENCIL_OFF
return true;
#else
@@ -679,7 +674,7 @@
return hint == GrPathIter::kConvex_ConvexHint ||
hint == GrPathIter::kNonOverlappingConvexPieces_ConvexHint ||
(hint == GrPathIter::kSameWindingConvexPieces_ConvexHint &&
- gpu.canDisableBlend() && !gpu.isDitherState());
+ target.canDisableBlend() && !target.isDitherState());
}
return false;
@@ -692,11 +687,11 @@
const GrPoint* translate) {
- this->prepareToDraw(paint);
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
- GrDrawTarget::AutoStateRestore asr(fGpu);
+ GrDrawTarget::AutoStateRestore asr(target);
- GrMatrix viewM = fGpu->getViewMatrix();
+ GrMatrix viewM = target->getViewMatrix();
// In order to tesselate the path we get a bound on how much the matrix can
// stretch when mapping to screen coordinates.
GrScalar stretch = viewM.getMaxStretch();
@@ -722,7 +717,7 @@
layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
}
// add 4 to hold the bounding rect
- GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, maxPts + 4, 0);
+ GrDrawTarget::AutoReleaseGeometry arg(target, layout, maxPts + 4, 0);
GrPoint* base = (GrPoint*) arg.vertices();
GrPoint* vert = base;
@@ -744,7 +739,7 @@
passes[0] = GrDrawTarget::kNone_StencilPass;
} else {
type = GrDrawTarget::kTriangleFan_PrimitiveType;
- if (single_pass_path(*path, fill, *fGpu)) {
+ if (single_pass_path(*path, fill, *target)) {
passCount = 1;
passes[0] = GrDrawTarget::kNone_StencilPass;
} else {
@@ -778,7 +773,7 @@
}
}
}
- fGpu->setReverseFill(reverse);
+ target->setReverseFill(reverse);
GrPoint pts[4];
@@ -840,13 +835,13 @@
if (useBounds) {
GrRect bounds;
if (reverse) {
- GrAssert(NULL != fGpu->getRenderTarget());
+ GrAssert(NULL != target->getRenderTarget());
// draw over the whole world.
bounds.setLTRB(0, 0,
- GrIntToScalar(fGpu->getRenderTarget()->width()),
- GrIntToScalar(fGpu->getRenderTarget()->height()));
+ GrIntToScalar(target->getRenderTarget()->width()),
+ GrIntToScalar(target->getRenderTarget()->height()));
GrMatrix vmi;
- if (fGpu->getViewInverse(&vmi)) {
+ if (target->getViewInverse(&vmi)) {
vmi.mapRect(&bounds);
}
} else {
@@ -857,16 +852,16 @@
}
for (int p = 0; p < passCount; ++p) {
- fGpu->setStencilPass(passes[p]);
+ target->setStencilPass(passes[p]);
if (useBounds && (GrDrawTarget::kEvenOddColor_StencilPass == passes[p] ||
GrDrawTarget::kWindingColor_StencilPass == passes[p])) {
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
+ target->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType,
maxPts, 4);
} else {
int baseVertex = 0;
for (int sp = 0; sp < subpathCnt; ++sp) {
- fGpu->drawNonIndexed(type,
+ target->drawNonIndexed(type,
baseVertex,
subpathVertCount[sp]);
baseVertex += subpathVertCount[sp];
@@ -878,19 +873,25 @@
////////////////////////////////////////////////////////////////////////////////
void GrContext::flush(bool flushRenderTarget) {
- flushText();
+ flushDrawBuffer();
if (flushRenderTarget) {
fGpu->forceRenderTargetFlush();
}
}
void GrContext::flushText() {
- if (NULL != fTextDrawBuffer) {
- fTextDrawBuffer->playback(fGpu);
- fTextDrawBuffer->reset();
+ if (kText_DrawCategory == fLastDrawCategory) {
+ flushDrawBuffer();
}
}
+void GrContext::flushDrawBuffer() {
+#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
+ fDrawBuffer->playback(fGpu);
+ fDrawBuffer->reset();
+#endif
+}
+
bool GrContext::readPixels(int left, int top, int width, int height,
GrTexture::PixelConfig config, void* buffer) {
this->flush(true);
@@ -962,10 +963,32 @@
target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
}
-void GrContext::prepareToDraw(const GrPaint& paint) {
-
- flushText();
+GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
+ DrawCategory category) {
+ if (category != fLastDrawCategory) {
+ flushDrawBuffer();
+ fLastDrawCategory = category;
+ }
SetPaint(paint, fGpu);
+ GrDrawTarget* target = fGpu;
+ switch (category) {
+ case kText_DrawCategory:
+#if DEFER_TEXT_RENDERING
+ target = fDrawBuffer;
+ fDrawBuffer->initializeDrawStateAndClip(*fGpu);
+#else
+ target = fGpu;
+#endif
+ break;
+ case kUnbuffered_DrawCategory:
+ target = fGpu;
+ break;
+ case kBuffered_DrawCategory:
+ target = fDrawBuffer;
+ fDrawBuffer->initializeDrawStateAndClip(*fGpu);
+ break;
+ }
+ return target;
}
////////////////////////////////////////////////////////////////////////////////
@@ -975,7 +998,7 @@
}
void GrContext::setRenderTarget(GrRenderTarget* target) {
- flushText();
+ flush(false);
fGpu->setRenderTarget(target);
}
@@ -1028,19 +1051,28 @@
MAX_TEXTURE_CACHE_BYTES);
fFontCache = new GrFontCache(fGpu);
-#if DEFER_TEXT_RENDERING
- fTextVBAllocPool = new GrVertexBufferAllocPool(gpu,
- false,
- TEXT_POOL_VB_SIZE,
- NUM_TEXT_POOL_VBS);
- fTextIBAllocPool = new GrIndexBufferAllocPool(gpu, false, 0, 0);
+ fLastDrawCategory = kUnbuffered_DrawCategory;
- fTextDrawBuffer = new GrInOrderDrawBuffer(fTextVBAllocPool,
- fTextIBAllocPool);
+#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
+ fDrawBufferVBAllocPool =
+ new GrVertexBufferAllocPool(gpu, false,
+ DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
+ DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
+ fDrawBufferIBAllocPool =
+ new GrIndexBufferAllocPool(gpu, false,
+ DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
+ DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
+
+ fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
+ fDrawBufferIBAllocPool);
#else
- fTextDrawBuffer = NULL;
- fTextVBAllocPool = NULL;
- fTextIBAllocPool = NULL;
+ fDrawBuffer = NULL;
+ fDrawBufferVBAllocPool = NULL;
+ fDrawBufferIBAllocPool = NULL;
+#endif
+
+#if BATCH_RECT_TO_RECT
+ fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
#endif
}
@@ -1070,22 +1102,14 @@
GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
GrDrawTarget* target;
#if DEFER_TEXT_RENDERING
- fTextDrawBuffer->initializeDrawStateAndClip(*fGpu);
- target = fTextDrawBuffer;
+ target = prepareToDraw(paint, kText_DrawCategory);
#else
- target = fGpu;
+ target = prepareToDraw(paint, kUnbuffered_DrawCategory);
#endif
SetPaint(paint, target);
return target;
}
-const GrIndexBuffer* GrContext::quadIndexBuffer() const {
- return fGpu->quadIndexBuffer();
+const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
+ return fGpu->getQuadIndexBuffer();
}
-
-int GrContext::maxQuadsInIndexBuffer() const {
- return fGpu->maxQuadsInIndexBuffer();
-}
-
-
-