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

#ifndef GrDeferredUpload_DEFINED
#define GrDeferredUpload_DEFINED

#include <functional>
#include "include/gpu/GrTypes.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"

class GrTextureProxy;

/**
 * A word about deferred uploads and tokens: Ops should usually schedule their uploads to occur at
 * the beginning 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 draw and therefore the draw
 * would read the new (wrong) texture data. When this read-before-write data hazard exists they
 * should schedule an inline upload.
 *
 * Ops, in conjunction with helpers such as GrDrawOpAtlas, use upload tokens 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 thereof) can be tagged with the most recent reading draw's token.
 * The deferred upload's 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 so that the upload occurs after the draw depending on the old contents and before the
 * draw depending on the updated contents. When scheduling an inline upload the op provides the
 * token of the draw that the upload must occur before.
 */

/**
 * GrDeferredUploadToken is used to sequence the uploads relative to each other and to draws.
 */
class GrDeferredUploadToken {
public:
    static GrDeferredUploadToken AlreadyFlushedToken() { return GrDeferredUploadToken(0); }

    GrDeferredUploadToken(const GrDeferredUploadToken&) = default;
    GrDeferredUploadToken& operator=(const GrDeferredUploadToken&) = default;

    bool operator==(const GrDeferredUploadToken& that) const {
        return fSequenceNumber == that.fSequenceNumber;
    }
    bool operator!=(const GrDeferredUploadToken& that) const { return !(*this == that); }
    bool operator<(const GrDeferredUploadToken that) const {
        return fSequenceNumber < that.fSequenceNumber;
    }
    bool operator<=(const GrDeferredUploadToken that) const {
        return fSequenceNumber <= that.fSequenceNumber;
    }
    bool operator>(const GrDeferredUploadToken that) const {
        return fSequenceNumber > that.fSequenceNumber;
    }
    bool operator>=(const GrDeferredUploadToken that) const {
        return fSequenceNumber >= that.fSequenceNumber;
    }

    GrDeferredUploadToken& operator++() {
        ++fSequenceNumber;
        return *this;
    }
    GrDeferredUploadToken operator++(int) {
        auto old = fSequenceNumber;
        ++fSequenceNumber;
        return GrDeferredUploadToken(old);
    }

    GrDeferredUploadToken next() const { return GrDeferredUploadToken(fSequenceNumber + 1); }

    /** Is this token in the [start, end] inclusive interval? */
    bool inInterval(const GrDeferredUploadToken& start, const GrDeferredUploadToken& end) {
        return *this >= start && *this <= end;
    }

private:
    GrDeferredUploadToken() = delete;
    explicit GrDeferredUploadToken(uint64_t sequenceNumber) : fSequenceNumber(sequenceNumber) {}
    uint64_t fSequenceNumber;
};

/*
 * The GrTokenTracker encapsulates the incrementing and distribution of tokens.
 */
class GrTokenTracker {
public:
    /** Gets the token one beyond the last token that has been flushed. */
    GrDeferredUploadToken nextTokenToFlush() const { return fLastFlushedToken.next(); }

    /** 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. */
    GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }

private:
    // Only these three classes get to increment the token counters
    friend class SkInternalAtlasTextContext;
    friend class GrOpFlushState;
    friend class TestingUploadTarget;

    /** Issues the next token for a draw. */
    GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; }

    /** Advances the last flushed token by one. */
    GrDeferredUploadToken flushToken() { return ++fLastFlushedToken; }

    GrDeferredUploadToken fLastIssuedToken = GrDeferredUploadToken::AlreadyFlushedToken();
    GrDeferredUploadToken fLastFlushedToken = GrDeferredUploadToken::AlreadyFlushedToken();
};

/**
 * Passed to a deferred upload when it is executed, this method allows the deferred upload to
 * actually write its pixel data into a texture.
 */
using GrDeferredTextureUploadWritePixelsFn = std::function<bool(GrTextureProxy*,
                                                                SkIRect,
                                                                GrColorType srcColorType,
                                                                const void*,
                                                                size_t rowBytes)>;

/**
 * A deferred texture upload is simply a std::function that takes a
 * GrDeferredTextureUploadWritePixelsFn as a parameter. It is called when it should perform its
 * upload as the draw/upload sequence is executed.
 */
using GrDeferredTextureUploadFn = std::function<void(GrDeferredTextureUploadWritePixelsFn&)>;

/**
 * An interface for scheduling deferred uploads. It accepts asap and deferred inline uploads.
 */
class GrDeferredUploadTarget {
public:
    virtual ~GrDeferredUploadTarget() {}

    virtual const GrTokenTracker* tokenTracker() = 0;

    /** Returns the token of the draw that this upload will occur before. */
    virtual GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) = 0;

    /** 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. */
    virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) = 0;
};

#endif
