GrEffect.h revision d42aca31b9ddc1cb9a81522b4c73a9fe550450bc
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 GrEffect_DEFINED 9#define GrEffect_DEFINED 10 11#include "GrColor.h" 12#include "GrEffectUnitTest.h" 13#include "GrNoncopyable.h" 14#include "GrRefCnt.h" 15#include "GrTexture.h" 16#include "GrTextureAccess.h" 17#include "GrTypesPriv.h" 18 19class GrBackendEffectFactory; 20class GrContext; 21class GrEffect; 22class SkString; 23 24/** 25 * A Wrapper class for GrEffect. Its ref-count will track owners that may use effects to enqueue 26 * new draw operations separately from ownership within a deferred drawing queue. When the 27 * GrEffectRef ref count reaches zero the scratch GrResources owned by the effect can be recycled 28 * in service of later draws. However, the deferred draw queue may still own direct references to 29 * the underlying GrEffect. 30 * 31 * GrEffectRefs created by new are placed in a per-thread managed pool. The pool is destroyed when 32 * the thread ends. Therefore, all dynamically allocated GrEffectRefs must be unreffed before thread 33 * termination. 34 */ 35class GrEffectRef : public SkRefCnt { 36public: 37 SK_DECLARE_INST_COUNT(GrEffectRef); 38 virtual ~GrEffectRef(); 39 40 GrEffect* get() { return fEffect; } 41 const GrEffect* get() const { return fEffect; } 42 43 const GrEffect* operator-> () { return fEffect; } 44 const GrEffect* operator-> () const { return fEffect; } 45 46 void* operator new(size_t size); 47 void operator delete(void* target); 48 49 void* operator new(size_t size, void* placement) { 50 return ::operator new(size, placement); 51 } 52 void operator delete(void* target, void* placement) { 53 ::operator delete(target, placement); 54 } 55 56private: 57 friend class GrEffect; // to construct these 58 59 explicit GrEffectRef(GrEffect* effect); 60 61 GrEffect* fEffect; 62 63 typedef SkRefCnt INHERITED; 64}; 65 66/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the 67 Ganesh shading pipeline. 68 Subclasses must have a function that produces a human-readable name: 69 static const char* Name(); 70 GrEffect objects *must* be immutable: after being constructed, their fields may not change. 71 72 GrEffect subclass objects should be created by factory functions that return GrEffectRef. 73 There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static 74 member function of a GrEffect subclass. 75 76 Because almost no code should ever handle a GrEffect directly outside of a GrEffectRef, we 77 privately inherit from GrRefCnt to help prevent accidental direct ref'ing/unref'ing of effects. 78 79 Dynamically allocated GrEffects and their corresponding GrEffectRefs are managed by a per-thread 80 memory pool. The ref count of an effect must reach 0 before the thread terminates and the pool 81 is destroyed. To create a static effect use the macro GR_CREATE_STATIC_EFFECT declared below. 82 */ 83class GrEffect : private GrRefCnt { 84public: 85 SK_DECLARE_INST_COUNT(GrEffect) 86 87 /** 88 * The types of vertex coordinates available to an effect in the vertex shader. Effects can 89 * require their own vertex attribute but these coordinates are made available by the framework 90 * in all programs. kCustom_CoordsType is provided to signify that an alternative set of coords 91 * is used (usually an explicit vertex attribute) but its meaning is determined by the effect 92 * subclass. 93 */ 94 enum CoordsType { 95 kLocal_CoordsType, 96 kPosition_CoordsType, 97 98 kCustom_CoordsType, 99 }; 100 101 virtual ~GrEffect(); 102 103 /** 104 * This function is used to perform optimizations. When called the color and validFlags params 105 * indicate whether the input components to this effect in the FS will have known values. 106 * validFlags is a bitfield of GrColorComponentFlags. The function updates both params to 107 * indicate known values of its output. A component of the color param only has meaning if the 108 * corresponding bit in validFlags is set. 109 */ 110 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const = 0; 111 112 /** This object, besides creating back-end-specific helper objects, is used for run-time-type- 113 identification. The factory should be an instance of templated class, 114 GrTBackendEffectFactory. It is templated on the subclass of GrEffect. The subclass must have 115 a nested type (or typedef) named GLEffect which will be the subclass of GrGLEffect created 116 by the factory. 117 118 Example: 119 class MyCustomEffect : public GrEffect { 120 ... 121 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 122 return GrTBackendEffectFactory<MyCustomEffect>::getInstance(); 123 } 124 ... 125 }; 126 */ 127 virtual const GrBackendEffectFactory& getFactory() const = 0; 128 129 /** Returns true if this and other effect conservatively draw identically. It can only return 130 true when the two effects are of the same subclass (i.e. they return the same object from 131 from getFactory()). 132 133 A return value of true from isEqual() should not be used to test whether the effects would 134 generate the same shader code. To test for identical code generation use the EffectKey 135 computed by the GrBackendEffectFactory: 136 effectA.getFactory().glEffectKey(effectA) == effectB.getFactory().glEffectKey(effectB). 137 */ 138 bool isEqual(const GrEffectRef& other) const { 139 return this->isEqual(*other.get()); 140 } 141 142 /** Human-meaningful string to identify this effect; may be embedded 143 in generated shader code. */ 144 const char* name() const; 145 146 int numTextures() const { return fTextureAccesses.count(); } 147 148 /** Returns the access pattern for the texture at index. index must be valid according to 149 numTextures(). */ 150 const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; } 151 152 /** Shortcut for textureAccess(index).texture(); */ 153 GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); } 154 155 /** Will this effect read the destination pixel value? */ 156 bool willReadDst() const { return fWillReadDst; } 157 158 int numVertexAttribs() const { return fVertexAttribTypes.count(); } 159 160 GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; } 161 162 static const int kMaxVertexAttribs = 2; 163 164 /** Useful for effects that want to insert a texture matrix that is implied by the texture 165 dimensions */ 166 static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) { 167 GrAssert(NULL != texture); 168 SkMatrix mat; 169 mat.setIDiv(texture->width(), texture->height()); 170 return mat; 171 } 172 173 void* operator new(size_t size); 174 void operator delete(void* target); 175 176 void* operator new(size_t size, void* placement) { 177 return ::operator new(size, placement); 178 } 179 void operator delete(void* target, void* placement) { 180 ::operator delete(target, placement); 181 } 182 183 /** These functions are used when recording effects into a deferred drawing queue. The inc call 184 keeps the effect alive outside of GrEffectRef while allowing any resources owned by the 185 effect to be returned to the cache for reuse. The dec call must balance the inc call. */ 186 void incDeferredRefCounts() const { 187 this->ref(); 188 int count = fTextureAccesses.count(); 189 for (int t = 0; t < count; ++t) { 190 fTextureAccesses[t]->getTexture()->incDeferredRefCount(); 191 } 192 } 193 void decDeferredRefCounts() const { 194 int count = fTextureAccesses.count(); 195 for (int t = 0; t < count; ++t) { 196 fTextureAccesses[t]->getTexture()->decDeferredRefCount(); 197 } 198 this->unref(); 199 } 200 201protected: 202 /** 203 * Subclasses call this from their constructor to register GrTextureAccesses. The effect 204 * subclass manages the lifetime of the accesses (this function only stores a pointer). This 205 * must only be called from the constructor because GrEffects are immutable. 206 */ 207 void addTextureAccess(const GrTextureAccess* textureAccess); 208 209 /** 210 * Subclasses call this from their constructor to register vertex attributes (at most 211 * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are 212 * immutable. 213 */ 214 void addVertexAttrib(GrSLType type); 215 216 GrEffect() : fWillReadDst(false), fEffectRef(NULL) {} 217 218 /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for 219 an example factory function. */ 220 static GrEffectRef* CreateEffectRef(GrEffect* effect) { 221 if (NULL == effect->fEffectRef) { 222 effect->fEffectRef = SkNEW_ARGS(GrEffectRef, (effect)); 223 } else { 224 effect->fEffectRef->ref(); 225 } 226 return effect->fEffectRef; 227 } 228 229 static const GrEffectRef* CreateEffectRef(const GrEffect* effect) { 230 return CreateEffectRef(const_cast<GrEffect*>(effect)); 231 } 232 233 /** Used by GR_CREATE_STATIC_EFFECT below */ 234 static GrEffectRef* CreateStaticEffectRef(void* refStorage, GrEffect* effect) { 235 GrAssert(NULL == effect->fEffectRef); 236 effect->fEffectRef = SkNEW_PLACEMENT_ARGS(refStorage, GrEffectRef, (effect)); 237 return effect->fEffectRef; 238 } 239 240 241 /** Helper used in subclass factory functions to unref the effect after it has been wrapped in a 242 GrEffectRef. E.g.: 243 244 class EffectSubclass : public GrEffect { 245 public: 246 GrEffectRef* Create(ParamType1 param1, ParamType2 param2, ...) { 247 AutoEffectUnref effect(SkNEW_ARGS(EffectSubclass, (param1, param2, ...))); 248 return CreateEffectRef(effect); 249 } 250 */ 251 class AutoEffectUnref { 252 public: 253 AutoEffectUnref(GrEffect* effect) : fEffect(effect) { } 254 ~AutoEffectUnref() { fEffect->unref(); } 255 operator GrEffect*() { return fEffect; } 256 private: 257 GrEffect* fEffect; 258 }; 259 260 /** Helper for getting the GrEffect out of a GrEffectRef and down-casting to a GrEffect subclass 261 */ 262 template <typename T> 263 static const T& CastEffect(const GrEffect& effectRef) { 264 return *static_cast<const T*>(&effectRef); 265 } 266 267 /** 268 * If the effect subclass will read the destination pixel value then it must call this function 269 * from its constructor. Otherwise, when its generated backend-specific effect class attempts 270 * to generate code that reads the destination pixel it will fail. 271 */ 272 void setWillReadDst() { fWillReadDst = true; } 273 274private: 275 bool isEqual(const GrEffect& other) const { 276 if (&this->getFactory() != &other.getFactory()) { 277 return false; 278 } 279 bool result = this->onIsEqual(other); 280#if GR_DEBUG 281 if (result) { 282 GrAssert(this->numTextures() == other.numTextures()); 283 for (int i = 0; i < this->numTextures(); ++i) { 284 GrAssert(*fTextureAccesses[i] == *other.fTextureAccesses[i]); 285 } 286 } 287#endif 288 return result; 289 } 290 291 /** Subclass implements this to support isEqual(). It will only be called if it is known that 292 the two effects are of the same subclass (i.e. they return the same object from 293 getFactory()).*/ 294 virtual bool onIsEqual(const GrEffect& other) const = 0; 295 296 void EffectRefDestroyed() { fEffectRef = NULL; } 297 298 friend class GrEffectRef; // to call EffectRefDestroyed() 299 friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage 300 // from deferred state, to call isEqual on naked GrEffects, and 301 // to inc/dec deferred ref counts. 302 303 SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; 304 SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes; 305 bool fWillReadDst; 306 GrEffectRef* fEffectRef; 307 308 typedef GrRefCnt INHERITED; 309}; 310 311inline GrEffectRef::GrEffectRef(GrEffect* effect) { 312 GrAssert(NULL != effect); 313 effect->ref(); 314 fEffect = effect; 315} 316 317/** 318 * This creates an effect outside of the effect memory pool. The effect's destructor will be called 319 * at global destruction time. NAME will be the name of the created GrEffectRef. 320 */ 321#define GR_CREATE_STATIC_EFFECT(NAME, EFFECT_CLASS, ARGS) \ 322enum { \ 323 k_##NAME##_EffectRefOffset = GR_CT_ALIGN_UP(sizeof(EFFECT_CLASS), 8), \ 324 k_##NAME##_StorageSize = k_##NAME##_EffectRefOffset + sizeof(GrEffectRef) \ 325}; \ 326static SkAlignedSStorage<k_##NAME##_StorageSize> g_##NAME##_Storage; \ 327static void* NAME##_RefLocation = (char*)g_##NAME##_Storage.get() + k_##NAME##_EffectRefOffset; \ 328static GrEffect* NAME##_Effect SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), EFFECT_CLASS, ARGS);\ 329static SkAutoTDestroy<GrEffect> NAME##_ad(NAME##_Effect); \ 330static GrEffectRef* NAME(GrEffect::CreateStaticEffectRef(NAME##_RefLocation, NAME##_Effect)); \ 331static SkAutoTDestroy<GrEffectRef> NAME##_Ref_ad(NAME) 332 333 334#endif 335