Chromium Code Reviews| Index: src/gpu/gl/GrGpuGL.h |
| =================================================================== |
| --- src/gpu/gl/GrGpuGL.h (revision 8015) |
| +++ src/gpu/gl/GrGpuGL.h (working copy) |
| @@ -20,6 +20,7 @@ |
| #include "GrGLProgram.h" |
| #include "GrGLStencilBuffer.h" |
| #include "GrGLTexture.h" |
| +#include "GrGLVertexArray.h" |
| #include "GrGLVertexBuffer.h" |
| #include "../GrTHashCache.h" |
| @@ -54,11 +55,29 @@ |
| const GrGLCaps& glCaps() const { return fGLContext.info().caps(); } |
| - // Callbacks to update state tracking when related GL objects are bound or deleted |
| - void notifyVertexBufferBind(GrGLuint id); |
| - void notifyVertexBufferDelete(GrGLuint id); |
| - void notifyIndexBufferBind(GrGLuint id); |
| - void notifyIndexBufferDelete(GrGLuint id); |
| + // These functions should be used to bind GL objects. They track the GL state and skip redundant |
| + // bindings. Making the equivalent glBind calls directly will confuse the state tracking. |
| + void bindVertexArray(GrGLuint id) { |
| + fHWGeometryState.setVertexArrayID(this, id); |
| + } |
| + void bindIndexBufferAndDefaultVertexArray(GrGLuint id) { |
| + fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, id); |
| + } |
| + void bindVertexBuffer(GrGLuint id) { |
| + fHWGeometryState.setVertexBufferID(this, id); |
| + } |
| + |
| + // These callbacks update state tracking when GL objects are deleted. They are called from |
| + // GrGLResource onRelease functions. |
| + void notifyVertexBufferDelete(GrGLuint id) { |
| + fHWGeometryState.notifyVertexBufferDelete(id); |
| + } |
| + void notifyIndexBufferDelete(GrGLuint id) { |
| + fHWGeometryState.notifyIndexBufferDelete(id); |
| + } |
| + void notifyVertexArrayDelete(GrGLuint id) { |
|
jvanverth1
2013/03/07 16:17:44
Match the order of the notify*Delete methods with
bsalomon
2013/03/07 16:25:07
will do before landing.
|
| + fHWGeometryState.notifyVertexArrayDelete(id); |
| + } |
| void notifyTextureDelete(GrGLTexture* texture); |
| void notifyRenderTargetDelete(GrRenderTarget* renderTarget); |
| @@ -121,12 +140,6 @@ |
| // 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 |
| @@ -268,134 +281,104 @@ |
| */ |
| class HWGeometryState { |
| public: |
| - HWGeometryState() { fAttribArrayCount = 0; this->invalidate();} |
| + HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); } |
| + |
| + ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); } |
| - void setMaxAttribArrays(int max) { |
| - fAttribArrayCount = max; |
| - fAttribArrays.reset(max); |
| - for (int i = 0; i < fAttribArrayCount; ++i) { |
| - fAttribArrays[i].invalidate(); |
| + void invalidate() { |
| + fBoundVertexArrayIDIsValid = false; |
| + fBoundVertexBufferIDIsValid = false; |
| + fDefaultVertexArrayBoundIndexBufferID = false; |
| + fDefaultVertexArrayBoundIndexBufferIDIsValid = false; |
| + fDefaultVertexArrayAttribState.invalidate(); |
| + } |
| + |
| + void notifyVertexArrayDelete(GrGLuint id) { |
| + if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) { |
| + // Does implicit bind to 0 |
| + fBoundVertexArrayID = 0; |
| } |
| } |
| - void invalidate() { |
| - fBoundVertexBufferIDIsValid = false; |
| - fBoundIndexBufferIDIsValid = false; |
| - for (int i = 0; i < fAttribArrayCount; ++i) { |
| - fAttribArrays[i].invalidate(); |
| + void setVertexArrayID(GrGpuGL* gpu, GrGLuint arrayID) { |
| + if (!gpu->glCaps().vertexArrayObjectSupport()) { |
| + GrAssert(0 == arrayID); |
| + return; |
| } |
| + if (!fBoundVertexArrayIDIsValid || arrayID != fBoundVertexArrayID) { |
| + GR_GL_CALL(gpu->glInterface(), BindVertexArray(arrayID)); |
| + fBoundVertexArrayIDIsValid = true; |
| + fBoundVertexArrayID = arrayID; |
| + } |
| } |
| void notifyVertexBufferDelete(GrGLuint id) { |
| - 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].isVertexBufferIDBound(id)) { |
| - fAttribArrays[i].invalidate(); |
| - } |
| - } |
| + if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) { |
| + fBoundVertexBufferID = 0; |
| } |
| + if (NULL != fVBOVertexArray) { |
| + fVBOVertexArray->notifyVertexBufferDelete(id); |
| + } |
| + fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id); |
| } |
| void notifyIndexBufferDelete(GrGLuint id) { |
| - if (0 != id) { |
| - if (this->isIndexBufferIDBound(id)) { |
| - // deleting bound buffer does implied bind to 0 |
| - this->setIndexBufferID(0); |
| - } |
| + if (fDefaultVertexArrayBoundIndexBufferIDIsValid && |
| + id == fDefaultVertexArrayBoundIndexBufferID) { |
| + fDefaultVertexArrayBoundIndexBufferID = 0; |
| } |
| + if (NULL != fVBOVertexArray) { |
| + fVBOVertexArray->notifyIndexBufferDelete(id); |
| + } |
| } |
| - void setVertexBufferID(GrGLuint id) { |
| - fBoundVertexBufferIDIsValid = true; |
| - fBoundVertexBufferID = id; |
| + void setVertexBufferID(GrGpuGL* gpu, GrGLuint id) { |
| + if (!fBoundVertexBufferIDIsValid || id != fBoundVertexBufferID) { |
| + GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ARRAY_BUFFER, 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); |
| - } |
| + /** |
| + * Binds the default vertex array and binds the index buffer. This is used when binding |
| + * an index buffer in order to update it. |
| + */ |
| + void setIndexBufferIDOnDefaultVertexArray(GrGpuGL* gpu, GrGLuint id) { |
| + this->setVertexArrayID(gpu, 0); |
| + if (!fDefaultVertexArrayBoundIndexBufferIDIsValid || |
| + id != fDefaultVertexArrayBoundIndexBufferID) { |
| + GR_GL_CALL(gpu->glInterface(), BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, id)); |
| + fDefaultVertexArrayBoundIndexBufferIDIsValid = true; |
| + fDefaultVertexArrayBoundIndexBufferID = id; |
| } |
| } |
| + /** |
| + * Binds the vertex array object that should be used to render from the vertex buffer. |
| + * The vertex array is bound and its attrib array state object is returned. The vertex |
| + * buffer is bound. The index buffer (if non-NULL) is bound to the vertex array. The |
| + * returned GrGLAttribArrayState should be used to set vertex attribute arrays. |
| + */ |
| + GrGLAttribArrayState* bindArrayAndBuffersToDraw(GrGpuGL* gpu, |
| + const GrGLVertexBuffer* vbuffer, |
| + const GrGLIndexBuffer* ibuffer); |
| + |
| private: |
| + GrGLuint fBoundVertexArrayID; |
| GrGLuint fBoundVertexBufferID; |
| - GrGLuint fBoundIndexBufferID; |
| + bool fBoundVertexArrayIDIsValid; |
| 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); |
| + GrGLuint fDefaultVertexArrayBoundIndexBufferID; |
| + bool fDefaultVertexArrayBoundIndexBufferIDIsValid; |
| + // We return a non-const pointer to this from bindArrayAndBuffersToDraw when vertex array 0 |
| + // is bound. However, this class is internal to GrGpuGL and this object never leaks out of |
| + // GrGpuGL. |
| + GrGLAttribArrayState fDefaultVertexArrayAttribState; |
| - 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; |
| - } |
| - |
| - bool isVertexBufferIDBound(GrGLuint id) const { |
| - return fAttribPointerIsValid && id == 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; |
| + // This is used when we're using a core profile and the vertices are in a VBO. |
| + GrGLVertexArray* fVBOVertexArray; |
| } fHWGeometryState; |
| struct { |