diff options
-rw-r--r-- | gyp/gpu.gypi | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLBufferImpl.cpp | 5 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexArray.cpp | 123 | ||||
-rw-r--r-- | src/gpu/gl/GrGLVertexArray.h | 147 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 154 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 211 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 77 | ||||
-rw-r--r-- | src/gpu/gl/debug/GrGLCreateDebugInterface.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/mac/SkNativeGLContext_mac.cpp | 3 | ||||
-rw-r--r-- | src/gpu/gl/win/SkNativeGLContext_win.cpp | 2 |
11 files changed, 472 insertions, 258 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi index a2644b7b75..41f0f09ee2 100644 --- a/gyp/gpu.gypi +++ b/gyp/gpu.gypi @@ -175,6 +175,8 @@ '<(skia_src_path)/gpu/gl/GrGLUniformManager.cpp', '<(skia_src_path)/gpu/gl/GrGLUniformManager.h', '<(skia_src_path)/gpu/gl/GrGLUniformHandle.h', + '<(skia_src_path)/gpu/gl/GrGLVertexArray.cpp', + '<(skia_src_path)/gpu/gl/GrGLVertexArray.h', '<(skia_src_path)/gpu/gl/GrGLVertexBuffer.cpp', '<(skia_src_path)/gpu/gl/GrGLVertexBuffer.h', '<(skia_src_path)/gpu/gl/GrGpuGL.cpp', diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp index d9a8a8eca8..04c90725ae 100644 --- a/src/gpu/gl/GrGLBufferImpl.cpp +++ b/src/gpu/gl/GrGLBufferImpl.cpp @@ -57,12 +57,11 @@ void GrGLBufferImpl::abandon() { void GrGLBufferImpl::bind(GrGpuGL* gpu) const { VALIDATE(); - GL_CALL(gpu, BindBuffer(fBufferType, fDesc.fID)); if (GR_GL_ARRAY_BUFFER == fBufferType) { - gpu->notifyVertexBufferBind(fDesc.fID); + gpu->bindVertexBuffer(fDesc.fID); } else { GrAssert(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); - gpu->notifyIndexBufferBind(fDesc.fID); + gpu->bindIndexBufferAndDefaultVertexArray(fDesc.fID); } } diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 08ef28e02a..02d6d383b7 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -308,7 +308,9 @@ const char* GrGLShaderBuilder::fragmentPosition() { #if 1 if (fCtxInfo.caps().fragCoordConventionsSupport()) { if (!fSetupFragPosition) { - fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n"); + if (fCtxInfo.glslGeneration() < k150_GrGLSLGeneration) { + fFSHeader.append("#extension GL_ARB_fragment_coord_conventions: require\n"); + } fFSInputs.push_back().set(kVec4f_GrSLType, GrGLShaderVar::kIn_TypeModifier, "gl_FragCoord", diff --git a/src/gpu/gl/GrGLVertexArray.cpp b/src/gpu/gl/GrGLVertexArray.cpp new file mode 100644 index 0000000000..ded4a9a5d2 --- /dev/null +++ b/src/gpu/gl/GrGLVertexArray.cpp @@ -0,0 +1,123 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrGLVertexArray.h" +#include "GrGpuGL.h" + +#define GPUGL static_cast<GrGpuGL*>(this->getGpu()) +#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X); + +void GrGLAttribArrayState::set(const GrGpuGL* gpu, + int index, + GrGLVertexBuffer* buffer, + GrGLint size, + GrGLenum type, + GrGLboolean normalized, + GrGLsizei stride, + GrGLvoid* offset) { + GrAssert(index >= 0 && index < fAttribArrayStates.count()); + AttribArrayState* array = &fAttribArrayStates[index]; + if (!array->fEnableIsValid || !array->fEnabled) { + GR_GL_CALL(gpu->glInterface(), EnableVertexAttribArray(index)); + array->fEnableIsValid = true; + array->fEnabled = true; + } + if (!array->fAttribPointerIsValid || + array->fVertexBufferID != buffer->bufferID() || + array->fSize != size || + array->fNormalized != normalized || + array->fStride != stride || + array->fOffset != offset) { + + buffer->bind(); + GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, + size, + type, + normalized, + stride, + offset)); + array->fAttribPointerIsValid = true; + array->fVertexBufferID = buffer->bufferID(); + array->fSize = size; + array->fNormalized = normalized; + array->fStride = stride; + array->fOffset = offset; + } +} + +void GrGLAttribArrayState::disableUnusedAttribArrays(const GrGpuGL* gpu, uint64_t usedMask) { + int count = fAttribArrayStates.count(); + for (int i = 0; i < count; ++i) { + if (!(usedMask & 0x1)) { + if (!fAttribArrayStates[i].fEnableIsValid || fAttribArrayStates[i].fEnabled) { + GR_GL_CALL(gpu->glInterface(), DisableVertexAttribArray(i)); + fAttribArrayStates[i].fEnableIsValid = true; + fAttribArrayStates[i].fEnabled = false; + } + } + // if the count is greater than 64 then this will become 0 and we will disable arrays 64+. + usedMask >>= 1; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +GrGLVertexArray::GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount) + : GrResource(gpu, false) + , fID(id) + , fAttribArrays(attribCount) + , fIndexBufferIDIsValid(false) { +} + +void GrGLVertexArray::onAbandon() { + fID = 0; + INHERITED::onAbandon(); +} + +void GrGLVertexArray::onRelease() { + if (0 != fID) { + GL_CALL(DeleteVertexArrays(1, &fID)); + GPUGL->notifyVertexArrayDelete(fID); + fID = 0; + } + INHERITED::onRelease(); +} + +GrGLAttribArrayState* GrGLVertexArray::bind() { + if (0 == fID) { + return NULL; + } + GPUGL->bindVertexArray(fID); + return &fAttribArrays; +} + +GrGLAttribArrayState* GrGLVertexArray::bindWithIndexBuffer(const GrGLIndexBuffer* buffer) { + GrGLAttribArrayState* state = this->bind(); + if (NULL != state && NULL != buffer) { + GrGLuint bufferID = buffer->bufferID(); + if (!fIndexBufferIDIsValid || bufferID != fIndexBufferID) { + GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, bufferID)); + fIndexBufferIDIsValid = true; + fIndexBufferID = bufferID; + } + } + return state; +} + +void GrGLVertexArray::notifyIndexBufferDelete(GrGLuint bufferID) { + if (fIndexBufferIDIsValid && bufferID == fIndexBufferID) { + fIndexBufferID = 0; + } + } + +void GrGLVertexArray::invalidateCachedState() { + int count = fAttribArrays.count(); + for (int i = 0; i < count; ++i) { + fAttribArrays.invalidate(); + } + fIndexBufferIDIsValid = false; +} diff --git a/src/gpu/gl/GrGLVertexArray.h b/src/gpu/gl/GrGLVertexArray.h new file mode 100644 index 0000000000..b68e71dbe8 --- /dev/null +++ b/src/gpu/gl/GrGLVertexArray.h @@ -0,0 +1,147 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrGLVertexArray_DEFINED +#define GrGLVertexArray_DEFINED + +#include "GrResource.h" +#include "gl/GrGLFunctions.h" + +#include "SkTArray.h" + +class GrGLVertexBuffer; +class GrGLIndexBuffer; +class GrGpuGL; + +/** + * This sets and tracks the vertex attribute array state. It is used internally by GrGLVertexArray + * (below) but is separate because it is also used to track the state of vertex array object 0. + */ +class GrGLAttribArrayState { +public: + explicit GrGLAttribArrayState(int arrayCount = 0) { this->resize(arrayCount); } + + void resize(int newCount) { + fAttribArrayStates.resize_back(newCount); + for (int i = 0; i < newCount; ++i) { + fAttribArrayStates[i].invalidate(); + } + } + + /** + * This function enables and sets vertex attrib state for the specified attrib index. It is + * assumed that the GrGLAttribArrayState is tracking the state of the currently bound vertex + * array object. + */ + void set(const GrGpuGL*, + int index, + GrGLVertexBuffer*, + GrGLint size, + GrGLenum type, + GrGLboolean normalized, + GrGLsizei stride, + GrGLvoid* offset); + + /** + * This function disables vertex attribs not present in the mask. It is assumed that the + * GrGLAttribArrayState is tracking the state of the currently bound vertex array object. + */ + void disableUnusedAttribArrays(const GrGpuGL*, uint64_t usedAttribArrayMask); + + void invalidate() { + int count = fAttribArrayStates.count(); + for (int i = 0; i < count; ++i) { + fAttribArrayStates[i].invalidate(); + } + } + + void notifyVertexBufferDelete(GrGLuint id) { + int count = fAttribArrayStates.count(); + for (int i = 0; i < count; ++i) { + if (id == fAttribArrayStates[i].fVertexBufferID) { + fAttribArrayStates[i].invalidate(); + } + } + } + + /** + * The number of attrib arrays that this object is configured to track. + */ + int count() const { return fAttribArrayStates.count(); } + +private: + /** + * Tracks the state of glVertexAttribArray for an attribute index. + */ + struct AttribArrayState { + void invalidate() { + fEnableIsValid = false; + fAttribPointerIsValid = false; + } + + bool fEnableIsValid; + bool fAttribPointerIsValid; + bool fEnabled; + GrGLuint fVertexBufferID; + GrGLint fSize; + GrGLenum fType; + GrGLboolean fNormalized; + GrGLsizei fStride; + GrGLvoid* fOffset; + }; + + SkSTArray<16, AttribArrayState, true> fAttribArrayStates; +}; + +/** + * This class represents an OpenGL vertex array object. It manages the lifetime of the vertex array + * and is used to track the state of the vertex array to avoid redundant GL calls. + */ +class GrGLVertexArray : public GrResource { +public: + GrGLVertexArray(GrGpuGL* gpu, GrGLint id, int attribCount); + + /** + * Binds this vertex array. If the ID has been deleted or abandoned then NULL is returned. + * Otherwise, the GrGLAttribArrayState that is tracking this vertex array's attrib bindings is + * returned. + */ + GrGLAttribArrayState* bind(); + + /** + * This is a version of the above function that also binds an index buffer to the vertex + * array object. + */ + GrGLAttribArrayState* bindWithIndexBuffer(const GrGLIndexBuffer* indexBuffer); + + void notifyIndexBufferDelete(GrGLuint bufferID); + + void notifyVertexBufferDelete(GrGLuint id) { + fAttribArrays.notifyVertexBufferDelete(id); + } + + GrGLuint arrayID() const { return fID; } + + void invalidateCachedState(); + + virtual size_t sizeInBytes() const SK_OVERRIDE { return 0; } + +protected: + virtual void onAbandon() SK_OVERRIDE; + + virtual void onRelease() SK_OVERRIDE; + +private: + GrGLuint fID; + GrGLAttribArrayState fAttribArrays; + GrGLuint fIndexBufferID; + bool fIndexBufferIDIsValid; + + typedef GrResource INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index 42e83b0435..343cae39f0 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -180,8 +180,6 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context) fProgramCache = SkNEW_ARGS(ProgramCache, (this->glContext())); - fHWGeometryState.setMaxAttribArrays(this->glCaps().maxVertexAttributes()); - GrAssert(this->glCaps().maxVertexAttributes() >= GrDrawState::kVertexAttribCnt); GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kColorOverrideAttribIndexValue); GrAssert(this->glCaps().maxVertexAttributes() > GrDrawState::kCoverageOverrideAttribIndexValue); @@ -423,6 +421,8 @@ void GrGpuGL::onResetContext() { GL_CALL(Disable(GR_GL_INDEX_LOGIC_OP)); } if (this->glCaps().imagingSupport()) { + // This produces a GL error on the windows NVIDIA driver when using a core profile but + // I think that is a driver bug since GL_ARB_imaging is in the extension string. GL_CALL(Disable(GR_GL_COLOR_TABLE)); } GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL)); @@ -1246,8 +1246,7 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { } else { GL_CALL(GenBuffers(1, &desc.fID)); if (desc.fID) { - GL_CALL(BindBuffer(GR_GL_ARRAY_BUFFER, desc.fID)); - fHWGeometryState.setVertexBufferID(desc.fID); + fHWGeometryState.setVertexBufferID(this, desc.fID); CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); // make sure driver can allocate memory for this buffer GL_ALLOC_CALL(this->glInterface(), @@ -1257,8 +1256,7 @@ GrVertexBuffer* GrGpuGL::onCreateVertexBuffer(uint32_t size, bool dynamic) { desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { GL_CALL(DeleteBuffers(1, &desc.fID)); - // deleting bound buffer does implicit bind to 0 - fHWGeometryState.setVertexBufferID(0); + this->notifyVertexBufferDelete(desc.fID); return NULL; } GrGLVertexBuffer* vertexBuffer = SkNEW_ARGS(GrGLVertexBuffer, (this, desc)); @@ -1281,8 +1279,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { } else { GL_CALL(GenBuffers(1, &desc.fID)); if (desc.fID) { - GL_CALL(BindBuffer(GR_GL_ELEMENT_ARRAY_BUFFER, desc.fID)); - fHWGeometryState.setIndexBufferID(desc.fID); + fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID); CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); // make sure driver can allocate memory for this buffer GL_ALLOC_CALL(this->glInterface(), @@ -1292,8 +1289,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_STATIC_DRAW)); if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { GL_CALL(DeleteBuffers(1, &desc.fID)); - // deleting bound buffer does implicit bind to 0 - fHWGeometryState.setIndexBufferID(0); + this->notifyIndexBufferDelete(desc.fID); return NULL; } GrIndexBuffer* indexBuffer = SkNEW_ARGS(GrGLIndexBuffer, (this, desc)); @@ -2165,22 +2161,6 @@ void GrGpuGL::flushMiscFixedFunctionState() { } } -void GrGpuGL::notifyVertexBufferBind(GrGLuint id) { - fHWGeometryState.setVertexBufferID(id); -} - -void GrGpuGL::notifyVertexBufferDelete(GrGLuint id) { - fHWGeometryState.notifyVertexBufferDelete(id); -} - -void GrGpuGL::notifyIndexBufferBind(GrGLuint id) { - fHWGeometryState.setIndexBufferID(id); -} - -void GrGpuGL::notifyIndexBufferDelete(GrGLuint id) { - fHWGeometryState.notifyIndexBufferDelete(id); -} - void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { GrAssert(NULL != renderTarget); if (fHWBoundRenderTarget == renderTarget) { @@ -2323,105 +2303,35 @@ void GrGpuGL::setSpareTextureUnit() { } } -GrGLVertexBuffer* GrGpuGL::setBuffers(bool indexed, - size_t* vertexOffsetInBytes, - size_t* indexOffsetInBytes) { - - GrAssert(NULL != vertexOffsetInBytes); - - const GeometryPoolState& geoPoolState = this->getGeomPoolState(); - - GrGLVertexBuffer* vbuf; - switch (this->getGeomSrc().fVertexSrc) { - 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()); - *vertexOffsetInBytes += vbuf->baseOffset(); - - if (indexed) { - GrAssert(NULL != indexOffsetInBytes); +/////////////////////////////////////////////////////////////////////////////// - GrGLIndexBuffer* ibuf; - switch (this->getGeomSrc().fIndexSrc) { - case kBuffer_GeometrySrcType: - *indexOffsetInBytes = 0; - ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; - break; - case kArray_GeometrySrcType: - case kReserved_GeometrySrcType: - this->finalizeReservedIndices(); - *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); - ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; - break; - default: - ibuf = NULL; // suppress warning - GrCrash("Unknown geometry src type!"); +GrGLAttribArrayState* GrGpuGL::HWGeometryState::bindArrayAndBuffersToDraw( + GrGpuGL* gpu, + const GrGLVertexBuffer* vbuffer, + const GrGLIndexBuffer* ibuffer) { + GrAssert(NULL != vbuffer); + GrGLAttribArrayState* attribState = &fDefaultVertexArrayAttribState; + // We use a vertex array if we're on a core profile and the verts are in a VBO. + if (gpu->glCaps().isCoreProfile() && !vbuffer->isCPUBacked()) { + if (NULL == fVBOVertexArray || !fVBOVertexArray->isValid()) { + SkSafeUnref(fVBOVertexArray); + GrGLuint arrayID; + GR_GL_CALL(gpu->glInterface(), GenVertexArrays(1, &arrayID)); + int attrCount = gpu->glCaps().maxVertexAttributes(); + fVBOVertexArray = SkNEW_ARGS(GrGLVertexArray, (gpu, arrayID, attrCount)); } - - GrAssert(NULL != ibuf); - GrAssert(!ibuf->isLocked()); - *indexOffsetInBytes += ibuf->baseOffset(); - if (!fHWGeometryState.isIndexBufferIDBound(ibuf->bufferID())) { - ibuf->bind(); - fHWGeometryState.setIndexBufferID(ibuf->bufferID()); + attribState = fVBOVertexArray->bindWithIndexBuffer(ibuffer); + } else { + if (NULL != ibuffer) { + this->setIndexBufferIDOnDefaultVertexArray(gpu, ibuffer->bufferID()); + } else { + this->setVertexArrayID(gpu, 0); } - } - 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); + int attrCount = gpu->glCaps().maxVertexAttributes(); + if (fDefaultVertexArrayAttribState.count() != attrCount) { + fDefaultVertexArrayAttribState.resize(attrCount); } - GR_GL_CALL(gpu->glInterface(), VertexAttribPointer(index, - size, - type, - normalized, - stride, - offset)); - fAttribPointerIsValid = true; - fVertexBufferID = bufferID; - fSize = size; - fNormalized = normalized; - fStride = stride; - fOffset = offset; + attribState = &fDefaultVertexArrayAttribState; } + return attribState; } diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index a0194151c7..e4c7197690 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -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 @@ public: 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 notifyVertexArrayDelete(GrGLuint id) { + fHWGeometryState.notifyVertexArrayDelete(id); + } + void notifyVertexBufferDelete(GrGLuint id) { + fHWGeometryState.notifyVertexBufferDelete(id); + } + void notifyIndexBufferDelete(GrGLuint id) { + fHWGeometryState.notifyIndexBufferDelete(id); + } void notifyTextureDelete(GrGLTexture* texture); void notifyRenderTargetDelete(GrRenderTarget* renderTarget); @@ -121,12 +140,6 @@ private: // 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 @@ private: */ 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(); - } - } + HWGeometryState() { fVBOVertexArray = NULL; this->invalidate(); } + + ~HWGeometryState() { SkSafeUnref(fVBOVertexArray); } void invalidate() { + fBoundVertexArrayIDIsValid = false; fBoundVertexBufferIDIsValid = false; - fBoundIndexBufferIDIsValid = false; - for (int i = 0; i < fAttribArrayCount; ++i) { - fAttribArrays[i].invalidate(); - } + fDefaultVertexArrayBoundIndexBufferID = false; + fDefaultVertexArrayBoundIndexBufferIDIsValid = false; + fDefaultVertexArrayAttribState.invalidate(); } - 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(); - } - } + void notifyVertexArrayDelete(GrGLuint id) { + if (fBoundVertexArrayIDIsValid && fBoundVertexArrayID == id) { + // Does implicit bind to 0 + fBoundVertexArrayID = 0; } } - void notifyIndexBufferDelete(GrGLuint id) { - if (0 != id) { - if (this->isIndexBufferIDBound(id)) { - // deleting bound buffer does implied bind to 0 - this->setIndexBufferID(0); - } + 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 setVertexBufferID(GrGLuint id) { - fBoundVertexBufferIDIsValid = true; - fBoundVertexBufferID = id; - } - - void setIndexBufferID(GrGLuint id) { - fBoundIndexBufferIDIsValid = true; - fBoundIndexBufferID = id; - } - - bool isVertexBufferIDBound(GrGLuint id) const { - return fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID; + void notifyVertexBufferDelete(GrGLuint id) { + if (fBoundVertexBufferIDIsValid && id == fBoundVertexBufferID) { + fBoundVertexBufferID = 0; + } + if (NULL != fVBOVertexArray) { + fVBOVertexArray->notifyVertexBufferDelete(id); + } + fDefaultVertexArrayAttribState.notifyVertexBufferDelete(id); } - bool isIndexBufferIDBound(GrGLuint id) const { - return fBoundIndexBufferIDIsValid && id == fBoundIndexBufferID; + void notifyIndexBufferDelete(GrGLuint id) { + if (fDefaultVertexArrayBoundIndexBufferIDIsValid && + id == fDefaultVertexArrayBoundIndexBufferID) { + fDefaultVertexArrayBoundIndexBufferID = 0; + } + if (NULL != fVBOVertexArray) { + fVBOVertexArray->notifyIndexBufferDelete(id); + } } - 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 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 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); - - 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 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; - 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 { diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index c65f0b6957..c087073ff7 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -217,9 +217,56 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { GrGLsizei stride = this->getDrawState().getVertexSize(); - size_t vertexOffset; - GrGLVertexBuffer* vb= this->setBuffers(info.isIndexed(), &vertexOffset, indexOffsetInBytes); - vertexOffset += stride * info.startVertex(); + size_t vertexOffsetInBytes = stride * info.startVertex(); + + const GeometryPoolState& geoPoolState = this->getGeomPoolState(); + + GrGLVertexBuffer* vbuf; + switch (this->getGeomSrc().fVertexSrc) { + case kBuffer_GeometrySrcType: + 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()); + vertexOffsetInBytes += vbuf->baseOffset(); + + GrGLIndexBuffer* ibuf = NULL; + if (info.isIndexed()) { + GrAssert(NULL != indexOffsetInBytes); + + switch (this->getGeomSrc().fIndexSrc) { + case kBuffer_GeometrySrcType: + *indexOffsetInBytes = 0; + ibuf = (GrGLIndexBuffer*)this->getGeomSrc().fIndexBuffer; + break; + case kArray_GeometrySrcType: + case kReserved_GeometrySrcType: + this->finalizeReservedIndices(); + *indexOffsetInBytes = geoPoolState.fPoolStartIndex * sizeof(GrGLushort); + ibuf = (GrGLIndexBuffer*) geoPoolState.fPoolIndexBuffer; + break; + default: + ibuf = NULL; // suppress warning + GrCrash("Unknown geometry src type!"); + } + + GrAssert(NULL != ibuf); + GrAssert(!ibuf->isLocked()); + *indexOffsetInBytes += ibuf->baseOffset(); + } + GrGLAttribArrayState* attribState = + fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf); uint32_t usedAttribArraysMask = 0; const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs(); @@ -229,16 +276,16 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) { usedAttribArraysMask |= (1 << vertexAttribIndex); GrVertexAttribType attribType = vertexAttrib->fType; - fHWGeometryState.setAttribArray(this, - vertexAttribIndex, - vb, - GrGLProgram::kAttribLayouts[attribType].fCount, - GrGLProgram::kAttribLayouts[attribType].fType, - GrGLProgram::kAttribLayouts[attribType].fNormalized, - stride, - reinterpret_cast<GrGLvoid*>( - vertexOffset + vertexAttrib->fOffset)); - } - - fHWGeometryState.disableUnusedAttribArrays(this, usedAttribArraysMask); + attribState->set(this, + vertexAttribIndex, + vbuf, + GrGLProgram::kAttribLayouts[attribType].fCount, + GrGLProgram::kAttribLayouts[attribType].fType, + GrGLProgram::kAttribLayouts[attribType].fNormalized, + stride, + reinterpret_cast<GrGLvoid*>( + vertexOffsetInBytes + vertexAttrib->fOffset)); + } + + attribState->disableUnusedAttribArrays(this, usedAttribArraysMask); } diff --git a/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp b/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp index f8c5b1fdcc..1cf9b53442 100644 --- a/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp +++ b/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp @@ -559,7 +559,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteVertexArrays(GrGLsizei n, const GrGLui GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindVertexArray(GrGLuint id) { GrVertexArrayObj* array = GR_FIND(id, GrVertexArrayObj, GrDebugGL::kVertexArray_ObjTypes); - GrAlwaysAssert(array); + GrAlwaysAssert((0 == id) || NULL != array); GrDebugGL::getInstance()->setVertexArray(array); } diff --git a/src/gpu/gl/mac/SkNativeGLContext_mac.cpp b/src/gpu/gl/mac/SkNativeGLContext_mac.cpp index b821f3dc11..2c43c3d2d4 100644 --- a/src/gpu/gl/mac/SkNativeGLContext_mac.cpp +++ b/src/gpu/gl/mac/SkNativeGLContext_mac.cpp @@ -6,6 +6,7 @@ * found in the LICENSE file. */ #include "gl/SkNativeGLContext.h" +#include "AvailabilityMacros.h" SkNativeGLContext::AutoContextRestore::AutoContextRestore() { fOldCGLContext = CGLGetCurrentContext(); @@ -35,7 +36,7 @@ const GrGLInterface* SkNativeGLContext::createGLContext() { SkASSERT(NULL == fContext); CGLPixelFormatAttribute attributes[] = { -#if 0 +#if MAC_OS_X_VERSION_10_7 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core, #endif (CGLPixelFormatAttribute)0 diff --git a/src/gpu/gl/win/SkNativeGLContext_win.cpp b/src/gpu/gl/win/SkNativeGLContext_win.cpp index b5a6053b92..4c736994fe 100644 --- a/src/gpu/gl/win/SkNativeGLContext_win.cpp +++ b/src/gpu/gl/win/SkNativeGLContext_win.cpp @@ -86,7 +86,7 @@ const GrGLInterface* SkNativeGLContext::createGLContext() { return NULL; } - if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, false))) { + if (!(fGlRenderContext = SkCreateWGLContext(fDeviceContext, 0, true))) { SkDebugf("Could not create rendering context.\n"); this->destroyGLContext(); return NULL; |