/*
 * 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 "src/gpu/graphite/DrawWriter.h"

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

namespace skgpu::graphite {

DrawWriter::DrawWriter(DrawPassCommands::List* commandList, DrawBufferManager* bufferManager)
        : fCommandList(commandList)
        , fManager(bufferManager)
        , fPrimitiveType(PrimitiveType::kTriangles)
        , fVertexStride(0)
        , fInstanceStride(0)
        , fVertices()
        , fIndices()
        , fInstances()
        , fTemplateCount(0)
        , fPendingCount(0)
        , fPendingBase(0)
        , fPendingBufferBinds(true) {
    SkASSERT(commandList && bufferManager);
}

void DrawWriter::setTemplate(BindBufferInfo vertices,
                             BindBufferInfo indices,
                             BindBufferInfo instances,
                             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 >= 0 && templateCount != fTemplateCount) || // vtx or reg. instances
               (templateCount < 0 && fTemplateCount >= 0)) {              // dynamic index instances
        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);
    // NOTE: This allows 'fTemplateCount' to update across multiple DynamicInstances as long
    // as they have the same vertex and index buffers.
    SkASSERT((fTemplateCount < 0) == (templateCount < 0));
    SkASSERT(fTemplateCount < 0 || fTemplateCount == templateCount);
}

void DrawWriter::flush() {
    // If nothing was appended, or the only appended data was through dynamic instances and the
    // final vertex count per instance is 0 (-1 in the sign encoded field), nothing should be drawn.
    if (fPendingCount == 0 || fTemplateCount == -1) {
        return;
    }
    if (fPendingBufferBinds) {
        fCommandList->bindDrawBuffers(fVertices, fInstances, fIndices);
        fPendingBufferBinds = false;
    }

    if (fTemplateCount) {
        // Instanced drawing
        unsigned int realVertexCount;
        if (fTemplateCount < 0) {
            realVertexCount = -fTemplateCount - 1;
            fTemplateCount = -1; // reset to re-accumulate max index account for next flush
        } else {
            realVertexCount = fTemplateCount;
        }

        if (fIndices) {
            fCommandList->drawIndexedInstanced(fPrimitiveType, 0, realVertexCount, 0,
                                               fPendingBase, fPendingCount);
        } else {
            fCommandList->drawInstanced(fPrimitiveType, 0, realVertexCount,
                                        fPendingBase, fPendingCount);
        }
    } else {
        SkASSERT(!fInstances);
        if (fIndices) {
            fCommandList->drawIndexed(fPrimitiveType, 0, fPendingCount, fPendingBase);
        } else {
            fCommandList->draw(fPrimitiveType, fPendingBase, fPendingCount);
        }
    }

    fPendingBase += fPendingCount;
    fPendingCount = 0;
}

} // namespace skgpu::graphite
