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

#include "GrTypes.h"
#include "SkTemplates.h"
#include "SkThread.h"
#include "SkTypes.h"
#include "SkTArray.h"

class GrGLEffect;
class GrGLCaps;
class GrDrawEffect;

/**
 * Used by effects to build their keys. It incorporates each per-effect key into a larger shader key.
 */
class GrEffectKeyBuilder {
public:
    GrEffectKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
        SkASSERT(0 == fData->count() % sizeof(uint32_t));
    }

    void add32(uint32_t v) {
        ++fCount;
        fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
    }

    /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
        add*() call. */
    uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
        SkASSERT(count > 0);
        fCount += count;
        return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
    }

    size_t size() const { return sizeof(uint32_t) * fCount; }

private:
    SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key.
    int fCount;                     // number of uint32_ts added to fData by the effect.
};

/**
 * Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
 * effect object. It also tracks equivalence of shaders generated via a key. The factory for an
 * effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at
 * construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect
 * subclass must always return the same object from getFactory() and that factory object must be
 * unique to the GrEffect subclass (and unique from any further derived subclasses).
 *
 * Rather than subclassing this class themselves, it is recommended that GrEffect authors use 
 * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as:
 *
 * const GrBackendEffectFactory& MyEffect::getFactory() const {
 *     return GrTBackendEffectFactory<MyEffect>::getInstance();
 * }
 *
 * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments.
 */
class GrBackendEffectFactory : SkNoncopyable {
public:
    typedef uint32_t EffectKey;

    /** 
     * Generates an effect's key. The key is based on the aspects of the GrEffect object's
     * configuration that affect GLSL code generation. Two GrEffect instances that would cause
     * this->createGLInstance()->emitCode() to produce different code must produce different keys.
     */
    virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;

    /**
     * Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL
     * program and to manage updating uniforms for the program when it is used.
     */
    virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;

    /**
     * Produces a human-reable name for the effect.
     */
    virtual const char* name() const = 0;

    /**
     * A unique value for every instance of this factory. It is automatically incorporated into the
     * effect's key. This allows keys generated by getGLEffectKey() to only be unique within a
     * GrEffect subclass and not necessarily across subclasses.
     */
    uint32_t effectClassID() const { return fEffectClassID; }

protected:
    GrBackendEffectFactory() : fEffectClassID(GenID()) {}
    virtual ~GrBackendEffectFactory() {}

private:
    enum {
        kIllegalEffectClassID = 0,
    };

    static uint32_t GenID() {
        // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
        // atomic inc returns the old value not the incremented value. So we add
        // 1 to the returned value.
        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1;
        if (!id) {
            SkFAIL("This should never wrap as it should only be called once for each GrEffect "
                   "subclass.");
        }
        return id;
    }

    const uint32_t fEffectClassID;
    static int32_t fCurrEffectClassID;
};

#endif
