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

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

class GrGLProcessor;
class GrGLCaps;
class GrProcessor;

/**
 * Used by processors to build their keys. It incorporates each per-processor key into a larger shader
 * key.
 */
class GrProcessorKeyBuilder {
public:
    GrProcessorKeyBuilder(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 processor.
};

/**
 * This class is used to pass the key that was created for a GrGLProcessor back to it
 * when it emits code. It may allow the emit step to skip calculations that were
 * performed when computing the key.
 */
class GrProcessorKey {
public:
    GrProcessorKey(const uint32_t* key, int count) : fKey(key), fCount(count) {
        SkASSERT(0 == reinterpret_cast<intptr_t>(key) % sizeof(uint32_t));
    }

    /** Gets the uint32_t values that the processor inserted into the key. */
    uint32_t get32(int index) const {
        SkASSERT(index >=0 && index < fCount);
        return fKey[index];
    }

    /** Gets the number of uint32_t values that the processor inserted into the key. */
    int count32() const { return fCount; }

private:
    const uint32_t* fKey;           // unowned ptr into the larger key.
    int             fCount;         // number of uint32_ts inserted by the processor into its key.
};

/**
 * Given a GrProcessor of a particular type, creates the corresponding graphics-backend-specific
 * processor object. It also tracks equivalence of shaders generated via a key. The factory for an
 * processor is accessed via GrProcessor::getFactory(). Each factory instance is assigned an ID at
 * construction. The ID of GrProcessor::getFactory() is used as a type identifier. Thus, a
 * GrProcessor subclass must always return the same object from getFactory() and that factory object
 * must be unique to the GrProcessor subclass (and unique from any further derived subclasses).
 *
 * Rather than subclassing this class themselves, it is recommended that GrProcessor authors use 
 * the templated subclass GrTBackendProcessorFactory by writing their getFactory() method as:
 *
 * const GrBackendProcessorFactory& MyProcessor::getFactory() const {
 *     return GrTBackendProcessorFactory<MyProcessor>::getInstance();
 * }
 *
 * Using GrTBackendProcessorFactory places a few constraints on the processor. See that class's
 * comments.
 */
class GrBackendProcessorFactory : SkNoncopyable {
public:
    /** 
     * Generates an processor's key. The key is based on the aspects of the GrProcessor object's
     * configuration that affect GLSL code generation. Two GrProcessor instances that would cause
     * this->createGLInstance()->emitCode() to produce different code must produce different keys.
     */
    virtual void getGLProcessorKey(const GrProcessor&, const GrGLCaps&,
                                   GrProcessorKeyBuilder*) const = 0;

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

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

protected:
    GrBackendProcessorFactory() : fProcessorClassID(GenClassID()) {}
    virtual ~GrBackendProcessorFactory() {}

private:
    enum {
        kIllegalProcessorClassID = 0,
    };

    static uint32_t GenClassID() {
        // fCurrProcessorClassID has been initialized to kIllegalProcessorClassID. 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(&fCurrProcessorClassID)) + 1;
        if (!id) {
            SkFAIL("This should never wrap as it should only be called once for each GrProcessor "
                   "subclass.");
        }
        return id;
    }

    const uint32_t fProcessorClassID;
    static int32_t fCurrProcessorClassID;
};

class GrFragmentProcessor;
class GrGeometryProcessor;
class GrGLFragmentProcessor;
class GrGLGeometryProcessor;

/**
 * Backend processor factory cannot actually create anything, it is up to subclasses to implement
 * a create binding which matches Gr to GL in a type safe way
 */

class GrBackendFragmentProcessorFactory : public GrBackendProcessorFactory {
public:
    /**
     * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
     * GLSL program and to manage updating uniforms for the program when it is used.
     */
    virtual GrGLFragmentProcessor* createGLInstance(const GrFragmentProcessor&) const = 0;
};

class GrBackendGeometryProcessorFactory : public GrBackendProcessorFactory {
public:
    /**
     * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
     * GLSL program and to manage updating uniforms for the program when it is used.
     */
    virtual GrGLGeometryProcessor* createGLInstance(const GrGeometryProcessor&) const = 0;
};

#endif
