| /* |
| * 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 GrEagerVertexAllocator_DEFINED |
| #define GrEagerVertexAllocator_DEFINED |
| |
| #include "src/gpu/ops/GrMeshDrawOp.h" |
| |
| // This interface is used to allocate and map GPU vertex data before the exact number of required |
| // vertices is known. Usage pattern: |
| // |
| // 1. Call lock(eagerCount) with an upper bound on the number of required vertices. |
| // 2. Compute and write vertex data to the returned pointer (if not null). |
| // 3. Call unlock(actualCount) and provide the actual number of vertices written during step #2. |
| // |
| // On step #3, the implementation will attempt to shrink the underlying GPU memory slot to fit the |
| // actual vertex count. |
| class GrEagerVertexAllocator { |
| public: |
| template<typename T> T* lock(int eagerCount) { |
| return static_cast<T*>(this->lock(sizeof(T), eagerCount)); |
| } |
| virtual void* lock(size_t stride, int eagerCount) = 0; |
| |
| virtual void unlock(int actualCount) = 0; |
| |
| virtual ~GrEagerVertexAllocator() {} |
| }; |
| |
| // GrEagerVertexAllocator implementation that uses GrMeshDrawOp::Target::makeVertexSpace and |
| // GrMeshDrawOp::Target::putBackVertices. |
| class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator { |
| public: |
| GrEagerDynamicVertexAllocator(GrMeshDrawOp::Target* target, |
| sk_sp<const GrBuffer>* vertexBuffer, |
| int* baseVertex) |
| : fTarget(target) |
| , fVertexBuffer(vertexBuffer) |
| , fBaseVertex(baseVertex) { |
| } |
| |
| #ifdef SK_DEBUG |
| ~GrEagerDynamicVertexAllocator() override { |
| SkASSERT(!fLockCount); |
| } |
| #endif |
| |
| // Un-shadow GrEagerVertexAllocator::lock<T>. |
| using GrEagerVertexAllocator::lock; |
| |
| // Mark "final" as a hint for the compiler to not use the vtable. |
| void* lock(size_t stride, int eagerCount) final { |
| SkASSERT(!fLockCount); |
| SkASSERT(eagerCount); |
| if (void* data = fTarget->makeVertexSpace(stride, eagerCount, fVertexBuffer, fBaseVertex)) { |
| fLockStride = stride; |
| fLockCount = eagerCount; |
| return data; |
| } |
| fVertexBuffer->reset(); |
| *fBaseVertex = 0; |
| return nullptr; |
| } |
| |
| // Mark "final" as a hint for the compiler to not use the vtable. |
| void unlock(int actualCount) final { |
| SkASSERT(fLockCount); |
| SkASSERT(actualCount <= fLockCount); |
| fTarget->putBackVertices(fLockCount - actualCount, fLockStride); |
| if (!actualCount) { |
| fVertexBuffer->reset(); |
| *fBaseVertex = 0; |
| } |
| fLockCount = 0; |
| } |
| |
| private: |
| GrMeshDrawOp::Target* const fTarget; |
| sk_sp<const GrBuffer>* const fVertexBuffer; |
| int* const fBaseVertex; |
| |
| size_t fLockStride; |
| int fLockCount = 0; |
| }; |
| |
| #endif |