/*
 * 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 "GrBatchAtlas.h"
#include "GrBufferAllocPool.h"
#include "GrPendingProgramElement.h"
#include "GrPipeline.h"
#include "GrTRecorder.h"
#include "GrVertices.h"

/*
 * GrBatch instances use this object to allocate space for their geometry and to issue the draws
 * that render their batch.
 */
class GrBatchTarget : public SkNoncopyable {
public:
    typedef GrBatchAtlas::BatchToken BatchToken;
    GrBatchTarget(GrGpu* gpu);

    void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
        GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline));
        fNumberOfDraws++;
        fCurrentToken++;
    }

    class 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->writeTexturePixels(texture, left, top, width, height, config, buffer,
                                            rowBytes);
        }

    private:
        GrGpu* fGpu;
    };

    class Uploader : public SkRefCnt {
    public:
        Uploader(BatchToken lastUploadToken) : fLastUploadToken(lastUploadToken) {}
        BatchToken lastUploadToken() const { return fLastUploadToken; }
        virtual void upload(TextureUploader)=0;

    private:
        BatchToken fLastUploadToken;
    };

    void upload(Uploader* upload) {
        if (this->asapToken() == upload->lastUploadToken()) {
            fAsapUploads.push_back().reset(SkRef(upload));
        } else {
            fInlineUploads.push_back().reset(SkRef(upload));
        }
    }

    void draw(const GrVertices& vertices) {
        fFlushBuffer.back().fVertexDraws.push_back(vertices);
    }

    bool isIssued(BatchToken token) const { return fLastFlushedToken >= token; }
    BatchToken currentToken() const { return fCurrentToken; }
    BatchToken asapToken() const { return fLastFlushedToken + 1; }

    // TODO much of this complexity goes away when batch is everywhere
    void resetNumberOfDraws() { fNumberOfDraws = 0; }
    int numberOfDraws() const { return fNumberOfDraws; }
    void preFlush() {
        this->unmapVertexAndIndexBuffers();
        int updateCount = fAsapUploads.count();
        for (int i = 0; i < updateCount; i++) {
            fAsapUploads[i]->upload(TextureUploader(fGpu));
        }
        fInlineUpdatesIndex = 0;
        fIter = FlushBuffer::Iter(fFlushBuffer);
    }
    void flushNext(int n);
    void postFlush() {
        SkASSERT(!fIter.next());
        fFlushBuffer.reset();
        fAsapUploads.reset();
        fInlineUploads.reset();
    }

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

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

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

    // A helper for draws which overallocate and then return data to the pool
    void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); }

    void putBackVertices(size_t vertices, size_t vertexStride) {
        fVertexPool->putBack(vertices * vertexStride);
    }

    void reset() {
        fVertexPool->reset();
        fIndexPool->reset();    
    }

private:
    void unmapVertexAndIndexBuffers() {
        fVertexPool->unmap();
        fIndexPool->unmap();
    }

    GrGpu* fGpu;
    SkAutoTDelete<GrVertexBufferAllocPool> fVertexPool;
    SkAutoTDelete<GrIndexBufferAllocPool> fIndexPool;

    typedef void* TBufferAlign; // This wouldn't be enough align if a command used long double.

    struct BufferedFlush {
        BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline)
            : fPrimitiveProcessor(primProc)
            , fPipeline(pipeline) {}
        typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
        ProgramPrimitiveProcessor fPrimitiveProcessor;
        const GrPipeline* fPipeline;
        GrBatchTracker fBatchTracker;
        SkSTArray<1, GrVertices, true> fVertexDraws;
    };

    enum {
        kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush),
    };

    typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer;

    FlushBuffer fFlushBuffer;
    // TODO this is temporary
    FlushBuffer::Iter fIter;
    int fNumberOfDraws;
    BatchToken fCurrentToken;
    BatchToken fLastFlushedToken; // The next token to be flushed
    SkTArray<SkAutoTUnref<Uploader>, true> fAsapUploads;
    SkTArray<SkAutoTUnref<Uploader>, true> fInlineUploads;
    int fInlineUpdatesIndex;
};

#endif
