diff options
-rw-r--r-- | include/gpu/GrConfig.h | 9 | ||||
-rw-r--r-- | include/gpu/GrUserConfig.h | 11 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 65 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 38 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 10 |
5 files changed, 130 insertions, 3 deletions
diff --git a/include/gpu/GrConfig.h b/include/gpu/GrConfig.h index d929d580ac..00e77eadb3 100644 --- a/include/gpu/GrConfig.h +++ b/include/gpu/GrConfig.h @@ -316,6 +316,15 @@ inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); } #endif /** + * GR_STATIC_RECT_VB controls whether rects are drawn by issuing a vertex + * for each corner or using a static vb that is positioned by modifying the + * view / texture matrix. + */ +#if !defined(GR_STATIC_RECT_VB) + #define GR_STATIC_RECT_VB 1 +#endif + +/** * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should * lock a GrGeometryBuffer to update its contents. It will use lock() if the * size of the updated region is greater than the threshold. Otherwise it will diff --git a/include/gpu/GrUserConfig.h b/include/gpu/GrUserConfig.h index b9df083c48..594889b1a7 100644 --- a/include/gpu/GrUserConfig.h +++ b/include/gpu/GrUserConfig.h @@ -21,7 +21,16 @@ #define GR_DEBUG 1 #endif -/* +/** + * When drawing rects this causes Ganesh to use a vertex buffer containing + * a unit square that is positioned by a matrix. Enable on systems where + * emitting per-rect-draw verts is more expensive than constant/matrix + * updates. Defaults to 0. + */ +//#define GR_STATIC_RECT_VB 1 + + +/** * This gives a threshold in bytes of when to lock a GrGeometryBuffer vs using * updateData. (Note the depending on the underlying 3D API the update functions * may always be implemented using a lock) diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index a73a5b5278..ef3fd6d2f3 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -734,6 +734,8 @@ void GrContext::drawRect(const GrPaint& paint, if (width >= 0) { // TODO: consider making static vertex buffers for these cases. + // Hairline could be done by just adding closing vertex to + // unitSquareVertexBuffer() static const int worstCaseVertCount = 10; target->drawState()->setVertexLayout(GrDrawState::kDefault_VertexLayout); @@ -771,7 +773,30 @@ void GrContext::drawRect(const GrPaint& paint, target->drawNonIndexed(primType, 0, vertCount); } else { - target->drawSimpleRect(rect, matrix); +#if GR_STATIC_RECT_VB + const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); + if (NULL == sqVB) { + GrPrintf("Failed to create static rect vb.\n"); + return; + } + + GrDrawState* drawState = target->drawState(); + drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); + target->setVertexSourceToBuffer(sqVB); + SkMatrix m; + m.setAll(rect.width(), 0, rect.fLeft, + 0, rect.height(), rect.fTop, + 0, 0, SkMatrix::I()[8]); + + if (NULL != matrix) { + m.postConcat(*matrix); + } + GrDrawState::AutoViewMatrixRestore avmr(drawState, m); + + target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); +#else + target->drawSimpleRect(rect, matrix); +#endif } } @@ -789,6 +814,43 @@ void GrContext::drawRectToRect(const GrPaint& paint, } GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW); + +#if GR_STATIC_RECT_VB + GrDrawState::AutoStageDisable atr(fDrawState); + GrDrawState* drawState = target->drawState(); + + SkMatrix m; + + m.setAll(dstRect.width(), 0, dstRect.fLeft, + 0, dstRect.height(), dstRect.fTop, + 0, 0, SkMatrix::I()[8]); + if (NULL != dstMatrix) { + m.postConcat(*dstMatrix); + } + + // The first color stage's coords come from srcRect rather than applying a matrix to dstRect. + // We explicitly compute a matrix for that stage below, no need to adjust here. + static const uint32_t kExplicitCoordMask = 1 << GrPaint::kFirstColorStage; + GrDrawState::AutoViewMatrixRestore avmr(drawState, m, kExplicitCoordMask); + + m.setAll(srcRect.width(), 0, srcRect.fLeft, + 0, srcRect.height(), srcRect.fTop, + 0, 0, SkMatrix::I()[8]); + if (NULL != srcMatrix) { + m.postConcat(*srcMatrix); + } + + drawState->preConcatStageMatrices(kExplicitCoordMask, m); + + const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); + if (NULL == sqVB) { + GrPrintf("Failed to create static rect vb.\n"); + return; + } + drawState->setVertexLayout(GrDrawState::kDefault_VertexLayout); + target->setVertexSourceToBuffer(sqVB); + target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4); +#else GrDrawState::AutoStageDisable atr(fDrawState); const GrRect* srcRects[GrDrawState::kNumStages] = {NULL}; @@ -797,6 +859,7 @@ void GrContext::drawRectToRect(const GrPaint& paint, srcMatrices[0] = srcMatrix; target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices); +#endif } void GrContext::drawVertices(const GrPaint& paint, diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 3f33a2abeb..c9aa046fa2 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -33,6 +33,7 @@ GrGpu::GrGpu() , fIndexPool(NULL) , fVertexPoolUseCnt(0) , fIndexPoolUseCnt(0) + , fUnitSquareVertexBuffer(NULL) , fQuadIndexBuffer(NULL) , fContextIsDirty(true) { @@ -65,7 +66,10 @@ void GrGpu::abandonResources() { } GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); + GrAssert(NULL == fUnitSquareVertexBuffer || + !fUnitSquareVertexBuffer->isValid()); GrSafeSetNull(fQuadIndexBuffer); + GrSafeSetNull(fUnitSquareVertexBuffer); delete fVertexPool; fVertexPool = NULL; delete fIndexPool; @@ -81,7 +85,10 @@ void GrGpu::releaseResources() { } GrAssert(NULL == fQuadIndexBuffer || !fQuadIndexBuffer->isValid()); + GrAssert(NULL == fUnitSquareVertexBuffer || + !fUnitSquareVertexBuffer->isValid()); GrSafeSetNull(fQuadIndexBuffer); + GrSafeSetNull(fUnitSquareVertexBuffer); delete fVertexPool; fVertexPool = NULL; delete fIndexPool; @@ -289,6 +296,37 @@ const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { return fQuadIndexBuffer; } +const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const { + if (NULL == fUnitSquareVertexBuffer) { + + static const GrPoint DATA[] = { + { 0, 0 }, + { SK_Scalar1, 0 }, + { SK_Scalar1, SK_Scalar1 }, + { 0, SK_Scalar1 } +#if 0 + GrPoint(0, 0), + GrPoint(SK_Scalar1,0), + GrPoint(SK_Scalar1,SK_Scalar1), + GrPoint(0, SK_Scalar1) +#endif + }; + static const size_t SIZE = sizeof(DATA); + + GrGpu* me = const_cast<GrGpu*>(this); + fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false); + if (NULL != fUnitSquareVertexBuffer) { + if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) { + fUnitSquareVertexBuffer->unref(); + fUnitSquareVertexBuffer = NULL; + GrCrash("Can't get vertices into buffer!"); + } + } + } + + return fUnitSquareVertexBuffer; +} + //////////////////////////////////////////////////////////////////////////////// bool GrGpu::setupClipAndFlushState(DrawType type) { diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 93427e01ac..d0ca377093 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -146,6 +146,13 @@ public: const GrIndexBuffer* getQuadIndexBuffer() const; /** + * Returns a vertex buffer with four position-only vertices [(0,0), (1,0), + * (1,1), (0,1)]. + * @ return unit square vertex buffer + */ + const GrVertexBuffer* getUnitSquareVertexBuffer() const; + + /** * Resolves MSAA. */ void resolveRenderTarget(GrRenderTarget* target); @@ -527,7 +534,8 @@ private: // counts number of uses of vertex/index pool in the geometry stack int fVertexPoolUseCnt; int fIndexPoolUseCnt; - // this is mutable so it can be created on-demand + // these are mutable so they can be created on-demand + mutable GrVertexBuffer* fUnitSquareVertexBuffer; mutable GrIndexBuffer* fQuadIndexBuffer; bool fContextIsDirty; ResourceList fResourceList; |