Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / gl / GrGLBufferImpl.cpp
index 3c75b9f..46e1f79 100644 (file)
@@ -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);
 }