diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-19 20:17:28 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-02-19 20:17:28 +0000 |
commit | 880b8fcf255e67a15687e8b7cc47397372db683c (patch) | |
tree | 116b5f1ccedc6a9187435eb471061436e67cdf1a /src/gpu/gl | |
parent | a62a9ce9e65071797e971c36a5b02d8931d32732 (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/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLIndexBuffer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLIndexBuffer.h | 19 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 14 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 12 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexBuffer.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexBuffer.h | 21 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 173 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 179 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 156 |
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); } |