| /* |
| * 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 "GrGLBufferImpl.h" |
| #include "GrGLGpu.h" |
| |
| #define GL_CALL(GPU, X) GR_GL_CALL(GPU->glInterface(), X) |
| |
| #ifdef SK_DEBUG |
| #define VALIDATE() this->validate() |
| #else |
| #define VALIDATE() do {} while(false) |
| #endif |
| |
| GrGLBufferImpl::GrGLBufferImpl(GrGLGpu* gpu, const Desc& desc, GrGLenum bufferType) |
| : fDesc(desc) |
| , fBufferType(bufferType) |
| , fMapPtr(nullptr) { |
| if (0 == desc.fID) { |
| if (gpu->caps()->mustClearUploadedBufferData()) { |
| fCPUData = sk_calloc_throw(desc.fSizeInBytes); |
| } else { |
| fCPUData = sk_malloc_flags(desc.fSizeInBytes, SK_MALLOC_THROW); |
| } |
| fGLSizeInBytes = 0; |
| } else { |
| fCPUData = nullptr; |
| // We assume that the GL buffer was created at the desc's size initially. |
| fGLSizeInBytes = fDesc.fSizeInBytes; |
| } |
| VALIDATE(); |
| } |
| |
| void GrGLBufferImpl::release(GrGLGpu* gpu) { |
| VALIDATE(); |
| // make sure we've not been abandoned or already released |
| if (fCPUData) { |
| sk_free(fCPUData); |
| fCPUData = nullptr; |
| } else if (fDesc.fID) { |
| gpu->releaseBuffer(fDesc.fID, fBufferType); |
| fDesc.fID = 0; |
| fGLSizeInBytes = 0; |
| } |
| fMapPtr = nullptr; |
| VALIDATE(); |
| } |
| |
| void GrGLBufferImpl::abandon() { |
| fDesc.fID = 0; |
| fGLSizeInBytes = 0; |
| fMapPtr = nullptr; |
| sk_free(fCPUData); |
| fCPUData = nullptr; |
| VALIDATE(); |
| } |
| |
| void* GrGLBufferImpl::map(GrGLGpu* gpu) { |
| VALIDATE(); |
| SkASSERT(!this->isMapped()); |
| if (0 == fDesc.fID) { |
| fMapPtr = fCPUData; |
| } else { |
| fMapPtr = gpu->mapBuffer(fDesc.fID, fBufferType, fDesc.fDynamic, fGLSizeInBytes, |
| fDesc.fSizeInBytes); |
| fGLSizeInBytes = fDesc.fSizeInBytes; |
| } |
| VALIDATE(); |
| return fMapPtr; |
| } |
| |
| void GrGLBufferImpl::unmap(GrGLGpu* gpu) { |
| VALIDATE(); |
| SkASSERT(this->isMapped()); |
| if (0 != fDesc.fID) { |
| gpu->unmapBuffer(fDesc.fID, fBufferType, fMapPtr); |
| } |
| fMapPtr = nullptr; |
| } |
| |
| bool GrGLBufferImpl::isMapped() const { |
| VALIDATE(); |
| return SkToBool(fMapPtr); |
| } |
| |
| bool GrGLBufferImpl::updateData(GrGLGpu* gpu, const void* src, size_t srcSizeInBytes) { |
| SkASSERT(!this->isMapped()); |
| VALIDATE(); |
| if (srcSizeInBytes > fDesc.fSizeInBytes) { |
| return false; |
| } |
| if (0 == fDesc.fID) { |
| memcpy(fCPUData, src, srcSizeInBytes); |
| return true; |
| } |
| gpu->bufferData(fDesc.fID, fBufferType, fDesc.fDynamic, fDesc.fSizeInBytes, src, |
| srcSizeInBytes); |
| #if GR_GL_USE_BUFFER_DATA_NULL_HINT |
| fGLSizeInBytes = fDesc.fSizeInBytes; |
| #else |
| fGLSizeInBytes = srcSizeInBytes; |
| #endif |
| VALIDATE(); |
| return true; |
| } |
| |
| void GrGLBufferImpl::validate() const { |
| SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); |
| // The following assert isn't valid when the buffer has been abandoned: |
| // SkASSERT((0 == fDesc.fID) == (fCPUData)); |
| SkASSERT(nullptr == fCPUData || 0 == fGLSizeInBytes); |
| SkASSERT(nullptr == fMapPtr || fCPUData || fGLSizeInBytes <= fDesc.fSizeInBytes); |
| SkASSERT(nullptr == fCPUData || nullptr == fMapPtr || fCPUData == fMapPtr); |
| } |