aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-19 20:17:28 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-02-19 20:17:28 +0000
commit880b8fcf255e67a15687e8b7cc47397372db683c (patch)
tree116b5f1ccedc6a9187435eb471061436e67cdf1a /src
parenta62a9ce9e65071797e971c36a5b02d8931d32732 (diff)
Refactor tracking of bound vbufs and ibufs and vertex attrib arrays.
Review URL: https://codereview.appspot.com/7359045 git-svn-id: http://skia.googlecode.com/svn/trunk@7779 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/gpu/gl/GrGLIndexBuffer.cpp4
-rw-r--r--src/gpu/gl/GrGLIndexBuffer.h19
-rw-r--r--src/gpu/gl/GrGLProgram.cpp14
-rw-r--r--src/gpu/gl/GrGLProgram.h12
-rw-r--r--src/gpu/gl/GrGLVertexBuffer.cpp4
-rw-r--r--src/gpu/gl/GrGLVertexBuffer.h21
-rw-r--r--src/gpu/gl/GrGpuGL.cpp173
-rw-r--r--src/gpu/gl/GrGpuGL.h179
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp156
9 files changed, 344 insertions, 238 deletions
diff --git a/src/gpu/gl/GrGLIndexBuffer.cpp b/src/gpu/gl/GrGLIndexBuffer.cpp
index 561133add8..035bfaccce 100644
--- a/src/gpu/gl/GrGLIndexBuffer.cpp
+++ b/src/gpu/gl/GrGLIndexBuffer.cpp
@@ -48,10 +48,6 @@ void GrGLIndexBuffer::bind() const {
GPUGL->notifyIndexBufferBind(this);
}
-GrGLuint GrGLIndexBuffer::bufferID() const {
- return fBufferID;
-}
-
void* GrGLIndexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());
diff --git a/src/gpu/gl/GrGLIndexBuffer.h b/src/gpu/gl/GrGLIndexBuffer.h
index 936e650e56..5182573abf 100644
--- a/src/gpu/gl/GrGLIndexBuffer.h
+++ b/src/gpu/gl/GrGLIndexBuffer.h
@@ -19,9 +19,18 @@ class GrGLIndexBuffer : public GrIndexBuffer {
public:
+ GrGLIndexBuffer(GrGpuGL* gpu,
+ bool isWrapped,
+ GrGLuint id,
+ size_t sizeInBytes,
+ bool dynamic);
+
virtual ~GrGLIndexBuffer() { this->release(); }
- GrGLuint bufferID() const;
+ GrGLuint bufferID() const { return fBufferID; }
+ size_t baseOffset() const { return 0; }
+
+ void bind() const;
// overrides of GrIndexBuffer
virtual void* lock();
@@ -31,24 +40,16 @@ public:
virtual bool updateData(const void* src, size_t srcSizeInBytes);
protected:
- GrGLIndexBuffer(GrGpuGL* gpu,
- bool isWrapped,
- GrGLuint id,
- size_t sizeInBytes,
- bool dynamic);
// overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
- void bind() const;
GrGLuint fBufferID;
void* fLockPtr;
- friend class GrGpuGL;
-
typedef GrIndexBuffer INHERITED;
};
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 8620c5cb4a..ccea34eae5 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -966,12 +966,12 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
// Bind the attrib locations to same values for all shaders
GL_CALL(BindAttribLocation(fProgramID,
- PositionAttributeIdx(),
+ kPositionAttributeIndex,
builder.positionAttribute().c_str()));
- GL_CALL(BindAttribLocation(fProgramID, TexCoordAttributeIdx(), TEX_ATTR_NAME));
- GL_CALL(BindAttribLocation(fProgramID, ColorAttributeIdx(), COL_ATTR_NAME));
- GL_CALL(BindAttribLocation(fProgramID, CoverageAttributeIdx(), COV_ATTR_NAME));
- GL_CALL(BindAttribLocation(fProgramID, EdgeAttributeIdx(), EDGE_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, kTexCoordAttributeIndex, TEX_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, kColorAttributeIndex, COL_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, kCoverageAttributeIndex, COV_ATTR_NAME));
+ GL_CALL(BindAttribLocation(fProgramID, kEdgeAttributeIndex, EDGE_ATTR_NAME));
GL_CALL(LinkProgram(fProgramID));
@@ -1067,7 +1067,7 @@ void GrGLProgram::setColor(const GrDrawState& drawState,
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(color, c);
- GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c));
+ GL_CALL(VertexAttrib4fv(kColorAttributeIndex, c));
sharedState->fConstAttribColor = color;
}
break;
@@ -1101,7 +1101,7 @@ void GrGLProgram::setCoverage(const GrDrawState& drawState,
// OpenGL ES only supports the float varieties of glVertexAttrib
GrGLfloat c[4];
GrColorToRGBAFloat(coverage, c);
- GL_CALL(VertexAttrib4fv(GrGLProgram::CoverageAttributeIdx(), c));
+ GL_CALL(VertexAttrib4fv(kCoverageAttributeIndex, c));
sharedState->fConstAttribCoverage = coverage;
}
break;
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 2c3c973c7c..2c48d73e03 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -81,11 +81,13 @@ public:
/**
* Attribute indices. These should not overlap.
*/
- static int PositionAttributeIdx() { return 0; }
- static int ColorAttributeIdx() { return 1; }
- static int CoverageAttributeIdx() { return 2; }
- static int EdgeAttributeIdx() { return 3; }
- static int TexCoordAttributeIdx() { return 4; }
+ enum {
+ kPositionAttributeIndex = 0,
+ kColorAttributeIndex = 1,
+ kCoverageAttributeIndex = 2,
+ kEdgeAttributeIndex = 3,
+ kTexCoordAttributeIndex = 4,
+ };
/**
* Some GL state that is relevant to programs is not stored per-program. In particular vertex
diff --git a/src/gpu/gl/GrGLVertexBuffer.cpp b/src/gpu/gl/GrGLVertexBuffer.cpp
index 1512fef1fa..42b76ea4a8 100644
--- a/src/gpu/gl/GrGLVertexBuffer.cpp
+++ b/src/gpu/gl/GrGLVertexBuffer.cpp
@@ -47,10 +47,6 @@ void GrGLVertexBuffer::bind() const {
GPUGL->notifyVertexBufferBind(this);
}
-GrGLuint GrGLVertexBuffer::bufferID() const {
- return fBufferID;
-}
-
void* GrGLVertexBuffer::lock() {
GrAssert(fBufferID);
GrAssert(!isLocked());
diff --git a/src/gpu/gl/GrGLVertexBuffer.h b/src/gpu/gl/GrGLVertexBuffer.h
index 17b0283f10..61b5020404 100644
--- a/src/gpu/gl/GrGLVertexBuffer.h
+++ b/src/gpu/gl/GrGLVertexBuffer.h
@@ -18,34 +18,35 @@ class GrGpuGL;
class GrGLVertexBuffer : public GrVertexBuffer {
public:
+ GrGLVertexBuffer(GrGpuGL* gpu,
+ bool isWrapped,
+ GrGLuint id,
+ size_t sizeInBytes,
+ bool dynamic);
virtual ~GrGLVertexBuffer() { this->release(); }
+
+ GrGLuint bufferID() const { return fBufferID; }
+ size_t baseOffset() const { return 0; }
+
+ void bind() const;
+
// overrides of GrVertexBuffer
virtual void* lock();
virtual void* lockPtr() const;
virtual void unlock();
virtual bool isLocked() const;
virtual bool updateData(const void* src, size_t srcSizeInBytes);
- GrGLuint bufferID() const;
protected:
- GrGLVertexBuffer(GrGpuGL* gpu,
- bool isWrapped,
- GrGLuint id,
- size_t sizeInBytes,
- bool dynamic);
-
// overrides of GrResource
virtual void onAbandon() SK_OVERRIDE;
virtual void onRelease() SK_OVERRIDE;
private:
- void bind() const;
GrGLuint fBufferID;
void* fLockPtr;
- friend class GrGpuGL;
-
typedef GrVertexBuffer INHERITED;
};
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index f14238cdd9..baa6e44ef2 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -178,6 +178,8 @@ GrGpuGL::GrGpuGL(const GrGLContextInfo& ctxInfo) : fGLContextInfo(ctxInfo) {
fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContextInfo()));
+ fHWGeometryState.setMaxAttribArrays(this->glCaps().maxVertexAttributes());
+
fLastSuccessfulStencilFmtIdx = 0;
if (false) { // avoid bit rot, suppress warning
fbo_test(this->glInterface(), 0, 0);
@@ -446,10 +448,7 @@ void GrGpuGL::onResetContext() {
fHWStencilSettings.invalidate();
fHWStencilTestEnabled = kUnknown_TriState;
- fHWGeometryState.fIndexBuffer = NULL;
- fHWGeometryState.fVertexBuffer = NULL;
-
- fHWGeometryState.fArrayPtrsDirty = true;
+ fHWGeometryState.invalidate();
fHWBoundRenderTarget = NULL;
@@ -474,28 +473,6 @@ void GrGpuGL::onResetContext() {
GL_CALL(PixelStorei(GR_GL_PACK_REVERSE_ROW_ORDER, GR_GL_FALSE));
}
- fHWGeometryState.fVertexOffset = ~0U;
-
- // Third party GL code may have left vertex attributes enabled. Some GL
- // implementations (osmesa) may read vetex attributes that are not required
- // by the current shader. Therefore, we have to ensure that only the
- // attributes we require for the current draw are enabled or we may cause an
- // invalid read.
-
- // Disable all vertex layout bits so that next flush will assume all
- // optional vertex attributes are disabled.
- fHWGeometryState.fVertexLayout = 0;
-
- // We always use the this attribute and assume it is always enabled.
- int posAttrIdx = GrGLProgram::PositionAttributeIdx();
- GL_CALL(EnableVertexAttribArray(posAttrIdx));
- // Disable all other vertex attributes.
- for (int va = 0; va < this->glCaps().maxVertexAttributes(); ++va) {
- if (va != posAttrIdx) {
- GL_CALL(DisableVertexAttribArray(va));
- }
- }
-
fHWProgramID = 0;
fSharedGLProgramState.invalidate();
}
@@ -1253,26 +1230,26 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) {
GL_CALL(GenBuffers(1, &id));
if (id) {
GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, id));
- fHWGeometryState.fArrayPtrsDirty = true;
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface());
// make sure driver can allocate memory for this buffer
GL_ALLOC_CALL(this->glInterface(),
BufferData(GR_GL_ARRAY_BUFFER,
size,
NULL, // data ptr
- dynamic ? GR_GL_DYNAMIC_DRAW :
- GR_GL_STATIC_DRAW));
+ dynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW));
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
GL_CALL(DeleteBuffers(1, &id));
// deleting bound buffer does implicit bind to 0
- fHWGeometryState.fVertexBuffer = NULL;
+ fHWGeometryState.setVertexBufferID(0);
return NULL;
}
static const bool kIsWrapped = false;
- GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer,
- (this, kIsWrapped, id,
- size, dynamic));
- fHWGeometryState.fVertexBuffer = vertexBuffer;
+ GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this,
+ false,
+ id,
+ size,
+ dynamic));
+ fHWGeometryState.setVertexBufferID(id);
return vertexBuffer;
}
return NULL;
@@ -1294,13 +1271,13 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) {
GL_CALL(DeleteBuffers(1, &id));
// deleting bound buffer does implicit bind to 0
- fHWGeometryState.fIndexBuffer = NULL;
+ fHWGeometryState.setIndexBufferID(0);
return NULL;
}
static const bool kIsWrapped = false;
GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer,
(this, kIsWrapped, id, size, dynamic));
- fHWGeometryState.fIndexBuffer = indexBuffer;
+ fHWGeometryState.setIndexBufferID(id);
return indexBuffer;
}
return NULL;
@@ -1660,16 +1637,14 @@ GrGLenum gPrimitiveType2GLMode[] = {
#endif
void GrGpuGL::onGpuDraw(const DrawInfo& info) {
- int extraStartIndexOffset;
- this->setupGeometry(info, &extraStartIndexOffset);
+ size_t indexOffsetInBytes;
+ this->setupGeometry(info, &indexOffsetInBytes);
GrAssert((size_t)info.primitiveType() < GR_ARRAY_COUNT(gPrimitiveType2GLMode));
- GrAssert(NULL != fHWGeometryState.fVertexBuffer);
if (info.isIndexed()) {
- GrAssert(NULL != fHWGeometryState.fIndexBuffer);
- GrGLvoid* indices = (GrGLvoid*)(sizeof(uint16_t) * (info.startIndex() +
- extraStartIndexOffset));
+ GrGLvoid* indices =
+ reinterpret_cast<GrGLvoid*>(indexOffsetInBytes + sizeof(uint16_t) * info.startIndex());
// info.startVertex() was accounted for by setupGeometry.
GL_CALL(DrawElements(gPrimitiveType2GLMode[info.primitiveType()],
info.indexCount(),
@@ -2171,29 +2146,19 @@ void GrGpuGL::flushMiscFixedFunctionState() {
}
void GrGpuGL::notifyVertexBufferBind(const GrGLVertexBuffer* buffer) {
- if (fHWGeometryState.fVertexBuffer != buffer) {
- fHWGeometryState.fArrayPtrsDirty = true;
- fHWGeometryState.fVertexBuffer = buffer;
- }
+ fHWGeometryState.setVertexBufferID(buffer->bufferID());
}
void GrGpuGL::notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
- if (fHWGeometryState.fVertexBuffer == buffer) {
- // deleting bound buffer does implied bind to 0
- fHWGeometryState.fVertexBuffer = NULL;
- fHWGeometryState.fArrayPtrsDirty = true;
- }
+ fHWGeometryState.notifyVertexBufferDelete(buffer);
}
void GrGpuGL::notifyIndexBufferBind(const GrGLIndexBuffer* buffer) {
- fHWGeometryState.fIndexBuffer = buffer;
+ fHWGeometryState.setIndexBufferID(buffer->bufferID());
}
void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
- if (fHWGeometryState.fIndexBuffer == buffer) {
- // deleting bound buffer does implied bind to 0
- fHWGeometryState.fIndexBuffer = NULL;
- }
+ fHWGeometryState.notifyIndexBufferDelete(buffer);
}
void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
@@ -2338,52 +2303,48 @@ void GrGpuGL::setSpareTextureUnit() {
}
}
-void GrGpuGL::setBuffers(bool indexed,
- int* extraVertexOffset,
- int* extraIndexOffset) {
+GrGLVertexBuffer* GrGpuGL::setBuffers(bool indexed,
+ size_t* vertexOffsetInBytes,
+ size_t* indexOffsetInBytes) {
- GrAssert(NULL != extraVertexOffset);
+ GrAssert(NULL != vertexOffsetInBytes);
const GeometryPoolState& geoPoolState = this->getGeomPoolState();
GrGLVertexBuffer* vbuf;
switch (this->getGeomSrc().fVertexSrc) {
- case kBuffer_GeometrySrcType:
- *extraVertexOffset = 0;
- vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
- break;
- case kArray_GeometrySrcType:
- case kReserved_GeometrySrcType:
- this->finalizeReservedVertices();
- *extraVertexOffset = geoPoolState.fPoolStartVertex;
- vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
- break;
- default:
- vbuf = NULL; // suppress warning
- GrCrash("Unknown geometry src type!");
+ case kBuffer_GeometrySrcType:
+ *vertexOffsetInBytes = 0;
+ vbuf = (GrGLVertexBuffer*) this->getGeomSrc().fVertexBuffer;
+ break;
+ case kArray_GeometrySrcType:
+ case kReserved_GeometrySrcType:
+ this->finalizeReservedVertices();
+ *vertexOffsetInBytes = geoPoolState.fPoolStartVertex * this->getGeomSrc().fVertexSize;
+ vbuf = (GrGLVertexBuffer*) geoPoolState.fPoolVertexBuffer;
+ break;
+ default:
+ vbuf = NULL; // suppress warning
+ GrCrash("Unknown geometry src type!");
}
GrAssert(NULL != vbuf);
GrAssert(!vbuf->isLocked());
- if (fHWGeometryState.fVertexBuffer != vbuf) {
- GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, vbuf->bufferID()));
- fHWGeometryState.fArrayPtrsDirty = true;
- fHWGeometryState.fVertexBuffer = vbuf;
- }
+ *vertexOffsetInBytes += vbuf->baseOffset();
if (indexed) {
- GrAssert(NULL != extraIndexOffset);
+ GrAssert(NULL != indexOffsetInBytes);
GrGLIndexBuffer* ibuf;
switch (this->getGeomSrc().fIndexSrc) {
case kBuffer_GeometrySrcType:
- *extraIndexOffset = 0;
+ *indexOffsetInBytes = 0;
ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer;
break;
case kArray_GeometrySrcType:
case kReserved_GeometrySrcType:
this->finalizeReservedIndices();
- *extraIndexOffset = geoPoolState.fPoolStartIndex;
+ *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort);
ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer;
break;
default:
@@ -2393,9 +2354,53 @@ void GrGpuGL::setBuffers(bool indexed,
GrAssert(NULL != ibuf);
GrAssert(!ibuf->isLocked());
- if (fHWGeometryState.fIndexBuffer != ibuf) {
- GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, ibuf->bufferID()));
- fHWGeometryState.fIndexBuffer = ibuf;
+ if (!fHWGeometryState.isIndexBufferIDBound(ibuf->bufferID())) {
+ ibuf->bind();
+ fHWGeometryState.setIndexBufferID(ibuf->bufferID());
+ }
+ }
+ return vbuf;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrGpuGL::HWGeometryState::AttribArray::set(const GrGpuGL* gpu,
+ HWGeometryState* geoState,
+ int index,
+ GrGLVertexBuffer* buffer,
+ GrGLint size,
+ GrGLenum type,
+ GrGLboolean normalized,
+ GrGLsizei stride,
+ GrGLvoid* offset) {
+ if (!fEnableIsValid || !fEnabled) {
+ GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index));
+ fEnableIsValid = true;
+ fEnabled = true;
+ }
+ if (!fAttribPointerIsValid ||
+ fVertexBufferID != buffer->bufferID() ||
+ fSize != size ||
+ fNormalized != normalized ||
+ fStride != stride ||
+ offset != fOffset) {
+
+ GrGLuint bufferID = buffer->bufferID();
+ if (!geoState->isVertexBufferIDBound(bufferID)) {
+ buffer->bind();
+ geoState->setVertexBufferID(bufferID);
}
+ GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index,
+ size,
+ type,
+ normalized,
+ stride,
+ offset));
+ fAttribPointerIsValid = true;
+ fVertexBufferID = bufferID;
+ fSize = size;
+ fNormalized = normalized;
+ fStride = stride;
+ fOffset = offset;
}
}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 505c99c374..fae4a93c6c 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -57,6 +57,14 @@ public:
const GrGLCaps& glCaps() const { return fGLContextInfo.caps(); }
+ // Callbacks to update state tracking when related GL objects are bound or deleted
+ void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
+ void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer);
+ void notifyIndexBufferBind(const GrGLIndexBuffer* buffer);
+ void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
+ void notifyTextureDelete(GrGLTexture* texture);
+ void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
+
private:
// GrGpu overrides
virtual void onResetContext() SK_OVERRIDE;
@@ -112,14 +120,16 @@ private:
// binds texture unit in GL
void setTextureUnit(int unitIdx);
- // Sets up vertex attribute pointers and strides. On return startIndexOffset specifies an
- // offset into the index buffer to the first index to be read (in addition to
- // info.startIndex()). It accounts for the fact that index buffer pool may have provided space
- // in the middle of a larger index buffer.
- void setupGeometry(const DrawInfo& info, int* startIndexOffset);
- // binds appropriate vertex and index buffers, also returns any extra verts or indices to
- // offset by based on how space was allocated in pool VB/IBs.
- void setBuffers(bool indexed, int* extraVertexOffset, int* extraIndexOffset);
+ // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
+ // an into the index buffer. It does not account for drawInfo.startIndex() but rather the start
+ // index is relative to the returned offset.
+ void setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes);
+ // binds appropriate vertex and index buffers. It also returns offsets for the vertex and index
+ // buffers. These offsets account for placement within a pool buffer or CPU-side addresses for
+ // use with buffer 0. They do not account for start values in the DrawInfo (which is not passed
+ // here). The vertex buffer that contains the vertex data is returned. It is not necessarily
+ // bound.
+ GrGLVertexBuffer* setBuffers(bool indexed, size_t* vertexOffsetInBytes, size_t* indexOffsetInBytes);
// Subclasses should call this to flush the blend state.
// The params should be the final coefficients to apply
@@ -199,15 +209,6 @@ private:
// determines valid stencil formats
void initStencilFormats();
- // notify callbacks to update state tracking when related
- // objects are bound to GL or deleted outside of the class
- void notifyVertexBufferBind(const GrGLVertexBuffer* buffer);
- void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer);
- void notifyIndexBufferBind(const GrGLIndexBuffer* buffer);
- void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer);
- void notifyTextureDelete(GrGLTexture* texture);
- void notifyRenderTargetDelete(GrRenderTarget* renderTarget);
-
void setSpareTextureUnit();
// bound is region that may be modified and therefore has to be resolved.
@@ -235,11 +236,6 @@ private:
void fillInConfigRenderableTable();
- friend class GrGLVertexBuffer;
- friend class GrGLIndexBuffer;
- friend class GrGLTexture;
- friend class GrGLRenderTarget;
-
GrGLContextInfo fGLContextInfo;
// GL program-related state
@@ -272,12 +268,139 @@ private:
GrGLIRect fHWViewport;
- struct {
- size_t fVertexOffset;
- GrVertexLayout fVertexLayout;
- const GrVertexBuffer* fVertexBuffer;
- const GrIndexBuffer* fIndexBuffer;
- bool fArrayPtrsDirty;
+ /**
+ * Tracks bound vertex and index buffers and vertex attrib array state.
+ */
+ class HWGeometryState {
+ public:
+ HWGeometryState() { fAttribArrayCount = 0; this->invalidate();}
+
+ void setMaxAttribArrays(int max) {
+ fAttribArrayCount = max;
+ fAttribArrays.reset(max);
+ for (int i = 0; i < fAttribArrayCount; ++i) {
+ fAttribArrays[i].invalidate();
+ }
+ }
+
+ void invalidate() {
+ fBoundVertexBufferIDIsValid = false;
+ fBoundIndexBufferIDIsValid = false;
+ for (int i = 0; i < fAttribArrayCount; ++i) {
+ fAttribArrays[i].invalidate();
+ }
+ }
+
+ void notifyVertexBufferDelete(const GrGLVertexBuffer* buffer) {
+ GrGLuint id = buffer->bufferID();
+ if (0 != id) {
+ if (this->isVertexBufferIDBound(id)) {
+ // deleting bound buffer does implied bind to 0
+ this->setVertexBufferID(0);
+ }
+ for (int i = 0; i < fAttribArrayCount; ++i) {
+ if (fAttribArrays[i].vertexBufferID() == id) {
+ fAttribArrays[i].invalidate();
+ }
+ }
+ }
+ }
+
+ void notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
+ GrGLuint id = buffer->bufferID();
+ if (0 != id) {
+ if (this->isIndexBufferIDBound(id)) {
+ // deleting bound buffer does implied bind to 0
+ this->setIndexBufferID(0);
+ }
+ }
+ }
+
+ void setVertexBufferID(GrGLuint id) {
+ fBoundVertexBufferIDIsValid = true;
+ fBoundVertexBufferID = id;
+ }
+
+ void setIndexBufferID(GrGLuint id) {
+ fBoundIndexBufferIDIsValid = true;
+ fBoundIndexBufferID = id;
+ }
+
+ bool isVertexBufferIDBound(GrGLuint id) const {
+ return fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID;
+ }
+
+ bool isIndexBufferIDBound(GrGLuint id) const {
+ return fBoundIndexBufferIDIsValid && id == fBoundIndexBufferID;
+ }
+
+ void setAttribArray(const GrGpuGL* gpu,
+ int index,
+ GrGLVertexBuffer* vertexBuffer,
+ GrGLint size,
+ GrGLenum type,
+ GrGLboolean normalized,
+ GrGLsizei stride,
+ GrGLvoid* offset) {
+ GrAssert(index >= 0 && index < fAttribArrayCount);
+ AttribArray* attrib = fAttribArrays.get() + index;
+ attrib->set(gpu, this, index, vertexBuffer, size, type, normalized, stride, offset);
+ }
+
+ void disableUnusedAttribArrays(const GrGpuGL* gpu,
+ uint32_t usedAttribIndexMask) {
+ for (int i = 0; i < fAttribArrayCount; ++i) {
+ if (!(usedAttribIndexMask & (1 << i))) {
+ fAttribArrays[i].disable(gpu, i);
+ }
+ }
+ }
+
+ private:
+ GrGLuint fBoundVertexBufferID;
+ GrGLuint fBoundIndexBufferID;
+ bool fBoundVertexBufferIDIsValid;
+ bool fBoundIndexBufferIDIsValid;
+
+ struct AttribArray {
+ public:
+ void set(const GrGpuGL* gpu,
+ HWGeometryState* geoState,
+ int index,
+ GrGLVertexBuffer* vertexBuffer,
+ GrGLint size,
+ GrGLenum type,
+ GrGLboolean normalized,
+ GrGLsizei stride,
+ GrGLvoid* offset);
+
+ void disable(const GrGpuGL* gpu, int index) {
+ if (!fEnableIsValid || fEnabled) {
+ GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(index));
+ fEnableIsValid = true;
+ fEnabled = false;
+ }
+ }
+
+ void invalidate() {
+ fEnableIsValid = false;
+ fAttribPointerIsValid = false;
+ }
+
+ GrGLuint vertexBufferID() const { return fVertexBufferID; }
+ private:
+ bool fEnableIsValid;
+ bool fAttribPointerIsValid;
+ bool fEnabled;
+ GrGLuint fVertexBufferID;
+ GrGLint fSize;
+ GrGLenum fType;
+ GrGLboolean fNormalized;
+ GrGLsizei fStride;
+ GrGLvoid* fOffset;
+ };
+ SkAutoTArray<AttribArray> fAttribArrays;
+ int fAttribArrayCount;
} fHWGeometryState;
struct {
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 84e3b6dbfd..87b0893bbe 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -213,103 +213,85 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
return true;
}
-void GrGpuGL::setupGeometry(const DrawInfo& info, int* startIndexOffset) {
+void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
- int newColorOffset;
- int newCoverageOffset;
- int newTexCoordOffset;
- int newEdgeOffset;
+ int colorOffset;
+ int coverageOffset;
+ int texCoordOffset;
+ int edgeOffset;
GrVertexLayout currLayout = this->getDrawState().getVertexLayout();
- GrGLsizei newStride = GrDrawState::VertexSizeAndOffsets(currLayout,
- &newTexCoordOffset,
- &newColorOffset,
- &newCoverageOffset,
- &newEdgeOffset);
- int oldColorOffset;
- int oldCoverageOffset;
- int oldTexCoordOffset;
- int oldEdgeOffset;
-
- GrGLsizei oldStride = GrDrawState::VertexSizeAndOffsets(fHWGeometryState.fVertexLayout,
- &oldTexCoordOffset,
- &oldColorOffset,
- &oldCoverageOffset,
- &oldEdgeOffset);
-
- int extraVertexOffset;
- this->setBuffers(info.isIndexed(), &extraVertexOffset, startIndexOffset);
-
- size_t vertexOffset = (info.startVertex() + extraVertexOffset) * newStride;
-
- // all the Pointers must be set if any of these are true
- bool allOffsetsChange = fHWGeometryState.fArrayPtrsDirty ||
- vertexOffset != fHWGeometryState.fVertexOffset ||
- newStride != oldStride;
-
- if (allOffsetsChange) {
- int idx = GrGLProgram::PositionAttributeIdx();
- GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, (GrGLvoid*)vertexOffset));
- fHWGeometryState.fVertexOffset = vertexOffset;
+ GrGLsizei stride = GrDrawState::VertexSizeAndOffsets(currLayout,
+ &texCoordOffset,
+ &colorOffset,
+ &coverageOffset,
+ &edgeOffset);
+
+ size_t vertexOffset;
+ GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes);
+ vertexOffset += stride * info.startVertex();
+
+ uint32_t usedAttribArraysMask = (1 << GrGLProgram::kPositionAttributeIndex);
+ fHWGeometryState.setAttribArray(this,
+ GrGLProgram::kPositionAttributeIndex,
+ vb,
+ 2,
+ GR_GL_FLOAT,
+ false,
+ stride,
+ reinterpret_cast<GrGLvoid*>(vertexOffset));
+ if (texCoordOffset > 0) {
+ usedAttribArraysMask |= (1 << GrGLProgram::kTexCoordAttributeIndex);
+ GrGLvoid* texCoordPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + texCoordOffset);
+ fHWGeometryState.setAttribArray(this,
+ GrGLProgram::kTexCoordAttributeIndex,
+ vb,
+ 2,
+ GR_GL_FLOAT,
+ false,
+ stride,
+ texCoordPtr);
}
- if (newTexCoordOffset > 0) {
- GrGLvoid* texCoordOffset = (GrGLvoid*)(vertexOffset + newTexCoordOffset);
- int idx = GrGLProgram::TexCoordAttributeIdx();
- if (oldTexCoordOffset <= 0) {
- GL_CALL(EnableVertexAttribArray(idx));
- GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
- } else if (allOffsetsChange || newTexCoordOffset != oldTexCoordOffset) {
- GL_CALL(VertexAttribPointer(idx, 2, GR_GL_FLOAT, false, newStride, texCoordOffset));
- }
- } else if (oldTexCoordOffset > 0) {
- GL_CALL(DisableVertexAttribArray(GrGLProgram::TexCoordAttributeIdx()));
- }
-
- if (newColorOffset > 0) {
- fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL;
- GrGLvoid* colorOffset = (int8_t*)(vertexOffset + newColorOffset);
- int idx = GrGLProgram::ColorAttributeIdx();
- if (oldColorOffset <= 0) {
- GL_CALL(EnableVertexAttribArray(idx));
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset));
- } else if (allOffsetsChange || newColorOffset != oldColorOffset) {
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE, true, newStride, colorOffset));
- }
- } else if (oldColorOffset > 0) {
- GL_CALL(DisableVertexAttribArray(GrGLProgram::ColorAttributeIdx()));
+ if (colorOffset > 0) {
+ usedAttribArraysMask |= (1 << GrGLProgram::kColorAttributeIndex);
+ GrGLvoid* colorPtr = reinterpret_cast<GrGLvoid*>(vertexOffset + colorOffset);
+ fHWGeometryState.setAttribArray(this,
+ GrGLProgram::kColorAttributeIndex,
+ vb,
+ 4,
+ GR_GL_UNSIGNED_BYTE,
+ true,
+ stride,
+ colorPtr);
}
- if (newCoverageOffset > 0) {
- fSharedGLProgramState.fConstAttribColor = GrColor_ILLEGAL;
- GrGLvoid* coverageOffset = (int8_t*)(vertexOffset + newCoverageOffset);
- int idx = GrGLProgram::CoverageAttributeIdx();
- if (oldCoverageOffset <= 0) {
- GL_CALL(EnableVertexAttribArray(idx));
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
- true, newStride, coverageOffset));
- } else if (allOffsetsChange || newCoverageOffset != oldCoverageOffset) {
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_UNSIGNED_BYTE,
- true, newStride, coverageOffset));
- }
- } else if (oldCoverageOffset > 0) {
- GL_CALL(DisableVertexAttribArray(GrGLProgram::CoverageAttributeIdx()));
+ if (coverageOffset > 0) {
+ usedAttribArraysMask |= (1 << GrGLProgram::kCoverageAttributeIndex);
+ GrGLvoid* coveragePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + coverageOffset);
+ fHWGeometryState.setAttribArray(this,
+ GrGLProgram::kCoverageAttributeIndex,
+ vb,
+ 4,
+ GR_GL_UNSIGNED_BYTE,
+ true,
+ stride,
+ coveragePtr);
}
- if (newEdgeOffset > 0) {
- GrGLvoid* edgeOffset = (int8_t*)(vertexOffset + newEdgeOffset);
- int idx = GrGLProgram::EdgeAttributeIdx();
- if (oldEdgeOffset <= 0) {
- GL_CALL(EnableVertexAttribArray(idx));
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset));
- } else if (allOffsetsChange || newEdgeOffset != oldEdgeOffset) {
- GL_CALL(VertexAttribPointer(idx, 4, GR_GL_FLOAT, false, newStride, edgeOffset));
- }
- } else if (oldEdgeOffset > 0) {
- GL_CALL(DisableVertexAttribArray(GrGLProgram::EdgeAttributeIdx()));
+ if (edgeOffset > 0) {
+ usedAttribArraysMask |= (1 << GrGLProgram::kEdgeAttributeIndex);
+ GrGLvoid* edgePtr = reinterpret_cast<GrGLvoid*>(vertexOffset + edgeOffset);
+ fHWGeometryState.setAttribArray(this,
+ GrGLProgram::kEdgeAttributeIndex,
+ vb,
+ 4,
+ GR_GL_FLOAT,
+ false,
+ stride,
+ edgePtr);
}
- fHWGeometryState.fVertexLayout = currLayout;
- fHWGeometryState.fArrayPtrsDirty = false;
+ fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask);
}