michael@0: /* michael@0: * Copyright 2011 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrResource_DEFINED michael@0: #define GrResource_DEFINED michael@0: michael@0: #include "SkRefCnt.h" michael@0: #include "SkTInternalLList.h" michael@0: michael@0: class GrGpu; michael@0: class GrContext; michael@0: class GrResourceEntry; michael@0: michael@0: /** michael@0: * Base class for the GPU resources created by a GrContext. michael@0: */ michael@0: class GrResource : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(GrResource) michael@0: michael@0: /** michael@0: * Frees the resource in the underlying 3D API. It must be safe to call this michael@0: * when the resource has been previously abandoned. michael@0: */ michael@0: void release(); michael@0: michael@0: /** michael@0: * Removes references to objects in the underlying 3D API without freeing michael@0: * them. Used when the API context has been torn down before the GrContext. michael@0: */ michael@0: void abandon(); michael@0: michael@0: /** michael@0: * Tests whether a resource has been abandoned or released. All resources michael@0: * will be in this state after their creating GrContext is destroyed or has michael@0: * contextLost called. It's up to the client to test isValid() before michael@0: * attempting to use a resource if it holds refs on resources across michael@0: * ~GrContext, freeResources with the force flag, or contextLost. michael@0: * michael@0: * @return true if the resource has been released or abandoned, michael@0: * false otherwise. michael@0: */ michael@0: bool isValid() const { return NULL != fGpu; } michael@0: michael@0: /** michael@0: * Retrieves the size of the object in GPU memory. This is approximate since michael@0: * we aren't aware of additional padding or copies made by the driver. michael@0: * michael@0: * @return the size of the buffer in bytes michael@0: */ michael@0: virtual size_t sizeInBytes() const = 0; michael@0: michael@0: /** michael@0: * Retrieves the context that owns the resource. Note that it is possible michael@0: * for this to return NULL. When resources have been release()ed or michael@0: * abandon()ed they no longer have an owning context. Destroying a michael@0: * GrContext automatically releases all its resources. michael@0: */ michael@0: const GrContext* getContext() const; michael@0: GrContext* getContext(); michael@0: michael@0: void setCacheEntry(GrResourceEntry* cacheEntry) { fCacheEntry = cacheEntry; } michael@0: GrResourceEntry* getCacheEntry() { return fCacheEntry; } michael@0: michael@0: void incDeferredRefCount() const { michael@0: SkASSERT(fDeferredRefCount >= 0); michael@0: ++fDeferredRefCount; michael@0: } michael@0: michael@0: void decDeferredRefCount() const { michael@0: SkASSERT(fDeferredRefCount > 0); michael@0: --fDeferredRefCount; michael@0: if (0 == fDeferredRefCount && this->needsDeferredUnref()) { michael@0: SkASSERT(this->getRefCnt() > 1); michael@0: this->unref(); michael@0: } michael@0: } michael@0: michael@0: int getDeferredRefCount() const { return fDeferredRefCount; } michael@0: michael@0: void setNeedsDeferredUnref() { fFlags |= kDeferredUnref_FlagBit; } michael@0: michael@0: protected: michael@0: /** michael@0: * isWrapped indicates we have wrapped a client-created backend resource in a GrResource. If it michael@0: * is true then the client is responsible for the lifetime of the underlying backend resource. michael@0: * Otherwise, our onRelease() should free the resource. michael@0: */ michael@0: GrResource(GrGpu* gpu, bool isWrapped); michael@0: virtual ~GrResource(); michael@0: michael@0: GrGpu* getGpu() const { return fGpu; } michael@0: michael@0: // Derived classes should always call their parent class' onRelease michael@0: // and onAbandon methods in their overrides. michael@0: virtual void onRelease() {}; michael@0: virtual void onAbandon() {}; michael@0: michael@0: bool isInCache() const { return NULL != fCacheEntry; } michael@0: bool isWrapped() const { return kWrapped_FlagBit & fFlags; } michael@0: bool needsDeferredUnref() const { return SkToBool(kDeferredUnref_FlagBit & fFlags); } michael@0: michael@0: private: michael@0: #ifdef SK_DEBUG michael@0: friend class GrGpu; // for assert in GrGpu to access getGpu michael@0: #endif michael@0: michael@0: // We're in an internal doubly linked list michael@0: SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrResource); michael@0: michael@0: GrGpu* fGpu; // not reffed. The GrGpu can be deleted while there michael@0: // are still live GrResources. It will call michael@0: // release() on all such resources in its michael@0: // destructor. michael@0: GrResourceEntry* fCacheEntry; // NULL if not in cache michael@0: mutable int fDeferredRefCount; // How many references in deferred drawing buffers. michael@0: michael@0: enum Flags { michael@0: /** michael@0: * This resource wraps a GPU resource given to us by the user. michael@0: * Lifetime management is left up to the user (i.e., we will not michael@0: * free it). michael@0: */ michael@0: kWrapped_FlagBit = 0x1, michael@0: michael@0: /** michael@0: * This texture should be de-refed when the deferred ref count goes michael@0: * to zero. A resource gets into this state when the resource cache michael@0: * is holding a ref-of-obligation (i.e., someone needs to own it but michael@0: * no one else wants to) but doesn't really want to keep it around. michael@0: */ michael@0: kDeferredUnref_FlagBit = 0x2, michael@0: }; michael@0: uint32_t fFlags; michael@0: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: #endif