/*
 * 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 "GrContext.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;
    GrVertexBufferAllocPool fVertexPool;
    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
