* Copyright 2020 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ganesh/GrRingBuffer.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/private/base/SkAlign.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/gpu/RefCntedCallback.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include <utility>
size_t GrRingBuffer::getAllocationOffset(size_t size) {
size_t head, tail;
head = fHead;
tail = fTail;
size_t modHead = head & (fTotalSize - 1);
size_t modTail = tail & (fTotalSize - 1);
bool full = (head != tail && modHead == modTail);
if (full) {
return fTotalSize;
}
if (modHead >= modTail) {
if (fTotalSize - modHead < size) {
if (modTail < size) {
return fTotalSize;
}
head += fTotalSize - modHead;
modHead = 0;
}
} else if (modTail - modHead < size) {
return fTotalSize;
}
fHead = SkAlignTo(head + size, fAlignment);
return modHead;
}
GrRingBuffer::Slice GrRingBuffer::suballocate(size_t size) {
fNewAllocation = true;
if (fCurrentBuffer) {
size_t offset = this->getAllocationOffset(size);
if (offset < fTotalSize) {
return { fCurrentBuffer.get(), offset };
}
fTotalSize *= 2;
fPreviousBuffers.push_back(std::move(fCurrentBuffer));
}
GrResourceProvider* resourceProvider = fGpu->getContext()->priv().resourceProvider();
fCurrentBuffer = resourceProvider->createBuffer(fTotalSize,
fType,
kDynamic_GrAccessPattern,
GrResourceProvider::ZeroInit::kNo);
SkASSERT(fCurrentBuffer);
fHead = 0;
fTail = 0;
fGenID++;
size_t offset = this->getAllocationOffset(size);
SkASSERT(offset < fTotalSize);
return { fCurrentBuffer.get(), offset };
}
void GrRingBuffer::startSubmit(GrGpu* gpu) {
for (unsigned int i = 0; i < fPreviousBuffers.size(); ++i) {
fPreviousBuffers[i]->unmap();
gpu->takeOwnershipOfBuffer(std::move(fPreviousBuffers[i]));
}
fPreviousBuffers.clear();
if (fNewAllocation) {
#ifdef SK_BUILD_FOR_MAC
fCurrentBuffer->unmap();
#endif
SubmitData* submitData = new SubmitData();
submitData->fOwner = this;
submitData->fLastHead = fHead;
submitData->fGenID = fGenID;
gpu->addFinishedCallback(skgpu::AutoCallback(FinishSubmit, submitData));
fNewAllocation = false;
}
}
void GrRingBuffer::FinishSubmit(void* finishedContext) {
GrRingBuffer::SubmitData* submitData = (GrRingBuffer::SubmitData*)finishedContext;
if (submitData && submitData->fOwner && submitData->fGenID == submitData->fOwner->fGenID) {
submitData->fOwner->fTail = submitData->fLastHead;
submitData->fOwner = nullptr;
}
delete submitData;
}