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 | /** |
| 51 | * Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific |
| 52 | * effect object. It also tracks equivalence of shaders generated via a key. The factory for an |
| 53 | * effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at |
| 54 | * construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect |
| 55 | * subclass must always return the same object from getFactory() and that factory object must be |
| 56 | * unique to the GrEffect subclass (and unique from any further derived subclasses). |
| 57 | * |
| 58 | * Rather than subclassing this class themselves, it is recommended that GrEffect authors use |
| 59 | * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as: |
| 60 | * |
| 61 | * const GrBackendEffectFactory& MyEffect::getFactory() const { |
| 62 | * return GrTBackendEffectFactory<MyEffect>::getInstance(); |
| 63 | * } |
| 64 | * |
| 65 | * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments. |
| 66 | */ |
commit-bot@chromium.org | e3beb6b | 2014-04-07 19:34:38 +0000 | [diff] [blame] | 67 | class GrBackendEffectFactory : SkNoncopyable { |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 68 | public: |
bsalomon@google.com | 46fba0d | 2012-10-25 21:42:05 +0000 | [diff] [blame] | 69 | typedef uint32_t EffectKey; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 70 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 71 | /** |
| 72 | * Generates an effect's key. The key is based on the aspects of the GrEffect object's |
| 73 | * configuration that affect GLSL code generation. Two GrEffect instances that would cause |
| 74 | * this->createGLInstance()->emitCode() to produce different code must produce different keys. |
| 75 | */ |
| 76 | virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0; |
| 77 | |
| 78 | /** |
| 79 | * Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL |
| 80 | * program and to manage updating uniforms for the program when it is used. |
| 81 | */ |
bsalomon@google.com | c781888 | 2013-03-20 19:19:53 +0000 | [diff] [blame] | 82 | virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 83 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 84 | /** |
| 85 | * Produces a human-reable name for the effect. |
| 86 | */ |
bsalomon@google.com | 289efe0 | 2012-05-21 20:57:59 +0000 | [diff] [blame] | 87 | virtual const char* name() const = 0; |
| 88 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 89 | /** |
| 90 | * A unique value for every instance of this factory. It is automatically incorporated into the |
| 91 | * effect's key. This allows keys generated by getGLEffectKey() to only be unique within a |
| 92 | * GrEffect subclass and not necessarily across subclasses. |
| 93 | */ |
| 94 | uint32_t effectClassID() const { return fEffectClassID; } |
| 95 | |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 96 | protected: |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 97 | GrBackendEffectFactory() : fEffectClassID(GenID()) {} |
| 98 | virtual ~GrBackendEffectFactory() {} |
| 99 | |
| 100 | private: |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 101 | enum { |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 102 | kIllegalEffectClassID = 0, |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 103 | }; |
| 104 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 105 | static uint32_t GenID() { |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 106 | // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 107 | // atomic inc returns the old value not the incremented value. So we add |
| 108 | // 1 to the returned value. |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 109 | uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1; |
| 110 | if (!id) { |
| 111 | SkFAIL("This should never wrap as it should only be called once for each GrEffect " |
| 112 | "subclass."); |
| 113 | } |
bsalomon | 848faf0 | 2014-07-11 10:01:02 -0700 | [diff] [blame] | 114 | return id; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 115 | } |
| 116 | |
bsalomon | 929f29a | 2014-07-17 07:55:11 -0700 | [diff] [blame] | 117 | const uint32_t fEffectClassID; |
bsalomon@google.com | 021fc73 | 2012-10-25 12:47:42 +0000 | [diff] [blame] | 118 | static int32_t fCurrEffectClassID; |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 119 | }; |
| 120 | |
bsalomon@google.com | ae4f96a | 2012-05-18 19:54:48 +0000 | [diff] [blame] | 121 | #endif |