diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-16 16:12:19 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-02-16 16:12:19 +0000 |
commit | 86afc2ae27fec84c01eb0e81a32766bdaf67dca8 (patch) | |
tree | f03d5bbd019a262e7725fe5004653569d2cb97c8 | |
parent | f08a44980b5a0e22fe40bf4bbfef5898948875e2 (diff) |
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
-rw-r--r-- | gpu/include/GrAllocPool.h | 2 | ||||
-rw-r--r-- | gpu/include/GrContext.h | 22 | ||||
-rw-r--r-- | gpu/include/GrContext_impl.h | 8 | ||||
-rw-r--r-- | gpu/include/GrDrawTarget.h | 130 | ||||
-rw-r--r-- | gpu/include/GrGeometryBuffer.h | 6 | ||||
-rw-r--r-- | gpu/include/GrGpu.h | 32 | ||||
-rw-r--r-- | gpu/include/GrInOrderDrawBuffer.h | 60 | ||||
-rw-r--r-- | gpu/include/GrIndexBuffer.h | 7 | ||||
-rw-r--r-- | gpu/include/GrRect.h | 7 | ||||
-rw-r--r-- | gpu/include/GrTextContext.h | 4 | ||||
-rw-r--r-- | gpu/include/GrTypes.h | 8 | ||||
-rw-r--r-- | gpu/src/GrContext.cpp | 246 | ||||
-rw-r--r-- | gpu/src/GrDrawTarget.cpp | 125 | ||||
-rw-r--r-- | gpu/src/GrGpu.cpp | 59 | ||||
-rw-r--r-- | gpu/src/GrInOrderDrawBuffer.cpp | 228 | ||||
-rw-r--r-- | gpu/src/GrTextContext.cpp | 12 |
16 files changed, 695 insertions, 261 deletions
diff --git a/gpu/include/GrAllocPool.h b/gpu/include/GrAllocPool.h index 46359e5058..251c0b4021 100644 --- a/gpu/include/GrAllocPool.h +++ b/gpu/include/GrAllocPool.h @@ -33,7 +33,7 @@ public: /** * Returns a block of memory bytes size big. This address must not be * passed to realloc/free/delete or any other function that assumes the - * address was allocated by malloc or new (becuase it hasn't). + * address was allocated by malloc or new (because it hasn't). */ void* alloc(size_t bytes); diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h index 6b9c3f3009..973198b135 100644 --- a/gpu/include/GrContext.h +++ b/gpu/include/GrContext.h @@ -445,25 +445,33 @@ public: GrFontCache* getFontCache() { return fFontCache; }
GrDrawTarget* getTextTarget(const GrPaint& paint);
void flushText();
-
- const GrIndexBuffer* quadIndexBuffer() const;
- int maxQuadsInIndexBuffer() const;
+ const GrIndexBuffer* getQuadIndexBuffer() const;
private:
+ // used to keep track of when we need to flush the draw buffer
+ enum DrawCategory {
+ kBuffered_DrawCategory, // last draw was inserted in draw buffer
+ kUnbuffered_DrawCategory, // last draw was not inserted in the draw buffer
+ kText_DrawCategory // text context was last to draw
+ };
+ DrawCategory fLastDrawCategory;
+
GrGpu* fGpu;
GrTextureCache* fTextureCache;
GrFontCache* fFontCache;
- GrVertexBufferAllocPool* fTextVBAllocPool;
- GrIndexBufferAllocPool* fTextIBAllocPool;
- GrInOrderDrawBuffer* fTextDrawBuffer;
+ GrVertexBufferAllocPool* fDrawBufferVBAllocPool;
+ GrIndexBufferAllocPool* fDrawBufferIBAllocPool;
+ GrInOrderDrawBuffer* fDrawBuffer;
GrContext(GrGpu* gpu);
+ void flushDrawBuffer();
static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
bool finalizeTextureKey(GrTextureKey*, const GrSamplerState&) const;
- void prepareToDraw(const GrPaint& paint);
+
+ GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
void drawClipIntoStencil();
};
diff --git a/gpu/include/GrContext_impl.h b/gpu/include/GrContext_impl.h index b54e9274bc..8af38e667a 100644 --- a/gpu/include/GrContext_impl.h +++ b/gpu/include/GrContext_impl.h @@ -30,7 +30,7 @@ inline void GrContext::drawCustomVertices(const GrPaint& paint, GrDrawTarget::AutoReleaseGeometry geo;
- this->prepareToDraw(paint);
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
if (NULL != paint.getTexture()) {
if (NULL != texCoordSrc) {
@@ -47,7 +47,7 @@ inline void GrContext::drawCustomVertices(const GrPaint& paint, int vertexCount = posSrc.count();
int indexCount = (NULL != idxSrc) ? idxSrc->count() : 0;
- if (!geo.set(fGpu, layout, vertexCount, indexCount)) {
+ if (!geo.set(target, layout, vertexCount, indexCount)) {
GrPrintf("Failed to get space for vertices!");
return;
}
@@ -77,9 +77,9 @@ inline void GrContext::drawCustomVertices(const GrPaint& paint, }
if (NULL == idxSrc) {
- fGpu->drawNonIndexed(primitiveType, 0, vertexCount);
+ target->drawNonIndexed(primitiveType, 0, vertexCount);
} else {
- fGpu->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+ target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
}
}
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h index 88782f1647..91af9ce909 100644 --- a/gpu/include/GrDrawTarget.h +++ b/gpu/include/GrDrawTarget.h @@ -18,7 +18,6 @@ #ifndef GrDrawTarget_DEFINED #define GrDrawTarget_DEFINED -#include "GrScalar.h" #include "GrMatrix.h" #include "GrColor.h" #include "GrRefCnt.h" @@ -347,7 +346,11 @@ public: void disableState(uint32_t stateBits); bool isDitherState() const { - return fCurrDrawState.fFlagBits & kDither_StateBit; + return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit); + } + + bool isClipState() const { + return 0 != (fCurrDrawState.fFlagBits & kClip_StateBit); } /** @@ -435,6 +438,16 @@ public: GrAssert(texCoordIdx < kMaxTexCoords); return 1 << (stage + (texCoordIdx * kNumStages)); } + + /** + * Determines if blend is effectively disabled. + * + * @return true if blend can be disabled without changing the rendering + * result given the current state including the vertex layout specified + * with the vertex source. + */ + bool canDisableBlend() const; + private: static const int TEX_COORD_BIT_CNT = kNumStages*kMaxTexCoords; public: @@ -655,6 +668,45 @@ public: int startVertex, int vertexCount) = 0; + /** + * Helper function for drawing rects. This does not use the current index + * and vertex sources. After returning, the vertex and index sources may + * have changed. They should be reestablished before the next drawIndexed + * or drawNonIndexed. This cannot be called between reserving and releasing + * geometry. The GrDrawTarget subclass may be able to perform additional + * optimizations if drawRect is used rather than drawIndexed or + * drawNonIndexed. + * @param rect the rect to draw + * @param matrix optional matrix applied to rect (before viewMatrix) + * @param stageEnableMask bitmask indicating which stages are enabled. + * Bit i indicates whether stage i is enabled. + * @param srcRects specifies rects for stages enabled by stageEnableMask. + * if stageEnableMask bit i is 1, srcRects is not NULL, + * and srcRects[i] is not NULL, then srcRects[i] will be + * used as coordinates for stage i. Otherwise, if stage i + * is enabled then rect is used as the coordinates. + * @param srcMatrices optional matrices applied to srcRects. If + * srcRect[i] is non-NULL and srcMatrices[i] is + * non-NULL then srcRect[i] will be transformed by + * srcMatrix[i]. srcMatrices can be NULL when no + * srcMatrices are desired. + */ + virtual void drawRect(const GrRect& rect, + const GrMatrix* matrix, + int stageEnableMask, + const GrRect* srcRects[], + const GrMatrix* srcMatrices[]); + + /** + * Helper for drawRect when the caller doesn't need separate src rects or + * matrices. + */ + void drawSimpleRect(const GrRect& rect, + const GrMatrix* matrix, + int stageEnableMask) { + drawRect(rect, matrix, stageEnableMask, NULL, NULL); + } + /////////////////////////////////////////////////////////////////////////// class AutoStateRestore : ::GrNoncopyable { @@ -869,6 +921,65 @@ public: static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout, int texCoordOffsetsByStage[kNumStages], int *colorOffset); + + /** + * Accessing positions, texture coords, or colors, of a vertex within an + * array is a hassle involving casts and simple math. These helpers exist + * to keep GrDrawTarget clients' code a bit nicer looking. + */ + + /** + * Gets a pointer to a GrPoint of a vertex's position or texture + * coordinate. + * @param vertices the vetex array + * @param vertexIndex the index of the vertex in the array + * @param vertexSize the size of each vertex in the array + * @param offset the offset in bytes of the vertex component. + * Defaults to zero (corresponding to vertex position) + * @return pointer to the vertex component as a GrPoint + */ + static GrPoint* GetVertexPoint(void* vertices, + int vertexIndex, + int vertexSize, + int offset = 0) { + intptr_t start = GrTCast<intptr_t>(vertices); + return GrTCast<GrPoint*>(start + offset + + vertexIndex * vertexSize); + } + static const GrPoint* GetVertexPoint(const void* vertices, + int vertexIndex, + int vertexSize, + int offset = 0) { + intptr_t start = GrTCast<intptr_t>(vertices); + return GrTCast<const GrPoint*>(start + offset + + vertexIndex * vertexSize); + } + + /** + * Gets a pointer to a GrColor inside a vertex within a vertex array. + * @param vertices the vetex array + * @param vertexIndex the index of the vertex in the array + * @param vertexSize the size of each vertex in the array + * @param offset the offset in bytes of the vertex color + * @return pointer to the vertex component as a GrColor + */ + static GrColor* GetVertexColor(void* vertices, + int vertexIndex, + int vertexSize, + int offset) { + intptr_t start = GrTCast<intptr_t>(vertices); + return GrTCast<GrColor*>(start + offset + + vertexIndex * vertexSize); + } + static const GrColor* GetVertexColor(const void* vertices, + int vertexIndex, + int vertexSize, + int offset) { + const intptr_t start = GrTCast<intptr_t>(vertices); + return GrTCast<const GrColor*>(start + offset + + vertexIndex * vertexSize); + } + protected: // Helpers for GrDrawTarget subclasses that won't have private access to @@ -885,7 +996,8 @@ protected: virtual void releaseGeometryHelper() = 0; - virtual void clipWillChange(const GrClip& clip) = 0; + // subclass overrides to be notified when clip is set. + virtual void clipWillBeSet(const GrClip& clip) = 0; virtual void setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount) = 0; @@ -893,6 +1005,18 @@ protected: virtual void setIndexSourceToArrayHelper(const void* indexArray, int indexCount) = 0; + // Helpers for drawRect, protected so subclasses that override drawRect + // can use them. + static GrVertexLayout GetRectVertexLayout(int stageEnableMask, + const GrRect* srcRects[]); + + static void SetRectVertices(const GrRect& rect, + const GrMatrix* matrix, + const GrRect* srcRects[], + const GrMatrix* srcMatrices[], + GrVertexLayout layout, + void* vertices); + enum GeometrySrcType { kReserved_GeometrySrcType, // src was set using reserveAndLockGeometry kArray_GeometrySrcType, // src was set using set*SourceToArray diff --git a/gpu/include/GrGeometryBuffer.h b/gpu/include/GrGeometryBuffer.h index fc3e358312..af6eed5f63 100644 --- a/gpu/include/GrGeometryBuffer.h +++ b/gpu/include/GrGeometryBuffer.h @@ -31,7 +31,7 @@ public: *
* @return the size of the buffer in bytes
*/
- size_t size() { return fSizeInBytes; }
+ size_t size() const { return fSizeInBytes; }
/**
*Retrieves whether the buffer was created with the dynamic flag
@@ -107,9 +107,9 @@ protected: fDynamic(dynamic) {}
private:
- size_t fSizeInBytes;
+ size_t fSizeInBytes;
bool fDynamic;
-
+
typedef GrRefCnt INHERITED;
};
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h index 9fb7b9c604..a132e9f4cc 100644 --- a/gpu/include/GrGpu.h +++ b/gpu/include/GrGpu.h @@ -21,9 +21,7 @@ #include "GrRect.h" #include "GrRefCnt.h" #include "GrDrawTarget.h" -#include "GrGpuVertex.h" #include "GrTexture.h" -#include "GrMemory.h" class GrVertexBufferAllocPool; class GrIndexBufferAllocPool; @@ -295,29 +293,20 @@ public: int vertexCount); /** - * Determines if blend is effectively disabled. - * - * @return true if blend can be disabled without changing the rendering - * result given the current state including the vertex layout specified - * with the vertex source. - */ - bool canDisableBlend() const; - - /** * Returns an index buffer that can be used to render quads. - * Indices are 0, 1, 2, 0, 2, 3, etc. + * Six indices per quad: 0, 1, 2, 0, 2, 3, etc. + * The max number of quads can be queried using GrIndexBuffer::maxQuads(). * Draw with kTriangles_PrimitiveType + * @ return the quad index buffer */ - const GrIndexBuffer* quadIndexBuffer() const; - /** - * Gets the number of quads that can be rendered using quadIndexBuffer. - */ - int maxQuadsInIndexBuffer() const; + const GrIndexBuffer* getQuadIndexBuffer() const; /** - * Returns a vertex buffer with four position-only vertices [(0,0), (1,0), (1,1), (0,1)] + * Returns a vertex buffer with four position-only vertices [(0,0), (1,0), + * (1,1), (0,1)]. + * @ return unit square vertex buffer */ - const GrVertexBuffer* unitSquareVertexBuffer() const; + const GrVertexBuffer* getUnitSquareVertexBuffer() const; /** * Ensures that the current render target is actually set in the @@ -356,7 +345,10 @@ protected: GrRenderTarget* fStencilClipTarget; } fClipState; - virtual void clipWillChange(const GrClip& clip); + // GrDrawTarget override + virtual void clipWillBeSet(const GrClip& newClip); + + // prepares clip flushes gpu state before a draw bool setupClipAndFlushState(PrimitiveType type); struct BoundsState { diff --git a/gpu/include/GrInOrderDrawBuffer.h b/gpu/include/GrInOrderDrawBuffer.h index 463ea2d651..0dba8e3e00 100644 --- a/gpu/include/GrInOrderDrawBuffer.h +++ b/gpu/include/GrInOrderDrawBuffer.h @@ -41,31 +41,65 @@ class GrIndexBufferAllocPool; class GrInOrderDrawBuffer : public GrDrawTarget { public: + /** + * Creates a GrInOrderDrawBuffer + * + * @param vertexPool pool where vertices for queued draws will be saved when + * the vertex source is either reserved or array. + * @param indexPool pool where indices for queued draws will be saved when + * the index source is either reserved or array. + */ GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool, GrIndexBufferAllocPool* indexPool); virtual ~GrInOrderDrawBuffer(); + /** + * Copies the draw state and clip from target to this draw buffer. + * + * @param target the target whose clip and state should be copied. + */ void initializeDrawStateAndClip(const GrDrawTarget& target); + /** + * Provides the buffer with an index buffer that can be used for quad rendering. + * The buffer may be able to batch consecutive drawRects if this is provided. + * @param indexBuffer index buffer with quad indices. + */ + void setQuadIndexBuffer(const GrIndexBuffer* indexBuffer); + + /** + * Empties the draw buffer of any queued up draws. + */ + void reset(); + + /** + * plays the queued up draws to another target. Does not empty this buffer so + * that it can be played back multiple times. + * @param target the target to receive the playback + */ + void playback(GrDrawTarget* target); + + // overrides from GrDrawTarget virtual void drawIndexed(PrimitiveType primitiveType, int startVertex, int startIndex, int vertexCount, int indexCount); - virtual void drawNonIndexed(PrimitiveType primitiveType, int startVertex, int vertexCount); + virtual void drawRect(const GrRect& rect, + const GrMatrix* matrix = NULL, + int stageEnableMask = 0, + const GrRect* srcRects[] = NULL, + const GrMatrix* srcMatrices[] = NULL); + virtual bool geometryHints(GrVertexLayout vertexLayout, int* vertexCount, int* indexCount) const; - void reset(); - - void playback(GrDrawTarget* target); - private: struct Draw { @@ -85,7 +119,7 @@ private: void** vertices, void** indices); virtual void releaseGeometryHelper(); - virtual void clipWillChange(const GrClip& clip); + virtual void clipWillBeSet(const GrClip& newClip); virtual void setVertexSourceToArrayHelper(const void* vertexArray, int vertexCount); @@ -93,9 +127,11 @@ private: virtual void setIndexSourceToArrayHelper(const void* indexArray, int indexCount); + bool needsNewState() const; + bool needsNewClip() const; - bool grabState(); - bool grabClip(); + void pushState(); + void pushClip(); GrTAllocator<Draw> fDraws; // HACK: We currently do not hold refs on RTs in the saved draw states. @@ -106,7 +142,12 @@ private: GrTAllocator<SavedDrawState> fStates; GrTAllocator<GrClip> fClips; - bool fClipChanged; + bool fClipSet; + + GrVertexLayout fLastRectVertexLayout; + const GrIndexBuffer* fQuadIndexBuffer; + int fMaxQuads; + int fCurrQuad; GrVertexBufferAllocPool& fVertexPool; const GrVertexBuffer* fCurrPoolVertexBuffer; @@ -134,6 +175,7 @@ private: STATES_BLOCK_SIZE]; int8_t fClipsStorage[sizeof(GrClip) * CLIPS_BLOCK_SIZE]; + typedef GrDrawTarget INHERITED; }; #endif diff --git a/gpu/include/GrIndexBuffer.h b/gpu/include/GrIndexBuffer.h index 85ff749805..09d1977bfc 100644 --- a/gpu/include/GrIndexBuffer.h +++ b/gpu/include/GrIndexBuffer.h @@ -21,6 +21,13 @@ #include "GrGeometryBuffer.h" class GrIndexBuffer : public GrGeometryBuffer { +public: + /** + * Retrieves the maximum number of quads that could be rendered + * from the index buffer (using kTriangles_PrimitiveType). + * @return the maximum number of quads using full size of index buffer. + */ + int maxQuads() const { return size() / (sizeof(uint16_t) * 6); } protected: GrIndexBuffer(size_t sizeInBytes, bool dynamic) : INHERITED(sizeInBytes, dynamic) {} diff --git a/gpu/include/GrRect.h b/gpu/include/GrRect.h index 5192ebdf18..e98913a57c 100644 --- a/gpu/include/GrRect.h +++ b/gpu/include/GrRect.h @@ -131,7 +131,7 @@ struct GrRect { * Initialize a rectangle to a point. * @param pt the point used to initialize the rectanglee. */ - GrRect(GrPoint pt) { + explicit GrRect(const GrPoint& pt) { setToPoint(pt); } @@ -187,6 +187,11 @@ struct GrRect { bool isInverted() const { return (fLeft > fRight) || (fTop > fBottom); } + + bool contains(const GrPoint& point) const { + return point.fX >= fLeft && point.fX < fRight && + point.fY >= fTop && point.fY < fBottom; + } /** * Initialize a rectangle to a point. diff --git a/gpu/include/GrTextContext.h b/gpu/include/GrTextContext.h index 727358ec42..3dc9c7a29b 100644 --- a/gpu/include/GrTextContext.h +++ b/gpu/include/GrTextContext.h @@ -19,8 +19,10 @@ #define GrTextContext_DEFINED #include "GrGlyph.h" -#include "GrGpuVertex.h" +#include "GrPaint.h" +struct GrGpuTextVertex; +class GrMatrix; class GrContext; class GrTextStrike; class GrFontScaler; diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h index 9553678dca..83112397cc 100644 --- a/gpu/include/GrTypes.h +++ b/gpu/include/GrTypes.h @@ -141,14 +141,14 @@ static inline int16_t GrToS16(intptr_t x) { /////////////////////////////////////////////////////////////////////////////// /** - * Use to cast a pointer to a different type, and maintaining strict-aliasing + * Use to cast a ptr to a different type, and maintain strict-aliasing */ -template <typename Dst> Dst GrTCast(const void* ptr) { +template <typename Dst, typename Src> Dst GrTCast(Src src) { union { - const void* src; + Src src; Dst dst; } data; - data.src = ptr; + data.src = src; return data.dst; } diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp index c11d02fb5a..ad7f776a13 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 @@ GrContext::~GrContext() { 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 @@ void GrContext::drawRect(const GrPaint& paint, 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 @@ void GrContext::drawRect(const GrPaint& paint, 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 @@ void GrContext::drawRect(const GrPaint& paint, 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 @@ void GrContext::drawRectToRect(const GrPaint& paint, 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 @@ void GrContext::drawRectToRect(const GrPaint& paint, 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 @@ void GrContext::drawRectToRect(const GrPaint& paint, 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
+
+ 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
- fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);
}
void GrContext::drawVertices(const GrPaint& paint,
@@ -486,7 +481,7 @@ void GrContext::drawVertices(const GrPaint& paint, GrDrawTarget::AutoReleaseGeometry geo;
- this->prepareToDraw(paint);
+ GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
if (NULL != paint.getTexture()) {
if (NULL == texCoords) {
@@ -503,7 +498,7 @@ void GrContext::drawVertices(const GrPaint& paint, }
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 @@ void GrContext::drawVertices(const GrPaint& paint, 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 int worst_case_point_count(GrPathIter* path, 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 @@ static inline bool single_pass_path(const GrPathIter& path, 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 @@ void GrContext::drawPath(const GrPaint& paint, 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 @@ void GrContext::drawPath(const GrPaint& paint, 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 @@ void GrContext::drawPath(const GrPaint& paint, 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 @@ void GrContext::drawPath(const GrPaint& paint, }
}
}
- fGpu->setReverseFill(reverse);
+ target->setReverseFill(reverse);
GrPoint pts[4];
@@ -840,13 +835,13 @@ FINISHED: 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 @@ FINISHED: }
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 @@ FINISHED: ////////////////////////////////////////////////////////////////////////////////
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 @@ void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) { 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::resetContext() { }
void GrContext::setRenderTarget(GrRenderTarget* target) {
- flushText();
+ flush(false);
fGpu->setRenderTarget(target);
}
@@ -1028,19 +1051,28 @@ GrContext::GrContext(GrGpu* gpu) { 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);
-
- fTextDrawBuffer = new GrInOrderDrawBuffer(fTextVBAllocPool,
- fTextIBAllocPool);
+ fLastDrawCategory = kUnbuffered_DrawCategory;
+
+#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 @@ bool GrContext::finalizeTextureKey(GrTextureKey* key, 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();
-}
-
-
-
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp index 5cfc6f4895..06e5ab8b3f 100644 --- a/gpu/src/GrDrawTarget.cpp +++ b/gpu/src/GrDrawTarget.cpp @@ -17,6 +17,7 @@ #include "GrDrawTarget.h" #include "GrGpuVertex.h" +#include "GrTexture.h" // recursive helper for creating mask with all the tex coord bits set for // one stage @@ -291,7 +292,7 @@ GrDrawTarget::GrDrawTarget() { } void GrDrawTarget::setClip(const GrClip& clip) { - clipWillChange(clip); + clipWillBeSet(clip); fClip = clip; } @@ -484,7 +485,127 @@ void GrDrawTarget::setIndexSourceToBuffer(const GrIndexBuffer* buffer) { fGeometrySrc.fIndexBuffer = buffer; } -//////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +bool GrDrawTarget::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... + if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend && + kOne_BlendCoeff != fCurrDrawState.fSrcBlend) { + return false; + } + + // ...and the dst coef is always 0... + if (kISA_BlendCoeff != fCurrDrawState.fDstBlend && + kZero_BlendCoeff != fCurrDrawState.fDstBlend) { + return false; + } + + // ...and there isn't a texture with an alpha channel... + for (int s = 0; s < kNumStages; ++s) { + if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) { + GrAssert(NULL != fCurrDrawState.fTextures[s]); + GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config(); + + if (GrTexture::kRGB_565_PixelConfig != config && + GrTexture::kRGBX_8888_PixelConfig != config) { + return false; + } + } + } + + // ...then we disable blend. + return true; +} +/////////////////////////////////////////////////////////////////////////////// +void GrDrawTarget::drawRect(const GrRect& rect, + const GrMatrix* matrix, + int stageEnableMask, + const GrRect* srcRects[], + const GrMatrix* srcMatrices[]) { + GR_STATIC_ASSERT(8*sizeof(int) >= kNumStages); + + GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects); + + AutoReleaseGeometry geo(this, layout, 4, 0); + + SetRectVertices(rect, matrix, srcRects, + srcMatrices, layout, geo.vertices()); + + drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); +} + +GrVertexLayout GrDrawTarget::GetRectVertexLayout(int stageEnableMask, + const GrRect* srcRects[]) { + GrVertexLayout layout = 0; + + for (int i = 0; i < kNumStages; ++i) { + int numTC = 0; + if (stageEnableMask & (1 << i)) { + if (NULL != srcRects && NULL != srcRects[i]) { + layout |= StageTexCoordVertexLayoutBit(i, numTC); + ++numTC; + } else { + layout |= StagePosAsTexCoordVertexLayoutBit(i); + } + } + } + return layout; +} +void GrDrawTarget::SetRectVertices(const GrRect& rect, + const GrMatrix* matrix, + const GrRect* srcRects[], + const GrMatrix* srcMatrices[], + GrVertexLayout layout, + void* vertices) { +#if GR_DEBUG + // check that the layout and srcRects agree + for (int i = 0; i < kNumStages; ++i) { + if (VertexTexCoordsForStage(i, layout) >= 0) { + GR_DEBUGASSERT(NULL != srcRects && NULL != srcRects[i]); + } else { + GR_DEBUGASSERT(NULL == srcRects || NULL == srcRects[i]); + } + } +#endif + + int stageOffsets[kNumStages]; + int colorOffset; + int vsize = VertexSizeAndOffsetsByStage(layout, stageOffsets, &colorOffset); + GrAssert(-1 == colorOffset); + + GrTCast<GrPoint*>(vertices)->setRectFan(rect.fLeft, rect.fTop, + rect.fRight, rect.fBottom, + vsize); + if (NULL != matrix) { + matrix->mapPointsWithStride(GrTCast<GrPoint*>(vertices), vsize, 4); + } + + for (int i = 0; i < kNumStages; ++i) { + if (stageOffsets[i] > 0) { + GrPoint* coords = GrTCast<GrPoint*>(GrTCast<intptr_t>(vertices) + + stageOffsets[i]); + coords->setRectFan(srcRects[i]->fLeft, srcRects[i]->fTop, + srcRects[i]->fRight, srcRects[i]->fBottom, + vsize); + if (NULL != srcMatrices && NULL != srcMatrices[i]) { + srcMatrices[i]->mapPointsWithStride(coords, vsize, 4); + } + } + } +} + +/////////////////////////////////////////////////////////////////////////////// GrDrawTarget::AutoStateRestore::AutoStateRestore(GrDrawTarget* target) { fDrawTarget = target; diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp index e406f6f38f..5425b58954 100644 --- a/gpu/src/GrGpu.cpp +++ b/gpu/src/GrGpu.cpp @@ -92,49 +92,6 @@ void GrGpu::unimpl(const char 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... - if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend && - kOne_BlendCoeff != fCurrDrawState.fSrcBlend) { - return false; - } - - // ...and the dst coef is always 0... - if (kISA_BlendCoeff != fCurrDrawState.fDstBlend && - kZero_BlendCoeff != fCurrDrawState.fDstBlend) { - return false; - } - - // ...and there isn't a texture with an alpha channel... - for (int s = 0; s < kNumStages; ++s) { - if (VertexUsesStage(s, fGeometrySrc.fVertexLayout)) { - GrAssert(NULL != fCurrDrawState.fTextures[s]); - GrTexture::PixelConfig config = fCurrDrawState.fTextures[s]->config(); - - if (GrTexture::kRGB_565_PixelConfig != config && - GrTexture::kRGBX_8888_PixelConfig != config) { - return false; - } - } - } - - // ...then we disable blend. - return true; -} - -/////////////////////////////////////////////////////////////////////////////// - static const int MAX_QUADS = 1 << 12; // max possible: (1 << 14) - 1; GR_STATIC_ASSERT(4 * MAX_QUADS <= 65535); @@ -150,7 +107,7 @@ static inline void fill_indices(uint16_t* indices, int quadCount) { } } -const GrIndexBuffer* GrGpu::quadIndexBuffer() const { +const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const { if (NULL == fQuadIndexBuffer) { static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS; GrGpu* me = const_cast<GrGpu*>(this); @@ -176,7 +133,7 @@ const GrIndexBuffer* GrGpu::quadIndexBuffer() const { return fQuadIndexBuffer; } -const GrVertexBuffer* GrGpu::unitSquareVertexBuffer() const { +const GrVertexBuffer* GrGpu::getUnitSquareVertexBuffer() const { if (NULL == fUnitSquareVertexBuffer) { static const GrPoint DATA[] = { @@ -201,14 +158,10 @@ const GrVertexBuffer* GrGpu::unitSquareVertexBuffer() const { return fUnitSquareVertexBuffer; } -int GrGpu::maxQuadsInIndexBuffer() const { - return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS; -} - /////////////////////////////////////////////////////////////////////////////// -void GrGpu::clipWillChange(const GrClip& clip) { - if (clip != fClip) { +void GrGpu::clipWillBeSet(const GrClip& newClip) { + if (newClip != fClip) { fClipState.fClipIsDirty = true; } } @@ -260,7 +213,7 @@ bool GrGpu::setupClipAndFlushState(PrimitiveType type) { } fVertexPool->unlock(); this->setVertexSourceToBuffer(0, vertexBuffer); - this->setIndexSourceToBuffer(quadIndexBuffer()); + this->setIndexSourceToBuffer(getQuadIndexBuffer()); this->setViewMatrix(GrMatrix::I()); // don't clip the clip or recurse! this->disableState(kClip_StateBit); @@ -268,7 +221,7 @@ bool GrGpu::setupClipAndFlushState(PrimitiveType type) { this->setStencilPass((GrDrawTarget::StencilPass)kSetClip_StencilPass); int currRect = 0; while (currRect < rectTotal) { - int rectCount = GrMin(this->maxQuadsInIndexBuffer(), + int rectCount = GrMin(MAX_QUADS, rectTotal - currRect); this->drawIndexed(kTriangles_PrimitiveType, vStart + currRect * 4, diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp index 49b8901810..25e74e37e4 100644 --- a/gpu/src/GrInOrderDrawBuffer.cpp +++ b/gpu/src/GrInOrderDrawBuffer.cpp @@ -18,6 +18,8 @@ #include "GrInOrderDrawBuffer.h" #include "GrTexture.h" #include "GrBufferAllocPool.h" +#include "GrIndexBuffer.h" +#include "GrVertexBuffer.h" #include "GrGpu.h" GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool, @@ -25,7 +27,13 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool, fDraws(DRAWS_BLOCK_SIZE, fDrawsStorage), fStates(STATES_BLOCK_SIZE, fStatesStorage), fClips(CLIPS_BLOCK_SIZE, fClipsStorage), - fClipChanged(true), + fClipSet(true), + + fLastRectVertexLayout(0), + fQuadIndexBuffer(NULL), + fMaxQuads(0), + fCurrQuad(0), + fVertexPool(*vertexPool), fCurrPoolVertexBuffer(NULL), fCurrPoolStartVertex(0), @@ -41,7 +49,8 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool, } GrInOrderDrawBuffer::~GrInOrderDrawBuffer() { - reset(); + this->reset(); + GrSafeUnref(fQuadIndexBuffer); } void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) { @@ -49,6 +58,121 @@ void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) this->setClip(target.getClip()); } +void GrInOrderDrawBuffer::setQuadIndexBuffer(const GrIndexBuffer* indexBuffer) { + bool newIdxBuffer = fQuadIndexBuffer != indexBuffer; + if (newIdxBuffer) { + GrSafeUnref(fQuadIndexBuffer); + fQuadIndexBuffer = indexBuffer; + GrSafeRef(fQuadIndexBuffer); + fCurrQuad = 0; + fMaxQuads = (NULL == indexBuffer) ? 0 : indexBuffer->maxQuads(); + } else { + GrAssert((NULL == indexBuffer && 0 == fMaxQuads) || + (indexBuffer->maxQuads() == fMaxQuads)); + } +} + +void GrInOrderDrawBuffer::drawRect(const GrRect& rect, + const GrMatrix* matrix, + int stageEnableMask, + const GrRect* srcRects[], + const GrMatrix* srcMatrices[]) { + + GrAssert(!(NULL == fQuadIndexBuffer && fCurrQuad)); + GrAssert(!(fDraws.empty() && fCurrQuad)); + GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer)); + + // if we have a quad IB then either append to the previous run of + // rects or start a new run + if (fMaxQuads) { + + bool appendToPreviousDraw = false; + GrVertexLayout layout = GetRectVertexLayout(stageEnableMask, srcRects); + AutoReleaseGeometry geo(this, layout, 4, 0); + AutoViewMatrixRestore avmr(this); + GrMatrix combinedMatrix = this->getViewMatrix(); + this->setViewMatrix(GrMatrix::I()); + if (NULL != matrix) { + combinedMatrix.preConcat(*matrix); + } + + SetRectVertices(rect, &combinedMatrix, srcRects, srcMatrices, layout, geo.vertices()); + + // we don't want to miss an opportunity to batch rects together + // simply because the clip has changed if the clip doesn't affect + // the rect. + bool disabledClip = false; + if (this->isClipState() && fClip.isRect()) { + GrRect clipRect = GrRect(*fClip.getRects()); + // If the clip rect touches the edge of the viewport, extended it + // out (close) to infinity to avoid bogus intersections. + // We might consider a more exact clip to viewport if this + // conservative test fails. + const GrRenderTarget* target = this->getRenderTarget(); + if (0 >= clipRect.fLeft) { + clipRect.fLeft = GR_ScalarMin; + } + if (target->width() <= clipRect.fRight) { + clipRect.fRight = GR_ScalarMax; + } + if (0 >= clipRect.top()) { + clipRect.fTop = GR_ScalarMin; + } + if (target->height() <= clipRect.fBottom) { + clipRect.fBottom = GR_ScalarMax; + } + int stride = VertexSize(layout); + bool insideClip = true; + for (int v = 0; v < 4; ++v) { + const GrPoint& p = *GetVertexPoint(geo.vertices(), v, stride); + if (!clipRect.contains(p)) { + insideClip = false; + break; + } + } + if (insideClip) { + this->disableState(kClip_StateBit); + disabledClip = true; + } + } + if (!needsNewClip() && !needsNewState() && fCurrQuad > 0 && + fCurrQuad < fMaxQuads && layout == fLastRectVertexLayout) { + + int vsize = VertexSize(layout); + + Draw& lastDraw = fDraws.back(); + + GrAssert(lastDraw.fIndexBuffer == fQuadIndexBuffer); + GrAssert(kTriangles_PrimitiveType == lastDraw.fPrimitiveType); + GrAssert(0 == lastDraw.fVertexCount % 4); + GrAssert(0 == lastDraw.fIndexCount % 6); + GrAssert(0 == lastDraw.fStartIndex); + + appendToPreviousDraw = lastDraw.fVertexBuffer == fCurrPoolVertexBuffer && + (fCurrQuad * 4 + lastDraw.fStartVertex) == fCurrPoolStartVertex; + if (appendToPreviousDraw) { + lastDraw.fVertexCount += 4; + lastDraw.fIndexCount += 6; + fCurrQuad += 1; + GrAssert(0 == fUsedReservedVertexBytes); + fUsedReservedVertexBytes = 4 * vsize; + } + } + if (!appendToPreviousDraw) { + this->setIndexSourceToBuffer(fQuadIndexBuffer); + drawIndexed(kTriangles_PrimitiveType, 0, 0, 4, 6); + fCurrQuad = 1; + fLastRectVertexLayout = layout; + } + if (disabledClip) { + this->enableState(kClip_StateBit); + } +this->enableState(kClip_StateBit); + } else { + INHERITED::drawRect(rect, matrix, stageEnableMask, srcRects, srcMatrices); + } +} + void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, int startVertex, int startIndex, @@ -59,14 +183,24 @@ void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, return; } + fCurrQuad = 0; + Draw& draw = fDraws.push_back(); draw.fPrimitiveType = primitiveType; draw.fStartVertex = startVertex; draw.fStartIndex = startIndex; draw.fVertexCount = vertexCount; draw.fIndexCount = indexCount; - draw.fClipChanged = grabClip(); - draw.fStateChanged = grabState(); + + draw.fClipChanged = this->needsNewClip(); + if (draw.fClipChanged) { + this->pushClip(); + } + + draw.fStateChanged = this->needsNewState(); + if (draw.fStateChanged) { + this->pushState(); + } draw.fVertexLayout = fGeometrySrc.fVertexLayout; switch (fGeometrySrc.fVertexSrc) { @@ -76,8 +210,7 @@ void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, case kReserved_GeometrySrcType: { size_t vertexBytes = (vertexCount + startVertex) * VertexSize(fGeometrySrc.fVertexLayout); - fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes, - vertexBytes); + fUsedReservedVertexBytes = GrMax(fUsedReservedVertexBytes, vertexBytes); } // fallthrough case kArray_GeometrySrcType: draw.fVertexBuffer = fCurrPoolVertexBuffer; @@ -86,6 +219,7 @@ void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, default: GrCrash("unknown geom src type"); } + draw.fVertexBuffer->ref(); switch (fGeometrySrc.fIndexSrc) { case kBuffer_GeometrySrcType: @@ -102,6 +236,7 @@ void GrInOrderDrawBuffer::drawIndexed(PrimitiveType primitiveType, default: GrCrash("unknown geom src type"); } + draw.fIndexBuffer->ref(); } void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType, @@ -111,6 +246,8 @@ void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType, return; } + fCurrQuad = 0; + Draw& draw = fDraws.push_back(); draw.fPrimitiveType = primitiveType; draw.fStartVertex = startVertex; @@ -118,8 +255,15 @@ void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType, draw.fVertexCount = vertexCount; draw.fIndexCount = 0; - draw.fClipChanged = grabClip(); - draw.fStateChanged = grabState(); + draw.fClipChanged = this->needsNewClip(); + if (draw.fClipChanged) { + this->pushClip(); + } + + draw.fStateChanged = this->needsNewState(); + if (draw.fStateChanged) { + this->pushState(); + } draw.fVertexLayout = fGeometrySrc.fVertexLayout; switch (fGeometrySrc.fVertexSrc) { @@ -139,6 +283,8 @@ void GrInOrderDrawBuffer::drawNonIndexed(PrimitiveType primitiveType, default: GrCrash("unknown geom src type"); } + draw.fVertexBuffer->ref(); + draw.fIndexBuffer = NULL; } void GrInOrderDrawBuffer::reset() { @@ -146,12 +292,19 @@ void GrInOrderDrawBuffer::reset() { uint32_t numStates = fStates.count(); for (uint32_t i = 0; i < numStates; ++i) { for (int s = 0; s < kNumStages; ++s) { - GrTexture* tex = accessSavedDrawState(fStates[i]).fTextures[s]; + GrTexture* tex = this->accessSavedDrawState(fStates[i]).fTextures[s]; if (NULL != tex) { tex->unref(); } } } + int numDraws = fDraws.count(); + for (int d = 0; d < numDraws; ++d) { + // we always have a VB, but not always an IB + GrAssert(NULL != fDraws[d].fVertexBuffer); + fDraws[d].fVertexBuffer->unref(); + GrSafeUnref(fDraws[d].fIndexBuffer); + } fDraws.reset(); fStates.reset(); @@ -159,6 +312,8 @@ void GrInOrderDrawBuffer::reset() { fIndexPool.reset(); fClips.reset(); + + fCurrQuad = 0; } void GrInOrderDrawBuffer::playback(GrDrawTarget* target) { @@ -331,37 +486,36 @@ void GrInOrderDrawBuffer::setIndexSourceToArrayHelper(const void* indexArray, GR_DEBUGASSERT(success); } -bool GrInOrderDrawBuffer::grabState() { - bool newState; - if (fStates.empty()) { - newState = true; - } else { - const DrState& old = accessSavedDrawState(fStates.back()); - newState = old != fCurrDrawState; - } - if (newState) { - for (int s = 0; s < kNumStages; ++s) { - if (NULL != fCurrDrawState.fTextures[s]) { - fCurrDrawState.fTextures[s]->ref(); - } - } - saveCurrentDrawState(&fStates.push_back()); - } - return newState; +bool GrInOrderDrawBuffer::needsNewState() const { + if (fStates.empty()) { + return true; + } else { + const DrState& old = this->accessSavedDrawState(fStates.back()); + return old != fCurrDrawState; + } } -bool GrInOrderDrawBuffer::grabClip() { - if ((fCurrDrawState.fFlagBits & kClip_StateBit) && - (fClipChanged || fClips.empty())) { - - fClips.push_back() = fClip; - fClipChanged = false; - return true; +void GrInOrderDrawBuffer::pushState() { + for (int s = 0; s < kNumStages; ++s) { + GrSafeRef(fCurrDrawState.fTextures[s]); + } + this->saveCurrentDrawState(&fStates.push_back()); + } + +bool GrInOrderDrawBuffer::needsNewClip() const { + if (fCurrDrawState.fFlagBits & kClip_StateBit) { + if (fClips.empty() || (fClipSet && fClips.back() != fClip)) { + return true; + } } return false; } - -void GrInOrderDrawBuffer::clipWillChange(const GrClip& clip) { - fClipChanged = true; + +void GrInOrderDrawBuffer::pushClip() { + fClips.push_back() = fClip; + fClipSet = false; +} + +void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) { + fClipSet = true; } - diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp index d59f4cee0d..7341005b86 100644 --- a/gpu/src/GrTextContext.cpp +++ b/gpu/src/GrTextContext.cpp @@ -15,13 +15,14 @@ */ +#include "GrTextContext.h" #include "GrAtlas.h" -#include "GrClipIterator.h" #include "GrContext.h" -#include "GrTextContext.h" #include "GrTextStrike.h" #include "GrTextStrike_impl.h" #include "GrFontScaler.h" +#include "GrIndexBuffer.h" +#include "GrGpuVertex.h" static const int TEXT_STAGE = 1; @@ -45,7 +46,7 @@ void GrTextContext::flushGlyphs() { GrAssert(fCurrTexture); fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture); fDrawTarget->setTextureMatrix(TEXT_STAGE, GrMatrix::I()); - fDrawTarget->setIndexSourceToBuffer(fContext->quadIndexBuffer()); + fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->drawIndexed(GrDrawTarget::kTriangles_PrimitiveType, 0, 0, fCurrVertex, nIndices); @@ -217,11 +218,12 @@ HAS_ATLAS: NULL); } + int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->size() / (6 * sizeof(uint16_t)); if (fMaxVertices < kMinRequestedVerts) { fMaxVertices = kDefaultRequestedVerts; - } else if (fMaxVertices > (fContext->maxQuadsInIndexBuffer() * 4)) { + } else if (fMaxVertices > maxQuadVertices) { // don't exceed the limit of the index buffer - fMaxVertices = (fContext->maxQuadsInIndexBuffer() * 4); + fMaxVertices = maxQuadVertices; } bool success = fDrawTarget->reserveAndLockGeometry(fVertexLayout, fMaxVertices, 0, |