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

#include "GrVertexBatch.h"
#include "GrBatchFlushState.h"
#include "GrResourceProvider.h"

GrVertexBatch::GrVertexBatch(uint32_t classID)
    : INHERITED(classID)
    , fBaseDrawToken(GrBatchDrawToken::AlreadyFlushedToken()) {
}

void GrVertexBatch::onPrepare(GrBatchFlushState* state) {
    Target target(state, this);
    this->onPrepareDraws(&target);
}

void* GrVertexBatch::InstancedHelper::init(Target* target, GrPrimitiveType primType,
                                           size_t vertexStride, const GrBuffer* indexBuffer,
                                           int verticesPerInstance, int indicesPerInstance,
                                           int instancesToDraw) {
    SkASSERT(target);
    if (!indexBuffer) {
        return nullptr;
    }
    const GrBuffer* vertexBuffer;
    int firstVertex;
    int vertexCount = verticesPerInstance * instancesToDraw;
    void* vertices = target->makeVertexSpace(vertexStride, vertexCount, &vertexBuffer, &firstVertex);
    if (!vertices) {
        SkDebugf("Vertices could not be allocated for instanced rendering.");
        return nullptr;
    }
    SkASSERT(vertexBuffer);
    size_t ibSize = indexBuffer->gpuMemorySize();
    int maxInstancesPerDraw = static_cast<int>(ibSize / (sizeof(uint16_t) * indicesPerInstance));

    fMesh.initInstanced(primType, vertexBuffer, indexBuffer,
        firstVertex, verticesPerInstance, indicesPerInstance, instancesToDraw,
        maxInstancesPerDraw);
    return vertices;
}

void GrVertexBatch::InstancedHelper::recordDraw(Target* target, const GrGeometryProcessor* gp) {
    SkASSERT(fMesh.instanceCount());
    target->draw(gp, fMesh);
}

void* GrVertexBatch::QuadHelper::init(Target* target, size_t vertexStride,
                                      int quadsToDraw) {
    SkAutoTUnref<const GrBuffer> quadIndexBuffer(
        target->resourceProvider()->refQuadIndexBuffer());
    if (!quadIndexBuffer) {
        SkDebugf("Could not get quad index buffer.");
        return nullptr;
    }
    return this->INHERITED::init(target, kTriangles_GrPrimitiveType, vertexStride,
                                 quadIndexBuffer, kVerticesPerQuad, kIndicesPerQuad, quadsToDraw);
}

void GrVertexBatch::onDraw(GrBatchFlushState* state) {
    int currUploadIdx = 0;
    int currMeshIdx = 0;

    SkASSERT(fQueuedDraws.empty() || fBaseDrawToken == state->nextTokenToFlush());

    for (int currDrawIdx = 0; currDrawIdx < fQueuedDraws.count(); ++currDrawIdx) {
        GrBatchDrawToken drawToken = state->nextTokenToFlush();
        while (currUploadIdx < fInlineUploads.count() &&
               fInlineUploads[currUploadIdx].fUploadBeforeToken == drawToken) {
            state->doUpload(fInlineUploads[currUploadIdx++].fUpload);
        }
        const QueuedDraw &draw = fQueuedDraws[currDrawIdx];
        state->gpu()->draw(*this->pipeline(), *draw.fGeometryProcessor.get(),
                           fMeshes.begin() + currMeshIdx, draw.fMeshCnt);
        currMeshIdx += draw.fMeshCnt;
        state->flushToken();
    }
    SkASSERT(currUploadIdx == fInlineUploads.count());
    SkASSERT(currMeshIdx == fMeshes.count());
    fQueuedDraws.reset();
    fInlineUploads.reset();
}

//////////////////////////////////////////////////////////////////////////////

void GrVertexBatch::Target::draw(const GrGeometryProcessor* gp, const GrMesh& mesh) {
    GrVertexBatch* batch = this->vertexBatch();
    batch->fMeshes.push_back(mesh);
    if (!batch->fQueuedDraws.empty()) {
        // If the last draw shares a geometry processor and there are no intervening uploads,
        // add this mesh to it.
        GrVertexBatch::QueuedDraw& lastDraw = this->vertexBatch()->fQueuedDraws.back();
        if (lastDraw.fGeometryProcessor == gp &&
            (batch->fInlineUploads.empty() ||
             batch->fInlineUploads.back().fUploadBeforeToken != this->nextDrawToken())) {
            ++lastDraw.fMeshCnt;
            return;
        }
    }
    GrVertexBatch::QueuedDraw& draw = this->vertexBatch()->fQueuedDraws.push_back();
    GrBatchDrawToken token = this->state()->issueDrawToken();
    draw.fGeometryProcessor.reset(gp);
    draw.fMeshCnt = 1;
    if (batch->fQueuedDraws.count() == 1) {
        batch->fBaseDrawToken = token;
    }
}
