aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-02-16 16:12:19 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-02-16 16:12:19 +0000
commit86afc2ae27fec84c01eb0e81a32766bdaf67dca8 (patch)
treef03d5bbd019a262e7725fe5004653569d2cb97c8
parentf08a44980b5a0e22fe40bf4bbfef5898948875e2 (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.h2
-rw-r--r--gpu/include/GrContext.h22
-rw-r--r--gpu/include/GrContext_impl.h8
-rw-r--r--gpu/include/GrDrawTarget.h130
-rw-r--r--gpu/include/GrGeometryBuffer.h6
-rw-r--r--gpu/include/GrGpu.h32
-rw-r--r--gpu/include/GrInOrderDrawBuffer.h60
-rw-r--r--gpu/include/GrIndexBuffer.h7
-rw-r--r--gpu/include/GrRect.h7
-rw-r--r--gpu/include/GrTextContext.h4
-rw-r--r--gpu/include/GrTypes.h8
-rw-r--r--gpu/src/GrContext.cpp246
-rw-r--r--gpu/src/GrDrawTarget.cpp125
-rw-r--r--gpu/src/GrGpu.cpp59
-rw-r--r--gpu/src/GrInOrderDrawBuffer.cpp228
-rw-r--r--gpu/src/GrTextContext.cpp12
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,