Index: src/gpu/gl/GrGLBufferImpl.cpp |
diff --git a/src/gpu/gl/GrGLBufferImpl.cpp b/src/gpu/gl/GrGLBufferImpl.cpp |
index 3c75b9fe6a1fefa1af8a696736dfbb58808dceba..46e1f797a0c06bb2596f8d10c08653b96d628b63 100644 |
--- a/src/gpu/gl/GrGLBufferImpl.cpp |
+++ b/src/gpu/gl/GrGLBufferImpl.cpp |
@@ -26,20 +26,22 @@ GrGLBufferImpl::GrGLBufferImpl(GrGpuGL* gpu, const Desc& desc, GrGLenum bufferTy |
, fLockPtr(NULL) { |
if (0 == desc.fID) { |
fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW); |
+ fGLSizeInBytes = 0; |
} else { |
fCPUData = NULL; |
+ // We assume that the GL buffer was created at the desc's size initially. |
+ fGLSizeInBytes = fDesc.fSizeInBytes; |
} |
VALIDATE(); |
} |
void GrGLBufferImpl::release(GrGpuGL* gpu) { |
+ VALIDATE(); |
// make sure we've not been abandoned or already released |
if (NULL != fCPUData) { |
- VALIDATE(); |
sk_free(fCPUData); |
fCPUData = NULL; |
} else if (fDesc.fID && !fDesc.fIsWrapped) { |
- VALIDATE(); |
GL_CALL(gpu, DeleteBuffers(1, &fDesc.fID)); |
if (GR_GL_ARRAY_BUFFER == fBufferType) { |
gpu->notifyVertexBufferDelete(fDesc.fID); |
@@ -48,15 +50,19 @@ void GrGLBufferImpl::release(GrGpuGL* gpu) { |
gpu->notifyIndexBufferDelete(fDesc.fID); |
} |
fDesc.fID = 0; |
+ fGLSizeInBytes = 0; |
} |
fLockPtr = NULL; |
+ VALIDATE(); |
} |
void GrGLBufferImpl::abandon() { |
fDesc.fID = 0; |
+ fGLSizeInBytes = 0; |
fLockPtr = NULL; |
sk_free(fCPUData); |
fCPUData = NULL; |
+ VALIDATE(); |
} |
void GrGLBufferImpl::bind(GrGpuGL* gpu) const { |
@@ -67,6 +73,7 @@ void GrGLBufferImpl::bind(GrGpuGL* gpu) const { |
SkASSERT(GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); |
gpu->bindIndexBufferAndDefaultVertexArray(fDesc.fID); |
} |
+ VALIDATE(); |
} |
void* GrGLBufferImpl::lock(GrGpuGL* gpu) { |
@@ -74,17 +81,55 @@ void* GrGLBufferImpl::lock(GrGpuGL* gpu) { |
SkASSERT(!this->isLocked()); |
if (0 == fDesc.fID) { |
fLockPtr = fCPUData; |
- } else if (gpu->caps()->bufferLockSupport()) { |
- this->bind(gpu); |
- // Let driver know it can discard the old data |
- GL_CALL(gpu, BufferData(fBufferType, |
- (GrGLsizeiptr) fDesc.fSizeInBytes, |
- NULL, |
- fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); |
- GR_GL_CALL_RET(gpu->glInterface(), |
- fLockPtr, |
- MapBuffer(fBufferType, GR_GL_WRITE_ONLY)); |
+ } else { |
+ switch (gpu->glCaps().mapBufferType()) { |
+ case GrGLCaps::kNone_MapBufferType: |
+ VALIDATE(); |
+ return NULL; |
+ case GrGLCaps::kMapBuffer_MapBufferType: |
+ this->bind(gpu); |
+ // Let driver know it can discard the old data |
+ if (GR_GL_USE_BUFFER_DATA_NULL_HINT || fDesc.fSizeInBytes != fGLSizeInBytes) { |
+ fGLSizeInBytes = fDesc.fSizeInBytes; |
+ GL_CALL(gpu, |
+ BufferData(fBufferType, fGLSizeInBytes, NULL, |
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); |
+ } |
+ GR_GL_CALL_RET(gpu->glInterface(), fLockPtr, |
+ MapBuffer(fBufferType, GR_GL_WRITE_ONLY)); |
+ break; |
+ case GrGLCaps::kMapBufferRange_MapBufferType: { |
+ this->bind(gpu); |
+ // Make sure the GL buffer size agrees with fDesc before mapping. |
+ if (fDesc.fSizeInBytes != fGLSizeInBytes) { |
+ fGLSizeInBytes = fDesc.fSizeInBytes; |
+ GL_CALL(gpu, |
+ BufferData(fBufferType, fGLSizeInBytes, NULL, |
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); |
+ } |
+ static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT | |
+ GR_GL_MAP_WRITE_BIT; |
+ GR_GL_CALL_RET(gpu->glInterface(), |
+ fLockPtr, |
+ MapBufferRange(fBufferType, 0, fGLSizeInBytes, kAccess)); |
+ break; |
+ } |
+ case GrGLCaps::kChromium_MapBufferType: |
+ this->bind(gpu); |
+ // Make sure the GL buffer size agrees with fDesc before mapping. |
+ if (fDesc.fSizeInBytes != fGLSizeInBytes) { |
+ fGLSizeInBytes = fDesc.fSizeInBytes; |
+ GL_CALL(gpu, |
+ BufferData(fBufferType, fGLSizeInBytes, NULL, |
+ fDesc.fDynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW)); |
+ } |
+ GR_GL_CALL_RET(gpu->glInterface(), |
+ fLockPtr, |
+ MapBufferSubData(fBufferType, 0, fGLSizeInBytes, GR_GL_WRITE_ONLY)); |
+ break; |
+ } |
} |
+ VALIDATE(); |
return fLockPtr; |
} |
@@ -92,9 +137,20 @@ void GrGLBufferImpl::unlock(GrGpuGL* gpu) { |
VALIDATE(); |
SkASSERT(this->isLocked()); |
if (0 != fDesc.fID) { |
- SkASSERT(gpu->caps()->bufferLockSupport()); |
- this->bind(gpu); |
- GL_CALL(gpu, UnmapBuffer(fBufferType)); |
+ switch (gpu->glCaps().mapBufferType()) { |
+ case GrGLCaps::kNone_MapBufferType: |
+ SkDEBUGFAIL("Shouldn't get here."); |
+ return; |
+ case GrGLCaps::kMapBuffer_MapBufferType: // fall through |
+ case GrGLCaps::kMapBufferRange_MapBufferType: |
+ this->bind(gpu); |
+ GL_CALL(gpu, UnmapBuffer(fBufferType)); |
+ break; |
+ case GrGLCaps::kChromium_MapBufferType: |
+ this->bind(gpu); |
+ GR_GL_CALL(gpu->glInterface(), UnmapBufferSubData(fLockPtr)); |
+ break; |
+ } |
} |
fLockPtr = NULL; |
} |
@@ -127,7 +183,8 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB |
// draws that reference the old contents. With this hint it can |
// assign a different allocation for the new contents to avoid |
// flushing the gpu past draws consuming the old contents. |
- GL_CALL(gpu, BufferData(fBufferType, (GrGLsizeiptr) fDesc.fSizeInBytes, NULL, usage)); |
+ fGLSizeInBytes = fDesc.fSizeInBytes; |
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage)); |
GL_CALL(gpu, BufferSubData(fBufferType, 0, (GrGLsizeiptr) srcSizeInBytes, src)); |
} |
#else |
@@ -147,10 +204,12 @@ bool GrGLBufferImpl::updateData(GrGpuGL* gpu, const void* src, size_t srcSizeInB |
// Chromium's command buffer may turn a glBufferSubData where the size |
// exactly matches the buffer size into a glBufferData. So we tack 1 |
// extra byte onto the glBufferData. |
- GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes + 1, NULL, usage)); |
+ fGLSizeInBytes = srcSizeInBytes + 1; |
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, NULL, usage)); |
GL_CALL(gpu, BufferSubData(fBufferType, 0, srcSizeInBytes, src)); |
} else { |
- GL_CALL(gpu, BufferData(fBufferType, srcSizeInBytes, src, usage)); |
+ fGLSizeInBytes = srcSizeInBytes; |
+ GL_CALL(gpu, BufferData(fBufferType, fGLSizeInBytes, src, usage)); |
} |
#endif |
return true; |
@@ -161,5 +220,7 @@ void GrGLBufferImpl::validate() const { |
// The following assert isn't valid when the buffer has been abandoned: |
// SkASSERT((0 == fDesc.fID) == (NULL != fCPUData)); |
SkASSERT(0 != fDesc.fID || !fDesc.fIsWrapped); |
+ SkASSERT(NULL == fCPUData || 0 == fGLSizeInBytes); |
+ SkASSERT(NULL == fLockPtr || NULL != fCPUData || fGLSizeInBytes == fDesc.fSizeInBytes); |
SkASSERT(NULL == fCPUData || NULL == fLockPtr || fCPUData == fLockPtr); |
} |