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

#ifndef GrBatchBuffer_DEFINED
#define GrBatchBuffer_DEFINED

#include "GrBufferAllocPool.h"
#include "batches/GrVertexBatch.h"

class GrResourceProvider;

/** Simple class that performs the upload on behalf of a GrBatchUploader. */
class GrBatchUploader::TextureUploader {
public:
    TextureUploader(GrGpu* gpu) : fGpu(gpu) { SkASSERT(gpu); }

    /**
        * Updates the pixels in a rectangle of a texture.
        *
        * @param left          left edge of the rectangle to write (inclusive)
        * @param top           top edge of the rectangle to write (inclusive)
        * @param width         width of rectangle to write in pixels.
        * @param height        height of rectangle to write in pixels.
        * @param config        the pixel config of the source buffer
        * @param buffer        memory to read pixels from
        * @param rowBytes      number of bytes between consecutive rows. Zero
        *                      means rows are tightly packed.
        */
    bool writeTexturePixels(GrTexture* texture,
                            int left, int top, int width, int height,
                            GrPixelConfig config, const void* buffer,
                            size_t rowBytes) {
        return fGpu->writePixels(texture, left, top, width, height, config, buffer, rowBytes);
    }

private:
    GrGpu* fGpu;
};

/** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
class GrBatchFlushState {
public:
    GrBatchFlushState(GrGpu*, GrResourceProvider*, GrBatchToken lastFlushedToken);

    ~GrBatchFlushState() { SkASSERT(fLastFlushedToken == fCurrentToken); }

    void advanceToken() { ++fCurrentToken; }

    void advanceLastFlushedToken() { ++fLastFlushedToken; }

    /** Inserts an upload to be executred after all batches in the flush prepared their draws
        but before the draws are executed to the backend 3D API. */
    void addASAPUpload(GrBatchUploader* upload) {
        fAsapUploads.push_back().reset(SkRef(upload));
    }

    const GrCaps& caps() const { return *fGpu->caps(); }
    GrResourceProvider* resourceProvider() const { return fResourceProvider; }

    /** Has the token been flushed to the backend 3D API. */
    bool hasTokenBeenFlushed(GrBatchToken token) const { return fLastFlushedToken >= token; }

    /** The current token advances once for every contiguous set of uninterrupted draws prepared
        by a batch. */
    GrBatchToken currentToken() const { return fCurrentToken; }

    /** The last token flushed to all the way to the backend API. */
    GrBatchToken lastFlushedToken() const { return fLastFlushedToken; }

    /** This is a magic token that can be used to indicate that an upload should occur before
        any draws for any batch in the current flush execute. */
    GrBatchToken asapToken() const { return fLastFlushedToken + 1; }

    void* makeVertexSpace(size_t vertexSize, int vertexCount,
                          const GrVertexBuffer** buffer, int* startVertex);
    uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex);

    /** This is called after each batch has a chance to prepare its draws and before the draws
        are issued. */
    void preIssueDraws() {
        fVertexPool.unmap();
        fIndexPool.unmap();
        int uploadCount = fAsapUploads.count();
        for (int i = 0; i < uploadCount; i++) {
            fAsapUploads[i]->upload(&fUploader);
        }
        fAsapUploads.reset();
    }

    void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }

    void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }

    GrBatchUploader::TextureUploader* uploader() { return &fUploader; }

    GrGpu* gpu() { return fGpu; }

private:
    GrGpu*                                          fGpu;
    GrBatchUploader::TextureUploader                fUploader;

    GrResourceProvider*                             fResourceProvider;

    GrVertexBufferAllocPool                         fVertexPool;
    GrIndexBufferAllocPool                          fIndexPool;

    SkTArray<SkAutoTUnref<GrBatchUploader>, true>   fAsapUploads;

    GrBatchToken                                    fCurrentToken;

    GrBatchToken                                    fLastFlushedToken;
};

/**
 * GrDrawBatch instances use this object to allocate space for their geometry and to issue the draws
 * that render their batch.
 */
class GrDrawBatch::Target {
public:
    Target(GrBatchFlushState* state, GrDrawBatch* batch) : fState(state), fBatch(batch) {}

    void upload(GrBatchUploader* upload) {
        if (this->asapToken() == upload->lastUploadToken()) {
            fState->addASAPUpload(upload);
        } else {
            fBatch->fInlineUploads.push_back().reset(SkRef(upload));
        }
    }

    bool hasTokenBeenFlushed(GrBatchToken token) const {
        return fState->hasTokenBeenFlushed(token);
    }
    GrBatchToken currentToken() const { return fState->currentToken(); }
    GrBatchToken asapToken() const { return fState->asapToken(); }

    const GrCaps& caps() const { return fState->caps(); }

    GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }

protected:
    GrDrawBatch* batch() { return fBatch; }
    GrBatchFlushState* state() { return fState; }

private:
    GrBatchFlushState*  fState;
    GrDrawBatch*        fBatch;
};

/** Extension of GrDrawBatch::Target for use by GrVertexBatch. Adds the ability to create vertex
    draws. */
class GrVertexBatch::Target : public GrDrawBatch::Target {
public:
    Target(GrBatchFlushState* state, GrVertexBatch* batch) : INHERITED(state, batch) {}

    void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
        GrVertexBatch::DrawArray* draws = this->vertexBatch()->fDrawArrays.addToTail();
        draws->fPrimitiveProcessor.reset(primProc);
        this->state()->advanceToken();
    }

    void draw(const GrVertices& vertices) {
        this->vertexBatch()->fDrawArrays.tail()->fDraws.push_back(vertices);
    }

    void* makeVertexSpace(size_t vertexSize, int vertexCount,
                          const GrVertexBuffer** buffer, int* startVertex) {
        return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
    }

    uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex) {
        return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
    }

    /** Helpers for batches which over-allocate and then return data to the pool. */
    void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
    void putBackVertices(int vertices, size_t vertexStride) {
        this->state()->putBackVertexSpace(vertices * vertexStride);
    }

private:
    GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); }
    typedef GrDrawBatch::Target INHERITED;
};

#endif
