/*
 * Copyright 2021 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "experimental/graphite/src/DrawWriter.h"

#include "experimental/graphite/src/DrawBufferManager.h"
#include "src/gpu/BufferWriter.h"

namespace skgpu {

DrawWriter::DrawWriter(DrawDispatcher* dispatcher, DrawBufferManager* bufferManager)
        : DrawWriter(dispatcher, bufferManager, PrimitiveType::kTriangles, 0, 0) {}

DrawWriter::DrawWriter(DrawDispatcher* dispatcher,
                       DrawBufferManager* bufferManager,
                       PrimitiveType primitiveType,
                       size_t vertexStride,
                       size_t instanceStride)
        : fDispatcher(dispatcher)
        , fManager(bufferManager)
        , fPrimitiveType(primitiveType)
        , fVertexStride(vertexStride)
        , fInstanceStride(instanceStride)
        , fVertices()
        , fIndices()
        , fInstances()
        , fTemplateCount(0)
        , fPendingCount(0)
        , fPendingBase(0)
        , fPendingBufferBinds(true) {
    SkASSERT(dispatcher && bufferManager);
}

void DrawWriter::setTemplate(BindBufferInfo vertices,
                             BindBufferInfo indices,
                             BindBufferInfo instances,
                             unsigned int templateCount) {
    if (vertices != fVertices || instances != fInstances || fIndices != indices) {
        if (fPendingCount > 0) {
            this->flush();
        }

        bool willAppendVertices = templateCount == 0;
        bool isAppendingVertices = fTemplateCount == 0;
        if (willAppendVertices != isAppendingVertices ||
            (isAppendingVertices && fVertices != vertices) ||
            (!isAppendingVertices && fInstances != instances)) {
            // The buffer binding target for appended data is changing, so reset the base offset
            fPendingBase = 0;
        }

        fVertices = vertices;
        fInstances = instances;
        fIndices = indices;

        fTemplateCount = templateCount;

        fPendingBufferBinds = true;
    } else if (templateCount != fTemplateCount) {
        if (fPendingCount > 0) {
            this->flush();
        }
        if ((templateCount == 0) != (fTemplateCount == 0)) {
            // Switching from appending vertices to instances, or vice versa, so the pending
            // base vertex for appended data is invalid
            fPendingBase = 0;
        }
        fTemplateCount = templateCount;
    }

    SkASSERT(fVertices      == vertices);
    SkASSERT(fInstances     == instances);
    SkASSERT(fIndices       == indices);
    SkASSERT(fTemplateCount == templateCount);
}

void DrawWriter::flush() {
    if (fPendingCount == 0) {
        return;
    }
    if (fPendingBufferBinds) {
        fDispatcher->bindDrawBuffers(fVertices, fInstances, fIndices);
        fPendingBufferBinds = false;
    }

    if (fTemplateCount) {
        // Instanced drawing
        if (fIndices) {
            fDispatcher->drawIndexedInstanced(fPrimitiveType, 0, fTemplateCount, 0,
                                              fPendingBase, fPendingCount);
        } else {
            fDispatcher->drawInstanced(fPrimitiveType, 0, fTemplateCount,
                                       fPendingBase, fPendingCount);
        }
    } else {
        SkASSERT(!fInstances);
        if (fIndices) {
            fDispatcher->drawIndexed(fPrimitiveType, 0, fPendingCount, fPendingBase);
        } else {
            fDispatcher->draw(fPrimitiveType, fPendingBase, fPendingCount);
        }
    }

    fPendingBase += fPendingCount;
    fPendingCount = 0;
}

VertexWriter DrawWriter::Appender::append(unsigned int count,
                                          size_t stride,
                                          BindBufferInfo& target) {
    SkASSERT(&target == &fWriter.fInstances || &target == &fWriter.fVertices);
    SkASSERT(this == fWriter.fAppender);

    auto [writer, nextChunk] = fWriter.fManager->getVertexWriter(count * stride);
    // Check if next chunk's data is contiguous with what's previously been appended
    if (nextChunk.fBuffer != target.fBuffer ||
        nextChunk.fOffset !=
                target.fOffset + (fWriter.fPendingBase + fWriter.fPendingCount) * stride) {
        // Alignment mismatch, or the old buffer filled up, so must update the bindings
        fWriter.flush();
        target = nextChunk;

        fWriter.fPendingBase = 0;
        fWriter.fPendingBufferBinds = true;
    }

    fWriter.fPendingCount += count;

    return std::move(writer);
}

} // namespace skgpu
