Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrBackendProcessorFactory_DEFINED
      9 #define GrBackendProcessorFactory_DEFINED
     10 
     11 #include "GrTypes.h"
     12 #include "SkTemplates.h"
     13 #include "SkThread.h"
     14 #include "SkTypes.h"
     15 #include "SkTArray.h"
     16 
     17 class GrGLProcessor;
     18 class GrGLCaps;
     19 class GrProcessor;
     20 
     21 /**
     22  * Used by effects to build their keys. It incorporates each per-processor key into a larger shader
     23  *  key.
     24  */
     25 class GrProcessorKeyBuilder {
     26 public:
     27     GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) {
     28         SkASSERT(0 == fData->count() % sizeof(uint32_t));
     29     }
     30 
     31     void add32(uint32_t v) {
     32         ++fCount;
     33         fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
     34     }
     35 
     36     /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
     37         add*() call. */
     38     uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
     39         SkASSERT(count > 0);
     40         fCount += count;
     41         return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
     42     }
     43 
     44     size_t size() const { return sizeof(uint32_t) * fCount; }
     45 
     46 private:
     47     SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key.
     48     int fCount;                     // number of uint32_ts added to fData by the effect.
     49 };
     50 
     51 /**
     52  * This class is used to pass the key that was created for a GrGLProcessor back to it
     53  * when it emits code. It may allow the emit step to skip calculations that were
     54  * performed when computing the key.
     55  */
     56 class GrProcessorKey {
     57 public:
     58     GrProcessorKey(const uint32_t* key, int count) : fKey(key), fCount(count) {
     59         SkASSERT(0 == reinterpret_cast<intptr_t>(key) % sizeof(uint32_t));
     60     }
     61 
     62     /** Gets the uint32_t values that the effect inserted into the key. */
     63     uint32_t get32(int index) const {
     64         SkASSERT(index >=0 && index < fCount);
     65         return fKey[index];
     66     }
     67 
     68     /** Gets the number of uint32_t values that the effect inserted into the key. */
     69     int count32() const { return fCount; }
     70 
     71 private:
     72     const uint32_t* fKey;           // unowned ptr into the larger key.
     73     int             fCount;         // number of uint32_ts inserted by the effect into its key.
     74 };
     75 
     76 /**
     77  * Given a GrProcessor of a particular type, creates the corresponding graphics-backend-specific
     78  * effect object. It also tracks equivalence of shaders generated via a key. The factory for an
     79  * effect is accessed via GrProcessor::getFactory(). Each factory instance is assigned an ID at
     80  * construction. The ID of GrProcessor::getFactory() is used as a type identifier. Thus, a
     81  * GrProcessor subclass must always return the same object from getFactory() and that factory object
     82  * must be unique to the GrProcessor subclass (and unique from any further derived subclasses).
     83  *
     84  * Rather than subclassing this class themselves, it is recommended that GrProcessor authors use
     85  * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as:
     86  *
     87  * const GrBackendEffectFactory& MyEffect::getFactory() const {
     88  *     return GrTBackendEffectFactory<MyEffect>::getInstance();
     89  * }
     90  *
     91  * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments.
     92  */
     93 class GrBackendProcessorFactory : SkNoncopyable {
     94 public:
     95     /**
     96      * Generates an effect's key. The key is based on the aspects of the GrProcessor object's
     97      * configuration that affect GLSL code generation. Two GrProcessor instances that would cause
     98      * this->createGLInstance()->emitCode() to produce different code must produce different keys.
     99      */
    100     virtual void getGLProcessorKey(const GrProcessor&, const GrGLCaps&,
    101                                    GrProcessorKeyBuilder*) const = 0;
    102 
    103     /**
    104      * Produces a human-reable name for the effect.
    105      */
    106     virtual const char* name() const = 0;
    107 
    108     /**
    109      * A unique value for every instance of this factory. It is automatically incorporated into the
    110      * effect's key. This allows keys generated by getGLProcessorKey() to only be unique within a
    111      * GrProcessor subclass and not necessarily across subclasses.
    112      */
    113     uint32_t effectClassID() const { return fEffectClassID; }
    114 
    115 protected:
    116     GrBackendProcessorFactory() : fEffectClassID(GenID()) {}
    117     virtual ~GrBackendProcessorFactory() {}
    118 
    119 private:
    120     enum {
    121         kIllegalEffectClassID = 0,
    122     };
    123 
    124     static uint32_t GenID() {
    125         // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
    126         // atomic inc returns the old value not the incremented value. So we add
    127         // 1 to the returned value.
    128         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1;
    129         if (!id) {
    130             SkFAIL("This should never wrap as it should only be called once for each GrProcessor "
    131                    "subclass.");
    132         }
    133         return id;
    134     }
    135 
    136     const uint32_t fEffectClassID;
    137     static int32_t fCurrEffectClassID;
    138 };
    139 
    140 class GrFragmentProcessor;
    141 class GrGeometryProcessor;
    142 class GrGLFragmentProcessor;
    143 class GrGLGeometryProcessor;
    144 
    145 /**
    146  * Backend processor factory cannot actually create anything, it is up to subclasses to implement
    147  * a create binding which matches Gr to GL in a type safe way
    148  */
    149 
    150 class GrBackendFragmentProcessorFactory : public GrBackendProcessorFactory {
    151 public:
    152     /**
    153      * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
    154      * GLSL program and to manage updating uniforms for the program when it is used.
    155      */
    156     virtual GrGLFragmentProcessor* createGLInstance(const GrFragmentProcessor&) const = 0;
    157 };
    158 
    159 class GrBackendGeometryProcessorFactory : public GrBackendProcessorFactory {
    160 public:
    161     /**
    162      * Creates a GrGLProcessor instance that is used both to generate code for the GrProcessor in a
    163      * GLSL program and to manage updating uniforms for the program when it is used.
    164      */
    165     virtual GrGLGeometryProcessor* createGLInstance(const GrGeometryProcessor&) const = 0;
    166 };
    167 
    168 #endif
    169