| /* |
| * Copyright 2020 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrAutoMapVertexBuffer_DEFINED |
| #define GrAutoMapVertexBuffer_DEFINED |
| |
| #include "include/private/SkNoncopyable.h" |
| #include "src/gpu/GrGpuBuffer.h" |
| #include "src/gpu/GrOnFlushResourceProvider.h" |
| |
| // This class automatically allocates and maps a GPU vertex buffer, and polyfills the mapping |
| // functionality with a mirror buffer on CPU if it is not supported. |
| class GrAutoMapVertexBuffer : SkNoncopyable { |
| public: |
| ~GrAutoMapVertexBuffer() { |
| if (this->isMapped()) { |
| this->unmapBuffer(); |
| } |
| } |
| |
| bool hasGpuBuffer() const { return SkToBool(fGpuBuffer.get()); } |
| sk_sp<const GrGpuBuffer> gpuBuffer() const { return fGpuBuffer; } |
| bool isMapped() const { return SkToBool(fData); } |
| void* data() const { SkASSERT(this->isMapped()); return fData; } |
| |
| void resetAndMapBuffer(GrOnFlushResourceProvider* onFlushRP, size_t sizeInBytes) { |
| if (this->isMapped()) { |
| this->unmapBuffer(); |
| } |
| fGpuBuffer = onFlushRP->makeBuffer(GrGpuBufferType::kVertex, sizeInBytes); |
| if (!fGpuBuffer) { |
| fSizeInBytes = 0; |
| fData = nullptr; |
| return; |
| } |
| fSizeInBytes = sizeInBytes; |
| fData = fGpuBuffer->map(); |
| if (!fData) { |
| // Mapping failed. Allocate a mirror buffer on CPU. |
| fData = sk_malloc_throw(fSizeInBytes); |
| } |
| } |
| |
| void unmapBuffer() { |
| SkASSERT(this->isMapped()); |
| if (fGpuBuffer->isMapped()) { |
| fGpuBuffer->unmap(); |
| } else { |
| // fData is a mirror buffer on CPU. |
| fGpuBuffer->updateData(fData, fSizeInBytes); |
| sk_free(fData); |
| } |
| fData = nullptr; |
| } |
| |
| protected: |
| sk_sp<GrGpuBuffer> fGpuBuffer; |
| size_t fSizeInBytes = 0; |
| void* fData = nullptr; |
| }; |
| |
| template<typename T> class GrTAutoMapVertexBuffer : public GrAutoMapVertexBuffer { |
| public: |
| T& operator[](int idx) { |
| SkASSERT(this->isMapped()); |
| SkASSERT(idx >= 0 && (size_t)idx < fSizeInBytes / sizeof(T)); |
| return ((T*)fData)[idx]; |
| } |
| }; |
| |
| #endif |