blob: 877a8d33679f16edf7cc3b3229b0ccb47a08a9cf [file] [log] [blame]
/*
* 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