/*
 * 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 GrOpFlushState_DEFINED
#define GrOpFlushState_DEFINED

#include "GrBufferAllocPool.h"
#include "GrGpu.h"
#include "ops/GrMeshDrawOp.h"

class GrGpuCommandBuffer;
class GrResourceProvider;

/** Tracks the state across all the GrOps (really just the GrDrawOps) in a GrOpList flush. */
class GrOpFlushState {
public:
    GrOpFlushState(GrGpu*, GrResourceProvider*);

    ~GrOpFlushState() { this->reset(); }

    /** Inserts an upload to be executed after all ops in the flush prepared their draws but before
        the draws are executed to the backend 3D API. */
    void addASAPUpload(GrDrawOp::DeferredUploadFn&& upload) {
        fAsapUploads.emplace_back(std::move(upload));
    }

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

    /** Has the token been flushed to the backend 3D API. */
    bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
        return token.fSequenceNumber <= fLastFlushedToken.fSequenceNumber;
    }

    /** Issue a token to an operation that is being enqueued. */
    GrDrawOpUploadToken issueDrawToken() {
        return GrDrawOpUploadToken(++fLastIssuedToken.fSequenceNumber);
    }

    /** Call every time a draw that was issued a token is flushed */
    void flushToken() { ++fLastFlushedToken.fSequenceNumber; }

    /** Gets the next draw token that will be issued. */
    GrDrawOpUploadToken nextDrawToken() const {
        return GrDrawOpUploadToken(fLastIssuedToken.fSequenceNumber + 1);
    }

    /** The last token flushed to all the way to the backend API. */
    GrDrawOpUploadToken nextTokenToFlush() const {
        return GrDrawOpUploadToken(fLastFlushedToken.fSequenceNumber + 1);
    }

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

    /** This is called after each op 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++) {
            this->doUpload(fAsapUploads[i]);
        }
        fAsapUploads.reset();
    }

    void doUpload(GrDrawOp::DeferredUploadFn& upload) {
        GrDrawOp::WritePixelsFn wp = [this] (GrSurface* surface,
                int left, int top, int width, int height,
                GrPixelConfig config, const void* buffer,
                size_t rowBytes) -> bool {
            return this->fGpu->writePixels(surface, left, top, width, height, config, buffer,
                                           rowBytes);
        };
        upload(wp);
    }

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

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

    GrGpuCommandBuffer* commandBuffer() { return fCommandBuffer; }
    void setCommandBuffer(GrGpuCommandBuffer* buffer) { fCommandBuffer = buffer; }

    GrGpu* gpu() { return fGpu; }

    void reset() {
        fVertexPool.reset();
        fIndexPool.reset();
    }

    /** Additional data required on a per-op basis when executing GrDrawOps. */
    struct DrawOpArgs {
        GrRenderTarget* fRenderTarget;
        const GrAppliedClip* fAppliedClip;
        GrXferProcessor::DstTexture fDstTexture;
    };

    void setDrawOpArgs(DrawOpArgs* opArgs) { fOpArgs = opArgs; }

    const DrawOpArgs& drawOpArgs() const {
        SkASSERT(fOpArgs);
        return *fOpArgs;
    }

private:
    GrGpu*                                      fGpu;
    GrResourceProvider*                         fResourceProvider;
    GrGpuCommandBuffer*                         fCommandBuffer;
    GrVertexBufferAllocPool                     fVertexPool;
    GrIndexBufferAllocPool                      fIndexPool;
    SkSTArray<4, GrDrawOp::DeferredUploadFn>    fAsapUploads;
    GrDrawOpUploadToken                         fLastIssuedToken;
    GrDrawOpUploadToken                         fLastFlushedToken;
    DrawOpArgs*                                 fOpArgs;
};

/**
 * A word about uploads and tokens: Ops should usually schedule their uploads to occur at the
 * begining of a frame whenever possible. These are called ASAP uploads. Of course, this requires
 * that there are no draws that have yet to be flushed that rely on the old texture contents. In
 * that case the ASAP upload would happen prior to the previous draw causing the draw to read the
 * new (wrong) texture data. In that case they should schedule an inline upload.
 *
 * Ops, in conjunction with helpers such as GrDrawOpAtlas, can use the token system to know
 * what the most recent draw was that referenced a resource (or portion of a resource). Each draw
 * is assigned a token. A resource (or portion) can be tagged with the most recent draw's
 * token. The target provides a facility for testing whether the draw corresponding to the token
 * has been flushed. If it has not been flushed then the op must perform an inline upload instead.
 * When scheduling an inline upload the op provides the token of the draw that the upload must occur
 * before. The upload will then occur between the draw that requires the new data but after the
 * token that requires the old data.
 *
 * TODO: Currently the token/upload interface is spread over GrDrawOp, GrMeshDrawOp,
 * GrDrawOp::Target, and GrMeshDrawOp::Target. However, the interface at the GrDrawOp level is not
 * complete and isn't useful. We should push it down to GrMeshDrawOp until it is required at the
 * GrDrawOp level.
 */

/**
 * GrDrawOp instances use this object to allocate space for their geometry and to issue the draws
 * that render their op.
 */
class GrDrawOp::Target {
public:
    Target(GrOpFlushState* state, GrDrawOp* op) : fState(state), fOp(op) {}

    /** Returns the token of the draw that this upload will occur before. */
    GrDrawOpUploadToken addInlineUpload(DeferredUploadFn&& upload) {
        fOp->fInlineUploads.emplace_back(std::move(upload), fState->nextDrawToken());
        return fOp->fInlineUploads.back().fUploadBeforeToken;
    }

    /** Returns the token of the draw that this upload will occur before. Since ASAP uploads
        are done first during a flush, this will be the first token since the most recent
        flush. */
    GrDrawOpUploadToken addAsapUpload(DeferredUploadFn&& upload) {
        fState->addASAPUpload(std::move(upload));
        return fState->nextTokenToFlush();
    }

    bool hasDrawBeenFlushed(GrDrawOpUploadToken token) const {
        return fState->hasDrawBeenFlushed(token);
    }

    /** Gets the next draw token that will be issued by this target. This can be used by an op
        to record that the next draw it issues will use a resource (e.g. texture) while preparing
        that draw. */
    GrDrawOpUploadToken nextDrawToken() const { return fState->nextDrawToken(); }

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

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

protected:
    GrDrawOp* op() { return fOp; }
    GrOpFlushState* state() { return fState; }

private:
    GrOpFlushState* fState;
    GrDrawOp* fOp;
};

/** Extension of GrDrawOp::Target for use by GrMeshDrawOp. Adds the ability to create vertex
    draws. */
class GrMeshDrawOp::Target : public GrDrawOp::Target {
public:
    Target(GrOpFlushState* state, GrMeshDrawOp* op) : INHERITED(state, op) {}

    void draw(const GrGeometryProcessor* gp, const GrMesh& mesh);

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

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

    /** Helpers for ops 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:
    GrMeshDrawOp* meshDrawOp() { return static_cast<GrMeshDrawOp*>(this->op()); }
    typedef GrDrawOp::Target INHERITED;
};

#endif
