| /* | 
 |  * 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 |