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

#ifndef GrEffect_DEFINED
#define GrEffect_DEFINED

#include "GrColor.h"
#include "GrEffectUnitTest.h"
#include "GrTexture.h"
#include "GrTextureAccess.h"
#include "GrTypesPriv.h"

class GrBackendEffectFactory;
class GrContext;
class GrEffect;
class SkString;

/**
 * A Wrapper class for GrEffect. Its ref-count will track owners that may use effects to enqueue
 * new draw operations separately from ownership within a deferred drawing queue. When the
 * GrEffectRef ref count reaches zero the scratch GrResources owned by the effect can be recycled
 * in service of later draws. However, the deferred draw queue may still own direct references to
 * the underlying GrEffect.
 *
 * GrEffectRefs created by new are placed in a per-thread managed pool. The pool is destroyed when
 * the thread ends. Therefore, all dynamically allocated GrEffectRefs must be unreffed before thread
 * termination.
 */
class GrEffectRef : public SkRefCnt {
public:
    SK_DECLARE_INST_COUNT(GrEffectRef);
    virtual ~GrEffectRef();

    GrEffect* get() { return fEffect; }
    const GrEffect* get() const { return fEffect; }

    const GrEffect* operator-> () { return fEffect; }
    const GrEffect* operator-> () const { return fEffect; }

    void* operator new(size_t size);
    void operator delete(void* target);

    void* operator new(size_t size, void* placement) {
        return ::operator new(size, placement);
    }
    void operator delete(void* target, void* placement) {
        ::operator delete(target, placement);
    }

private:
    friend class GrEffect; // to construct these

    explicit GrEffectRef(GrEffect* effect);

    GrEffect* fEffect;

    typedef SkRefCnt INHERITED;
};

/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the
    Ganesh shading pipeline.
    Subclasses must have a function that produces a human-readable name:
        static const char* Name();
    GrEffect objects *must* be immutable: after being constructed, their fields may not change.

    GrEffect subclass objects should be created by factory functions that return GrEffectRef.
    There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static
    member function of a GrEffect subclass.

    Because almost no code should ever handle a GrEffect directly outside of a GrEffectRef, we
    privately inherit from SkRefCnt to help prevent accidental direct ref'ing/unref'ing of effects.

    Dynamically allocated GrEffects and their corresponding GrEffectRefs are managed by a per-thread
    memory pool. The ref count of an effect must reach 0 before the thread terminates and the pool
    is destroyed. To create a static effect use the macro GR_CREATE_STATIC_EFFECT declared below.
  */
class GrEffect : private SkRefCnt {
public:
    SK_DECLARE_INST_COUNT(GrEffect)

    /**
     * The types of vertex coordinates available to an effect in the vertex shader. Effects can
     * require their own vertex attribute but these coordinates are made available by the framework
     * in all programs. kCustom_CoordsType is provided to signify that an alternative set of coords
     * is used (usually an explicit vertex attribute) but its meaning is determined by the effect
     * subclass.
     */
    enum CoordsType {
        kLocal_CoordsType,
        kPosition_CoordsType,

        kCustom_CoordsType,
    };

    virtual ~GrEffect();

    /**
     * This function is used to perform optimizations. When called the color and validFlags params
     * indicate whether the input components to this effect in the FS will have known values.
     * validFlags is a bitfield of GrColorComponentFlags. The function updates both params to
     * indicate known values of its output. A component of the color param only has meaning if the
     * corresponding bit in validFlags is set.
     */
    virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0;

    /** This object, besides creating back-end-specific helper objects, is used for run-time-type-
        identification. The factory should be an instance of templated class,
        GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have
        a nested type (or typedef) named GLEffect which will be the subclass of GrGLEffect created
        by the factory.

        Example:
        class MyCustomEffect : public GrEffect {
        ...
            virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
                return GrTBackendEffectFactory<MyCustomEffect>::getInstance();
            }
        ...
        };
     */
    virtual const GrBackendEffectFactory& getFactory() const = 0;

    /** Returns true if this and other effect conservatively draw identically. It can only return
        true when the two effects are of the same subclass (i.e. they return the same object from
        from getFactory()).

        A return value of true from isEqual() should not be used to test whether the effects would
        generate the same shader code. To test for identical code generation use the EffectKey
        computed by the GrBackendEffectFactory:
            effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().glEffectKey(effectB).
     */
    bool isEqual(const GrEffectRef& other) const {
        return this->isEqual(*other.get());
    }

    /** Human-meaningful string to identify this effect; may be embedded
        in generated shader code. */
    const char* name() const;

    int numTextures() const { return fTextureAccesses.count(); }

    /** Returns the access pattern for the texture at index. index must be valid according to
        numTextures(). */
    const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; }

    /** Shortcut for textureAccess(index).texture(); */
    GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }

    /** Will this effect read the destination pixel value? */
    bool willReadDstColor() const { return fWillReadDstColor; }

    /** Will this effect read the fragment position? */
    bool willReadFragmentPosition() const { return fWillReadFragmentPosition; }

    int numVertexAttribs() const { return fVertexAttribTypes.count(); }

    GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; }

    static const int kMaxVertexAttribs = 2;

    /** Useful for effects that want to insert a texture matrix that is implied by the texture
        dimensions */
    static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) {
        SkASSERT(NULL != texture);
        SkMatrix mat;
        mat.setIDiv(texture->width(), texture->height());
        return mat;
    }

    void* operator new(size_t size);
    void operator delete(void* target);

    void* operator new(size_t size, void* placement) {
        return ::operator new(size, placement);
    }
    void operator delete(void* target, void* placement) {
        ::operator delete(target, placement);
    }

    /** These functions are used when recording effects into a deferred drawing queue. The inc call
        keeps the effect alive outside of GrEffectRef while allowing any resources owned by the
        effect to be returned to the cache for reuse. The dec call must balance the inc call. */
    void incDeferredRefCounts() const {
        this->ref();
        int count = fTextureAccesses.count();
        for (int t = 0; t < count; ++t) {
            fTextureAccesses[t]->getTexture()->incDeferredRefCount();
        }
    }
    void decDeferredRefCounts() const {
        int count = fTextureAccesses.count();
        for (int t = 0; t < count; ++t) {
            fTextureAccesses[t]->getTexture()->decDeferredRefCount();
        }
        this->unref();
    }

