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 GrEagerVertexAllocator_DEFINED |
9 | #define GrEagerVertexAllocator_DEFINED |
10 | |
11 | #include "src/gpu/ops/GrMeshDrawOp.h" |
12 | |
13 | // This interface is used to allocate and map GPU vertex data before the exact number of required |
14 | // vertices is known. Usage pattern: |
15 | // |
16 | // 1. Call lock(eagerCount) with an upper bound on the number of required vertices. |
17 | // 2. Compute and write vertex data to the returned pointer (if not null). |
18 | // 3. Call unlock(actualCount) and provide the actual number of vertices written during step #2. |
19 | // |
20 | // On step #3, the implementation will attempt to shrink the underlying GPU memory slot to fit the |
21 | // actual vertex count. |
22 | class GrEagerVertexAllocator { |
23 | public: |
24 | template<typename T> T* lock(int eagerCount) { |
25 | return static_cast<T*>(this->lock(sizeof(T), eagerCount)); |
26 | } |
27 | virtual void* lock(size_t stride, int eagerCount) = 0; |
28 | |
29 | virtual void unlock(int actualCount) = 0; |
30 | |
31 | virtual ~GrEagerVertexAllocator() {} |
32 | }; |
33 | |
34 | // GrEagerVertexAllocator implementation that uses GrMeshDrawOp::Target::makeVertexSpace and |
35 | // GrMeshDrawOp::Target::putBackVertices. |
36 | class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator { |
37 | public: |
38 | GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target* target, |
39 | sk_sp<const GrBuffer>* vertexBuffer, int* baseVertex) |
40 | : fTarget(target) |
41 | , fVertexBuffer(vertexBuffer) |
42 | , fBaseVertex(baseVertex) { |
43 | } |
44 | |
45 | #ifdef SK_DEBUG |
46 | ~GrEagerDynamicVertexAllocator() override { |
47 | SkASSERT(!fLockCount); |
48 | } |
49 | #endif |
50 | |
51 | void* lock(size_t stride, int eagerCount) override { |
52 | SkASSERT(!fLockCount); |
53 | SkASSERT(eagerCount); |
54 | if (void* data = fTarget->makeVertexSpace(stride, eagerCount, fVertexBuffer, fBaseVertex)) { |
55 | fLockStride = stride; |
56 | fLockCount = eagerCount; |
57 | return data; |
58 | } |
59 | fVertexBuffer->reset(); |
60 | *fBaseVertex = 0; |
61 | return nullptr; |
62 | } |
63 | |
64 | void unlock(int actualCount) override { |
65 | SkASSERT(fLockCount); |
66 | SkASSERT(actualCount <= fLockCount); |
67 | fTarget->putBackVertices(fLockCount - actualCount, fLockStride); |
68 | if (!actualCount) { |
69 | fVertexBuffer->reset(); |
70 | *fBaseVertex = 0; |
71 | } |
72 | fLockCount = 0; |
73 | } |
74 | |
75 | private: |
76 | GrMeshDrawOp::Target* const fTarget; |
77 | sk_sp<const GrBuffer>* const fVertexBuffer; |
78 | int* const fBaseVertex; |
79 | |
80 | size_t fLockStride; |
81 | int fLockCount = 0; |
82 | }; |
83 | |
84 | #endif |
85 | |