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

#ifndef GrCoordTransform_DEFINED
#define GrCoordTransform_DEFINED

#include "include/core/SkMatrix.h"
#include "src/gpu/GrSurfaceProxyPriv.h"
#include "src/gpu/GrTextureProxy.h"

class GrTexture;

/**
 * A class representing a linear transformation of local coordinates. GrFragnentProcessors
 * these transformations, and the GrGeometryProcessor implements the transformation.
 */
class GrCoordTransform {
public:
    GrCoordTransform()
            : fProxy(nullptr)
            , fNormalize(false)
            , fReverseY(false)
            , fComputeInVertexShader(true) {
        SkDEBUGCODE(fInProcessor = false);
    }

    GrCoordTransform(const GrCoordTransform&) = default;

    /**
     * Create a transformation that maps [0, 1] to a proxy's boundaries. The proxy origin also
     * implies whether a y-reversal should be performed.
     */
    GrCoordTransform(GrTextureProxy* proxy) {
        SkASSERT(proxy);
        SkDEBUGCODE(fInProcessor = false);
        this->reset(SkMatrix::I(), proxy);
    }

    /**
     * Create a transformation from a matrix. The proxy origin also implies whether a y-reversal
     * should be performed.
     */
    GrCoordTransform(const SkMatrix& m, GrTextureProxy* proxy) {
        SkASSERT(proxy);
        SkDEBUGCODE(fInProcessor = false);
        this->reset(m, proxy);
    }

    /**
     * Create a transformation that applies the matrix to a coord set.
     */
    GrCoordTransform(const SkMatrix& m) {
        SkDEBUGCODE(fInProcessor = false);
        this->reset(m);
    }

    GrCoordTransform& operator= (const GrCoordTransform& that) {
        SkASSERT(!fInProcessor);
        fMatrix = that.fMatrix;
        fProxy = that.fProxy;
        fNormalize = that.fNormalize;
        fReverseY = that.fReverseY;
        return *this;
    }

    /**
     * Access the matrix for editing. Note, this must be done before adding the transform to an
     * effect, since effects are immutable.
     */
    SkMatrix* accessMatrix() {
        SkASSERT(!fInProcessor);
        return &fMatrix;
    }

    bool hasSameEffectAs(const GrCoordTransform& that) const {
        if (fNormalize != that.fNormalize ||
            fReverseY != that.fReverseY ||
            !fMatrix.cheapEqualTo(that.fMatrix)) {
            return false;
        }

        if (fNormalize) {
            if (fProxy->backingStoreDimensions() != that.fProxy->backingStoreDimensions()) {
                return false;
            }
        }

        return true;
    }

    const SkMatrix& getMatrix() const { return fMatrix; }
    const GrTextureProxy* proxy() const { return fProxy; }
    bool normalize() const { return fNormalize; }
    bool reverseY() const { return fReverseY; }

    // This should only ever be called at flush time after the backing texture has been
    // successfully instantiated
    GrTexture* peekTexture() const { return fProxy->peekTexture(); }

    bool computeInVertexShader() const { return fComputeInVertexShader; }

    void setComputeInVertexShader(bool computeInVertexShader) {
        fComputeInVertexShader = computeInVertexShader;
    }

private:
    void reset(const SkMatrix& m, GrTextureProxy* proxy = nullptr) {
        SkASSERT(!fInProcessor);

        fMatrix = m;
        fProxy = proxy;
        fNormalize = proxy && proxy->textureType() != GrTextureType::kRectangle;
        fReverseY = proxy && kBottomLeft_GrSurfaceOrigin == proxy->origin();
        fComputeInVertexShader = true;
    }

    // The textures' effect is to optionally normalize the final matrix, so a blind
    // equality check could be misleading
    bool operator==(const GrCoordTransform& that) const;
    bool operator!=(const GrCoordTransform& that) const;

    SkMatrix                fMatrix;
    const GrTextureProxy*   fProxy;
    bool                    fNormalize;
    bool                    fReverseY;
    bool                    fComputeInVertexShader;

#ifdef SK_DEBUG
public:
    void setInProcessor() const { fInProcessor = true; }
private:
    mutable bool fInProcessor;
#endif
};

#endif
