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