bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 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 | |
bsalomon@google.com | 396e61f | 2012-10-25 19:00:29 +0000 | [diff] [blame] | 8 | #ifndef GrBackendEffectFactory_DEFINED |
| 9 | #define GrBackendEffectFactory_DEFINED |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 10 | |
| 11 | #include "GrTypes.h" |
bsalomon@google.com | 8e520fc | 2012-05-18 20:06:45 +0000 | [diff] [blame] | 12 | #include "SkTemplates.h" |
commit-bot@chromium.org | 86b0de4 | 2014-05-28 20:02:17 +0000 | [diff] [blame] | 13 | #include "SkThread.h" |
commit-bot@chromium.org | a0b4028 | 2013-09-18 13:00:55 +0000 | [diff] [blame] | 14 | #include "SkTypes.h" |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 15 | #include "SkTArray.h" |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 16 | |
bsalomon@google.com | d698f77 | 2012-10-25 13:22:00 +0000 | [diff] [blame] | 17 | class GrGLEffect; |
twiz@google.com | a5e65ec | 2012-08-02 15:15:16 +0000 | [diff] [blame] | 18 | class GrGLCaps; |
bsalomon@google.com | c781888 | 2013-03-20 19:19:53 +0000 | [diff] [blame] | 19 | class GrDrawEffect; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 20 | |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 21 | /** |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 22 | * Used by effects to build their keys. It incorporates each per-effect key into a larger shader key. |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 23 | */ |
| 24 | class GrEffectKeyBuilder { |
| 25 | public: |
| 26 | GrEffectKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) { |
| 27 | SkASSERT(0 == fData->count() % sizeof(uint32_t)); |
| 28 | } |
| 29 | |
| 30 | void add32(uint32_t v) { |
| 31 | ++fCount; |
| 32 | fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v)); |
| 33 | } |
| 34 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 35 | /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next |
| 36 | add*() call. */ |
| 37 | uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) { |
| 38 | SkASSERT(count > 0); |
| 39 | fCount += count; |
| 40 | return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count)); |
| 41 | } |
| 42 | |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 43 | size_t size() const { return sizeof(uint32_t) * fCount; } |
| 44 | |
| 45 | private: |
| 46 | SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key. |
| 47 | int fCount; // number of uint32_ts added to fData by the effect. |
| 48 | }; |
| 49 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 50 | /** |
bsalomon | 63e99f7 | 2014-07-21 08:03:14 -0700 | [diff] [blame^] | 51 | * This class is used to pass the key that was created for a GrGLEffect back to it |
| 52 | * when it emits code. It may allow the emit step to skip calculations that were |
| 53 | * performed when computing the key. |
| 54 | */ |
| 55 | class GrEffectKey { |
| 56 | public: |
| 57 | GrEffectKey(const uint32_t* key, int count) : fKey(key), fCount(count) { |
| 58 | SkASSERT(0 == reinterpret_cast<intptr_t>(key) % sizeof(uint32_t)); |
| 59 | } |
| 60 | |
| 61 | /** Gets the uint32_t values that the effect inserted into the key. */ |
| 62 | uint32_t get32(int index) const { |
| 63 | SkASSERT(index >=0 && index < fCount); |
| 64 | return fKey[index]; |
| 65 | } |
| 66 | |
| 67 | /** Gets the number of uint32_t values that the effect inserted into the key. */ |
| 68 | int count32() const { return fCount; } |
| 69 | |
| 70 | private: |
| 71 | const uint32_t* fKey; // unowned ptr into the larger key. |
| 72 | int fCount; // number of uint32_ts inserted by the effect into its key. |
| 73 | }; |
| 74 | |
| 75 | /** |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 76 | * Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific |
| 77 | * effect object. It also tracks equivalence of shaders generated via a key. The factory for an |
| 78 | * effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at |
| 79 | * construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect |
| 80 | * subclass must always return the same object from getFactory() and that factory object must be |
| 81 | * unique to the GrEffect subclass (and unique from any further derived subclasses). |
| 82 | * |
| 83 | * Rather than subclassing this class themselves, it is recommended that GrEffect authors use |
| 84 | * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as: |
| 85 | * |
| 86 | * const GrBackendEffectFactory& MyEffect::getFactory() const { |
| 87 | * return GrTBackendEffectFactory<MyEffect>::getInstance(); |
| 88 | * } |
| 89 | * |
| 90 | * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments. |
| 91 | */ |
commit-bot@chromium.org | e3beb6b | 2014-04-07 19:34:38 +0000 | [diff] [blame] | 92 | class GrBackendEffectFactory : SkNoncopyable { |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 93 | public: |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 94 | /** |
| 95 | * Generates an effect's key. The key is based on the aspects of the GrEffect object's |
| 96 | * configuration that affect GLSL code generation. Two GrEffect instances that would cause |
| 97 | * this->createGLInstance()->emitCode() to produce different code must produce different keys. |
| 98 | */ |
| 99 | virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0; |
| 100 | |
| 101 | /** |
| 102 | * Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL |
| 103 | * program and to manage updating uniforms for the program when it is used. |
| 104 | */ |
bsalomon@google.com | c781888 | 2013-03-20 19:19:53 +0000 | [diff] [blame] | 105 | virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 106 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 107 | /** |
| 108 | * Produces a human-reable name for the effect. |
| 109 | */ |
bsalomon@google.com | 289efe0 | 2012-05-21 20:57:59 +0000 | [diff] [blame] | 110 | virtual const char* name() const = 0; |
| 111 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 112 | /** |
| 113 | * A unique value for every instance of this factory. It is automatically incorporated into the |
| 114 | * effect's key. This allows keys generated by getGLEffectKey() to only be unique within a |
| 115 | * GrEffect subclass and not necessarily across subclasses. |
| 116 | */ |
| 117 | uint32_t effectClassID() const { return fEffectClassID; } |
| 118 | |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 119 | protected: |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 120 | GrBackendEffectFactory() : fEffectClassID(GenID()) {} |
| 121 | virtual ~GrBackendEffectFactory() {} |
| 122 | |
| 123 | private: |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 124 | enum { |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 125 | kIllegalEffectClassID = 0, |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 126 | }; |
| 127 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 128 | static uint32_t GenID() { |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 129 | // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 130 | // atomic inc returns the old value not the incremented value. So we add |
| 131 | // 1 to the returned value. |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 132 | uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1; |
| 133 | if (!id) { |
| 134 | SkFAIL("This should never wrap as it should only be called once for each GrEffect " |
| 135 | "subclass."); |
| 136 | } |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 137 | return id; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 138 | } |
| 139 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 140 | const uint32_t fEffectClassID; |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 141 | static int32_t fCurrEffectClassID; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 142 | }; |
| 143 | |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 144 | #endif |