|  | /* | 
|  | * 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/BufferWriter.h" | 
|  | #include "src/gpu/ganesh/GrThreadSafeCache.h" | 
|  |  | 
|  | class GrMeshDrawTarget; | 
|  |  | 
|  | // 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: | 
|  | virtual void* lock(size_t stride, int eagerCount) = 0; | 
|  |  | 
|  | virtual void unlock(int actualCount) = 0; | 
|  |  | 
|  | virtual ~GrEagerVertexAllocator() {} | 
|  |  | 
|  | skgpu::VertexWriter lockWriter(size_t stride, int eagerCount) { | 
|  | void* p = this->lock(stride, eagerCount); | 
|  | return p ? skgpu::VertexWriter{p, stride * eagerCount} : skgpu::VertexWriter{}; | 
|  | } | 
|  | }; | 
|  |  | 
|  | // GrEagerVertexAllocator implementation that uses GrMeshDrawTarget::makeVertexSpace and | 
|  | // GrMeshDrawTarget::putBackVertices. | 
|  | class GrEagerDynamicVertexAllocator : public GrEagerVertexAllocator { | 
|  | public: | 
|  | GrEagerDynamicVertexAllocator(GrMeshDrawTarget* target, | 
|  | sk_sp<const GrBuffer>* vertexBuffer, | 
|  | int* baseVertex) | 
|  | : fTarget(target) | 
|  | , fVertexBuffer(vertexBuffer) | 
|  | , fBaseVertex(baseVertex) { | 
|  | } | 
|  |  | 
|  | #ifdef SK_DEBUG | 
|  | ~GrEagerDynamicVertexAllocator() override { | 
|  | SkASSERT(!fLockCount); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | // Mark "final" as a hint for the compiler to not use the vtable. | 
|  | void* lock(size_t stride, int eagerCount) final; | 
|  |  | 
|  | // Mark "final" as a hint for the compiler to not use the vtable. | 
|  | void unlock(int actualCount) final; | 
|  |  | 
|  | private: | 
|  | GrMeshDrawTarget* const fTarget; | 
|  | sk_sp<const GrBuffer>* const fVertexBuffer; | 
|  | int* const fBaseVertex; | 
|  |  | 
|  | size_t fLockStride; | 
|  | int fLockCount = 0; | 
|  | }; | 
|  |  | 
|  | class GrCpuVertexAllocator : public GrEagerVertexAllocator { | 
|  | public: | 
|  | GrCpuVertexAllocator() = default; | 
|  |  | 
|  | #ifdef SK_DEBUG | 
|  | ~GrCpuVertexAllocator() override { | 
|  | SkASSERT(!fLockStride && !fVertices && !fVertexData); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | void* lock(size_t stride, int eagerCount) override; | 
|  | void unlock(int actualCount) override; | 
|  |  | 
|  | sk_sp<GrThreadSafeCache::VertexData> detachVertexData(); | 
|  |  | 
|  | private: | 
|  | sk_sp<GrThreadSafeCache::VertexData> fVertexData; | 
|  |  | 
|  | void*  fVertices = nullptr; | 
|  | size_t fLockStride = 0; | 
|  | }; | 
|  |  | 
|  | #endif |