protected:
    /**
     * Subclasses call this from their constructor to register GrTextureAccesses. The effect
     * subclass manages the lifetime of the accesses (this function only stores a pointer). The
     * GrTextureAccess is typically a member field of the GrEffet subclass. This must only be
     * called from the constructor because GrEffects are immutable.
     */
    void addTextureAccess(const GrTextureAccess* textureAccess);

    /**
     * Subclasses call this from their constructor to register vertex attributes (at most
     * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are
     * immutable.
     */
    void addVertexAttrib(GrSLType type);

    GrEffect() : fWillReadDstColor(false), fWillReadFragmentPosition(false), fEffectRef(NULL) {}

    /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for
        an example factory function. */
    static GrEffectRef* CreateEffectRef(GrEffect* effect) {
        if (NULL == effect->fEffectRef) {
            effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect));
        } else {
            effect->fEffectRef->ref();
        }
        return effect->fEffectRef;
    }

    static const GrEffectRef* CreateEffectRef(const GrEffect* effect) {
        return CreateEffectRef(const_cast<GrEffect*>(effect));
    }

    /** Used by GR_CREATE_STATIC_EFFECT below */
    static GrEffectRef* CreateStaticEffectRef(void* refStorage, GrEffect* effect) {
        SkASSERT(NULL == effect->fEffectRef);
        effect->fEffectRef = SkNEW_PLACEMENT_ARGS(refStorage, GrEffectRef, (effect));
        return effect->fEffectRef;
    }


    /** Helper used in subclass factory functions to unref the effect after it has been wrapped in a
        GrEffectRef. E.g.:

        class EffectSubclass : public GrEffect {
        public:
            GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) {
                AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param2, ...)));
                return CreateEffectRef(effect);
            }
     */
    class AutoEffectUnref {
    public:
        AutoEffectUnref(GrEffect* effect) : fEffect(effect) { }
        ~AutoEffectUnref() { fEffect->unref(); }
        operator GrEffect*() { return fEffect; }
    private:
        GrEffect* fEffect;
    };

    /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to a GrEffect subclass
      */
    template <typename T>
    static const T& CastEffect(const GrEffect& effectRef) {
        return *static_cast<const T*>(&effectRef);
    }

    /**
     * If the effect subclass will read the destination pixel value then it must call this function
     * from its constructor. Otherwise, when its generated backend-specific effect class attempts
     * to generate code that reads the destination pixel it will fail.
     */
    void setWillReadDstColor() { fWillReadDstColor = true; }

    /**
     * If the effect will generate a backend-specific effect that will read the fragment position
     * in the FS then it must call this method from its constructor. Otherwise, the request to
     * access the fragment position will be denied.
     */
    void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; }

private:
    bool isEqual(const GrEffect& other) const {
        if (&this->getFactory() != &other.getFactory()) {
            return false;
        }
        bool result = this->onIsEqual(other);
#ifdef SK_DEBUG
        if (result) {
            SkASSERT(this->numTextures() == other.numTextures());
            for (int i = 0; i < this->numTextures(); ++i) {
                SkASSERT(*fTextureAccesses[i] == *other.fTextureAccesses[i]);
            }
        }
#endif
        return result;
    }

    /** Subclass implements this to support isEqual(). It will only be called if it is known that
        the two effects are of the same subclass (i.e. they return the same object from
        getFactory()).*/
    virtual bool onIsEqual(const GrEffect& other) const = 0;

    void EffectRefDestroyed() { fEffectRef = NULL; }

    friend class GrEffectRef;   // to call EffectRefDestroyed()
    friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage
                                // from deferred state, to call isEqual on naked GrEffects, and
                                // to inc/dec deferred ref counts.

    SkSTArray<4, const GrTextureAccess*, true>   fTextureAccesses;
    SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes;
    bool                                         fWillReadDstColor;
    bool                                         fWillReadFragmentPosition;
    GrEffectRef*                                 fEffectRef;

    typedef SkRefCnt INHERITED;
};

inline GrEffectRef::GrEffectRef(GrEffect* effect) {
    SkASSERT(NULL != effect);
    effect->ref();
    fEffect = effect;
}

/**
 * This creates an effect outside of the effect memory pool. The effect's destructor will be called
 * at global destruction time. NAME will be the name of the created GrEffectRef.
 */
#define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS)                                         \
enum {                                                                                            \
    k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8),                         \
    k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef)                     \
};                                                                                                \
static SkAlignedSStorage<k_##NAME##_StorageSize> g_##NAME##_Storage;                              \
static void* NAME##_RefLocation = (char*)g_##NAME##_Storage.get() + k_##NAME##_EffectRefOffset;   \
static GrEffect* NAME##_Effect SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS);\
static SkAutoTDestroy<GrEffect> NAME##_ad(NAME##_Effect);                                         \
static GrEffectRef* NAME(GrEffect::CreateStaticEffectRef(NAME##_RefLocation, NAME##_Effect));     \
static SkAutoTDestroy<GrEffectRef> NAME##_Ref_ad(NAME)


#endif
