/*
 * Copyright 2023 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/GrMeshBuffers.h"

#include "include/core/SkData.h"
#include "include/core/SkMesh.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/ganesh/SkMeshGanesh.h"
#include "include/private/base/SkAssert.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkMeshPriv.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrDrawingManager.h"
#include "src/gpu/ganesh/GrGpu.h"
#include "src/gpu/ganesh/GrGpuBuffer.h"
#include "src/gpu/ganesh/GrResourceCache.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrStagingBufferManager.h"

#include <cstring>
#include <utility>

template <typename Base, GrGpuBufferType Type> GrMeshBuffer<Base, Type>::~GrMeshBuffer() {
    GrResourceCache::ReturnResourceFromThread(std::move(fBuffer), fContextID);
}

template <typename Base, GrGpuBufferType Type>
sk_sp<Base> GrMeshBuffer<Base, Type>::Make(GrDirectContext* dc, const void* data, size_t size) {
    SkASSERT(dc);

    sk_sp<GrGpuBuffer> buffer = dc->priv().resourceProvider()->createBuffer(
            size,
            Type,
            kStatic_GrAccessPattern,
            data ? GrResourceProvider::ZeroInit::kNo : GrResourceProvider::ZeroInit::kYes);
    if (!buffer) {
        return nullptr;
    }

    if (data && !buffer->updateData(data, 0, size, /*preserve=*/false)) {
        return nullptr;
    }

    auto result = new GrMeshBuffer;
    result->fBuffer = std::move(buffer);
    result->fContextID = dc->directContextID();
    return sk_sp<Base>(result);
}

template <typename Base, GrGpuBufferType Type>
bool GrMeshBuffer<Base, Type>::onUpdate(GrDirectContext* dc,
                                        const void* data,
                                        size_t offset,
                                        size_t size) {
    if (!dc || dc != fBuffer->getContext()) {
        return false;
    }
    SkASSERT(!dc->abandoned());  // If dc is abandoned then fBuffer->getContext() should be null.

    if (!dc->priv().caps()->transferFromBufferToBufferSupport()) {
        auto ownedData = SkData::MakeWithCopy(data, size);
        dc->priv().drawingManager()->newBufferUpdateTask(
                std::move(ownedData), fBuffer, offset);
        return true;
    }

    sk_sp<GrGpuBuffer> tempBuffer;
    size_t tempOffset = 0;
    if (auto* sbm = dc->priv().getGpu()->stagingBufferManager()) {
        auto alignment = dc->priv().caps()->transferFromBufferToBufferAlignment();
        auto [sliceBuffer, sliceOffset, ptr] = sbm->allocateStagingBufferSlice(size, alignment);
        if (sliceBuffer) {
            std::memcpy(ptr, data, size);
            tempBuffer.reset(SkRef(sliceBuffer));
            tempOffset = sliceOffset;
        }
    }

    if (!tempBuffer) {
        tempBuffer = dc->priv().resourceProvider()->createBuffer(size,
                                                                 GrGpuBufferType::kXferCpuToGpu,
                                                                 kDynamic_GrAccessPattern,
                                                                 GrResourceProvider::ZeroInit::kNo);
        if (!tempBuffer) {
            return false;
        }
        if (!tempBuffer->updateData(data, 0, size, /*preserve=*/false)) {
            return false;
        }
    }

    dc->priv().drawingManager()->newBufferTransferTask(
            std::move(tempBuffer), tempOffset, fBuffer, offset, size);

    return true;
}

namespace SkMeshes {
sk_sp<SkMesh::IndexBuffer> MakeIndexBuffer(GrDirectContext* dc, const void* data, size_t size) {
    if (!dc) {
        // Fallback to a CPU buffer.
        return MakeIndexBuffer(data, size);
    }
    return SkMeshPriv::GaneshIndexBuffer::Make(dc, data, size);
}

sk_sp<SkMesh::IndexBuffer> CopyIndexBuffer(GrDirectContext* dc, sk_sp<SkMesh::IndexBuffer> src) {
    if (!src) {
        return nullptr;
    }
    auto* ib = static_cast<SkMeshPriv::IB*>(src.get());
    const void* data = ib->peek();
    if (!data) {
        return nullptr;
    }
    if (!dc) {
        return MakeIndexBuffer(data, ib->size());
    }
    return MakeIndexBuffer(dc, data, ib->size());
}

sk_sp<SkMesh::VertexBuffer> MakeVertexBuffer(GrDirectContext* dc, const void* data, size_t size) {
    if (!dc) {
        return MakeVertexBuffer(data, size);
    }
    return SkMeshPriv::GaneshVertexBuffer::Make(dc, data, size);
}

sk_sp<SkMesh::VertexBuffer> CopyVertexBuffer(GrDirectContext* dc, sk_sp<SkMesh::VertexBuffer> src) {
    if (!src) {
        return nullptr;
    }
    auto* vb = static_cast<SkMeshPriv::VB*>(src.get());
    const void* data = vb->peek();
    if (!data) {
        return nullptr;
    }
    if (!dc) {
        return MakeVertexBuffer(data, vb->size());
    }
    return MakeVertexBuffer(dc, data, vb->size());
}
}  // namespace SkMeshes
