1 /* 2 * Copyright 2020 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrAutoMapVertexBuffer_DEFINED 9 #define GrAutoMapVertexBuffer_DEFINED 10 11 #include "include/private/SkNoncopyable.h" 12 #include "src/gpu/GrGpuBuffer.h" 13 #include "src/gpu/GrOnFlushResourceProvider.h" 14 15 // This class automatically allocates and maps a GPU vertex buffer, and polyfills the mapping 16 // functionality with a mirror buffer on CPU if it is not supported. 17 class GrAutoMapVertexBuffer : SkNoncopyable { 18 public: ~GrAutoMapVertexBuffer()19 ~GrAutoMapVertexBuffer() { 20 if (this->isMapped()) { 21 this->unmapBuffer(); 22 } 23 } 24 gpuBuffer()25 const GrGpuBuffer* gpuBuffer() const { return fGpuBuffer.get(); } isMapped()26 bool isMapped() const { return SkToBool(fData); } data()27 void* data() const { SkASSERT(this->isMapped()); return fData; } 28 resetAndMapBuffer(GrOnFlushResourceProvider * onFlushRP,size_t sizeInBytes)29 void resetAndMapBuffer(GrOnFlushResourceProvider* onFlushRP, size_t sizeInBytes) { 30 if (this->isMapped()) { 31 this->unmapBuffer(); 32 } 33 fGpuBuffer = onFlushRP->makeBuffer(GrGpuBufferType::kVertex, sizeInBytes); 34 if (!fGpuBuffer) { 35 fSizeInBytes = 0; 36 fData = nullptr; 37 return; 38 } 39 fSizeInBytes = sizeInBytes; 40 fData = fGpuBuffer->map(); 41 if (!fData) { 42 // Mapping failed. Allocate a mirror buffer on CPU. 43 fData = sk_malloc_throw(fSizeInBytes); 44 } 45 } 46 unmapBuffer()47 void unmapBuffer() { 48 SkASSERT(this->isMapped()); 49 if (fGpuBuffer->isMapped()) { 50 fGpuBuffer->unmap(); 51 } else { 52 // fData is a mirror buffer on CPU. 53 fGpuBuffer->updateData(fData, fSizeInBytes); 54 sk_free(fData); 55 } 56 fData = nullptr; 57 } 58 59 protected: 60 sk_sp<GrGpuBuffer> fGpuBuffer; 61 size_t fSizeInBytes = 0; 62 void* fData = nullptr; 63 }; 64 65 template<typename T> class GrTAutoMapVertexBuffer : public GrAutoMapVertexBuffer { 66 public: 67 T& operator[](int idx) { 68 SkASSERT(this->isMapped()); 69 SkASSERT(idx >= 0 && (size_t)idx < fSizeInBytes / sizeof(T)); 70 return ((T*)fData)[idx]; 71 } 72 }; 73 74 #endif 75