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

#include "InstancedRendering.h"

#include "InstancedOp.h"
#include "GrAppliedClip.h"
#include "GrCaps.h"
#include "GrPipeline.h"
#include "GrResourceProvider.h"

#include "instanced/InstanceProcessor.h"

namespace gr_instanced {


InstancedRendering::InstancedRendering(GrGpu* gpu)
    : fGpu(SkRef(gpu))
    SkDEBUGCODE(, fState(State::kRecordingDraws)) {
}


void InstancedRendering::beginFlush(GrResourceProvider* rp) {
#ifdef SK_DEBUG
    SkASSERT(State::kRecordingDraws == fState);
    fState = State::kFlushing;
#endif

    if (fTrackedOps.isEmpty()) {
        return;
    }

    if (!fVertexBuffer) {
        fVertexBuffer.reset(InstanceProcessor::FindOrCreateVertexBuffer(fGpu.get()));
        if (!fVertexBuffer) {
            return;
        }
    }

    if (!fIndexBuffer) {
      fIndexBuffer.reset(InstanceProcessor::FindOrCreateIndex8Buffer(fGpu.get()));
        if (!fIndexBuffer) {
            return;
        }
    }

    if (!fParams.empty()) {
        fParamsBuffer.reset(rp->createBuffer(fParams.count() * sizeof(ParamsTexel),
                                             kTexel_GrBufferType, kDynamic_GrAccessPattern,
                                             GrResourceProvider::kNoPendingIO_Flag |
                                             GrResourceProvider::kRequireGpuMemory_Flag,
                                             fParams.begin()));
        if (!fParamsBuffer) {
            return;
        }
    }

    this->onBeginFlush(rp);
}

void InstancedRendering::draw(const GrPipeline& pipeline,
                              OpInfo info,
                              const InstancedOp* baseOp) {
    InstanceProcessor instProc(info, fParamsBuffer.get());

    this->onDraw(pipeline, instProc, baseOp);
}

void InstancedRendering::endFlush() {
    // The caller is expected to delete all tracked ops (i.e. ops whose applyPipelineOptimizations
    // method has been called) before ending the flush.
    SkASSERT(fTrackedOps.isEmpty());
    fParams.reset();
    fParamsBuffer.reset();
    this->onEndFlush();
    SkDEBUGCODE(fState = State::kRecordingDraws;)
    // Hold on to the shape coords and index buffers.
}

void InstancedRendering::resetGpuResources(ResetType resetType) {
    fVertexBuffer.reset();
    fIndexBuffer.reset();
    fParamsBuffer.reset();
    this->onResetGpuResources(resetType);
}

int InstancedRendering::addOpParams(InstancedOp* op) {
    if (op->fParams.empty()) {
        return 0;
    }

    SkASSERT(fParams.count() < (int)kParamsIdx_InfoMask); // TODO: cleaner.
    int count = fParams.count();
    fParams.push_back_n(op->fParams.count(), op->fParams.begin());
    return count;
}
}
