/* * 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.fUsage, 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()); SkASSERT(GR_GL_ARRAY_BUFFER == fBufferType || GR_GL_ELEMENT_ARRAY_BUFFER == fBufferType); VALIDATE(); if (srcSizeInBytes > fDesc.fSizeInBytes) { return false; } if (0 == fDesc.fID) { memcpy(fCPUData, src, srcSizeInBytes); return true; } gpu->bufferData(fDesc.fID, fBufferType, fDesc.fUsage, 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 || GR_GL_PIXEL_PACK_BUFFER == fBufferType || GR_GL_PIXEL_UNPACK_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); }