michael@0: /* michael@0: * Copyright 2012 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 GrFakeRefObj_DEFINED michael@0: #define GrFakeRefObj_DEFINED michael@0: michael@0: #include "SkTypes.h" michael@0: #include "gl/GrGLInterface.h" michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // This object is used to track the OpenGL objects. We don't use real michael@0: // reference counting (i.e., we don't free the objects when their ref count michael@0: // goes to 0) so that we can detect invalid memory accesses. The refs we michael@0: // are tracking in this class are actually OpenGL's references to the objects michael@0: // not "ours" michael@0: // Each object also gets a unique globally identifying ID michael@0: class GrFakeRefObj : public SkNoncopyable { michael@0: public: michael@0: GrFakeRefObj() michael@0: : fRef(0) michael@0: , fHighRefCount(0) michael@0: , fMarkedForDeletion(false) michael@0: , fDeleted(false) { michael@0: michael@0: // source for globally unique IDs - 0 is reserved! michael@0: static int fNextID = 0; michael@0: michael@0: fID = ++fNextID; michael@0: } michael@0: virtual ~GrFakeRefObj() {}; michael@0: michael@0: void ref() { michael@0: fRef++; michael@0: if (fHighRefCount < fRef) { michael@0: fHighRefCount = fRef; michael@0: } michael@0: } michael@0: void unref() { michael@0: fRef--; michael@0: GrAlwaysAssert(fRef >= 0); michael@0: michael@0: // often in OpenGL a given object may still be in use when the michael@0: // delete call is made. In these cases the object is marked michael@0: // for deletion and then freed when it is no longer in use michael@0: if (0 == fRef && fMarkedForDeletion) { michael@0: this->deleteAction(); michael@0: } michael@0: } michael@0: int getRefCount() const { return fRef; } michael@0: int getHighRefCount() const { return fHighRefCount; } michael@0: michael@0: GrGLuint getID() const { return fID; } michael@0: michael@0: void setMarkedForDeletion() { fMarkedForDeletion = true; } michael@0: bool getMarkedForDeletion() const { return fMarkedForDeletion; } michael@0: michael@0: bool getDeleted() const { return fDeleted; } michael@0: michael@0: // The deleteAction fires if the object has been marked for deletion but michael@0: // couldn't be deleted earlier due to refs michael@0: virtual void deleteAction() { michael@0: this->setDeleted(); michael@0: } michael@0: michael@0: protected: michael@0: private: michael@0: int fRef; // ref count michael@0: int fHighRefCount; // high water mark of the ref count michael@0: GrGLuint fID; // globally unique ID michael@0: bool fMarkedForDeletion; michael@0: // The deleted flag is only set when OpenGL thinks the object is deleted michael@0: // It is obviously still allocated w/in this framework michael@0: bool fDeleted; michael@0: michael@0: // setDeleted should only ever appear in the deleteAction method! michael@0: void setDeleted() { fDeleted = true; } michael@0: }; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // Each class derived from GrFakeRefObj should use this macro to add a michael@0: // factory creation entry point. This entry point is used by the GrGLDebug michael@0: // object to instantiate the various objects michael@0: // all globally unique IDs michael@0: #define GR_DEFINE_CREATOR(className) \ michael@0: public: \ michael@0: static GrFakeRefObj *create ## className() { \ michael@0: return SkNEW(className); \ michael@0: } michael@0: michael@0: #endif // GrFakeRefObj_DEFINED