blob: ff2b8313d386ca5558e4a7835c87dd2196c64457 [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 GrAutoMapVertexBuffer_DEFINED
#define GrAutoMapVertexBuffer_DEFINED
#include "include/private/SkNoncopyable.h"
#include "src/gpu/GrGpuBuffer.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
// This class automatically allocates and maps a GPU vertex buffer, and polyfills the mapping
// functionality with a mirror buffer on CPU if it is not supported.
class GrAutoMapVertexBuffer : SkNoncopyable {
public:
~GrAutoMapVertexBuffer() {
if (this->isMapped()) {
this->unmapBuffer();
}
}
bool hasGpuBuffer() const { return SkToBool(fGpuBuffer.get()); }
sk_sp<const GrGpuBuffer> gpuBuffer() const { return fGpuBuffer; }
bool isMapped() const { return SkToBool(fData); }
void* data() const { SkASSERT(this->isMapped()); return fData; }
void resetAndMapBuffer(GrOnFlushResourceProvider* onFlushRP, size_t sizeInBytes) {
if (this->isMapped()) {
this->unmapBuffer();
}
fGpuBuffer = onFlushRP->makeBuffer(GrGpuBufferType::kVertex, sizeInBytes);
if (!fGpuBuffer) {
fSizeInBytes = 0;
fData = nullptr;
return;
}
fSizeInBytes = sizeInBytes;
fData = fGpuBuffer->map();
if (!fData) {
// Mapping failed. Allocate a mirror buffer on CPU.
fData = sk_malloc_throw(fSizeInBytes);
}
}
void unmapBuffer() {
SkASSERT(this->isMapped());
if (fGpuBuffer->isMapped()) {
fGpuBuffer->unmap();
} else {
// fData is a mirror buffer on CPU.
fGpuBuffer->updateData(fData, fSizeInBytes);
sk_free(fData);
}
fData = nullptr;
}
protected:
sk_sp<GrGpuBuffer> fGpuBuffer;
size_t fSizeInBytes = 0;
void* fData = nullptr;
};
template<typename T> class GrTAutoMapVertexBuffer : public GrAutoMapVertexBuffer {
public:
T& operator[](int idx) {
SkASSERT(this->isMapped());
SkASSERT(idx >= 0 && (size_t)idx < fSizeInBytes / sizeof(T));
return ((T*)fData)[idx];
}
};
#endif