From dd743fefad9764ad86d7f69deec32e9a3b5de47f Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Thu, 5 Apr 2012 14:40:53 +0000 Subject: [PATCH] Initial split up of Debug Interface into separate files http://codereview.appspot.com/5979048/ git-svn-id: http://skia.googlecode.com/svn/trunk@3616 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gyp/gpu.gyp | 20 + src/gpu/gl/debug/GrBufferObj.cpp | 9 + src/gpu/gl/debug/GrBufferObj.h | 84 ++ src/gpu/gl/debug/GrDebugGL.cpp | 196 +++++ src/gpu/gl/debug/GrDebugGL.h | 124 +++ src/gpu/gl/debug/GrFBBindableObj.cpp | 9 + src/gpu/gl/debug/GrFBBindableObj.h | 88 ++ src/gpu/gl/debug/GrFakeRefObj.cpp | 9 + src/gpu/gl/debug/GrFakeRefObj.h | 93 +++ src/gpu/gl/debug/GrFrameBufferObj.cpp | 67 ++ src/gpu/gl/debug/GrFrameBufferObj.h | 68 ++ src/gpu/gl/debug/GrGLCreateDebugInterface.cpp | 790 +----------------- src/gpu/gl/debug/GrProgramObj.cpp | 27 + src/gpu/gl/debug/GrProgramObj.h | 43 + src/gpu/gl/debug/GrRenderBufferObj.cpp | 9 + src/gpu/gl/debug/GrRenderBufferObj.h | 40 + src/gpu/gl/debug/GrShaderObj.cpp | 9 + src/gpu/gl/debug/GrShaderObj.h | 38 + src/gpu/gl/debug/GrTextureObj.cpp | 9 + src/gpu/gl/debug/GrTextureObj.h | 60 ++ src/gpu/gl/debug/GrTextureUnitObj.cpp | 32 + src/gpu/gl/debug/GrTextureUnitObj.h | 45 + 22 files changed, 1087 insertions(+), 782 deletions(-) create mode 100644 src/gpu/gl/debug/GrBufferObj.cpp create mode 100644 src/gpu/gl/debug/GrBufferObj.h create mode 100644 src/gpu/gl/debug/GrDebugGL.cpp create mode 100644 src/gpu/gl/debug/GrDebugGL.h create mode 100644 src/gpu/gl/debug/GrFBBindableObj.cpp create mode 100644 src/gpu/gl/debug/GrFBBindableObj.h create mode 100644 src/gpu/gl/debug/GrFakeRefObj.cpp create mode 100644 src/gpu/gl/debug/GrFakeRefObj.h create mode 100644 src/gpu/gl/debug/GrFrameBufferObj.cpp create mode 100644 src/gpu/gl/debug/GrFrameBufferObj.h create mode 100644 src/gpu/gl/debug/GrProgramObj.cpp create mode 100644 src/gpu/gl/debug/GrProgramObj.h create mode 100644 src/gpu/gl/debug/GrRenderBufferObj.cpp create mode 100644 src/gpu/gl/debug/GrRenderBufferObj.h create mode 100644 src/gpu/gl/debug/GrShaderObj.cpp create mode 100644 src/gpu/gl/debug/GrShaderObj.h create mode 100644 src/gpu/gl/debug/GrTextureObj.cpp create mode 100644 src/gpu/gl/debug/GrTextureObj.h create mode 100644 src/gpu/gl/debug/GrTextureUnitObj.cpp create mode 100644 src/gpu/gl/debug/GrTextureUnitObj.h diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp index 7f7b566c49..df8fb7bba8 100644 --- a/gyp/gpu.gyp +++ b/gyp/gpu.gyp @@ -301,6 +301,26 @@ '../src/gpu/gl/GrGpuGLShaders.h', '../src/gpu/gl/debug/GrGLCreateDebugInterface.cpp', + '../src/gpu/gl/debug/GrFakeRefObj.h', + '../src/gpu/gl/debug/GrFakeRefObj.cpp', + '../src/gpu/gl/debug/GrBufferObj.h', + '../src/gpu/gl/debug/GrBufferObj.cpp', + '../src/gpu/gl/debug/GrFBBindableObj.h', + '../src/gpu/gl/debug/GrFBBindableObj.cpp', + '../src/gpu/gl/debug/GrRenderBufferObj.h', + '../src/gpu/gl/debug/GrRenderBufferObj.cpp', + '../src/gpu/gl/debug/GrTextureObj.h', + '../src/gpu/gl/debug/GrTextureObj.cpp', + '../src/gpu/gl/debug/GrTextureUnitObj.h', + '../src/gpu/gl/debug/GrTextureUnitObj.cpp', + '../src/gpu/gl/debug/GrFrameBufferObj.h', + '../src/gpu/gl/debug/GrFrameBufferObj.cpp', + '../src/gpu/gl/debug/GrShaderObj.h', + '../src/gpu/gl/debug/GrShaderObj.cpp', + '../src/gpu/gl/debug/GrProgramObj.h', + '../src/gpu/gl/debug/GrProgramObj.cpp', + '../src/gpu/gl/debug/GrDebugGL.h', + '../src/gpu/gl/debug/GrDebugGL.cpp', '../src/gpu/gl/mac/GrGLCreateNativeInterface_mac.cpp', diff --git a/src/gpu/gl/debug/GrBufferObj.cpp b/src/gpu/gl/debug/GrBufferObj.cpp new file mode 100644 index 0000000000..0cd4fc8068 --- /dev/null +++ b/src/gpu/gl/debug/GrBufferObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrBufferObj.h" diff --git a/src/gpu/gl/debug/GrBufferObj.h b/src/gpu/gl/debug/GrBufferObj.h new file mode 100644 index 0000000000..e4cfee2a0e --- /dev/null +++ b/src/gpu/gl/debug/GrBufferObj.h @@ -0,0 +1,84 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrBufferObj_DEFINED +#define GrBufferObj_DEFINED + +#include "GrFakeRefObj.h" + +//////////////////////////////////////////////////////////////////////////////// +class GrBufferObj : public GrFakeRefObj { + GR_DEFINE_CREATOR(GrBufferObj); + +public: + GrBufferObj() + : GrFakeRefObj() + , fDataPtr(NULL) + , fMapped(false) + , fBound(false) + , fSize(0) + , fUsage(GR_GL_STATIC_DRAW) { + } + virtual ~GrBufferObj() { + delete[] fDataPtr; + } + + void access() { + // cannot access the buffer if it is currently mapped + GrAlwaysAssert(!fMapped); + } + + void setMapped() { fMapped = true; } + void resetMapped() { fMapped = false; } + bool getMapped() const { return fMapped; } + + void setBound() { fBound = true; } + void resetBound() { fBound = false; } + bool getBound() const { return fBound; } + + void allocate(GrGLint size, const GrGLchar *dataPtr) { + GrAlwaysAssert(size >= 0); + + // delete pre-existing data + delete[] fDataPtr; + + fSize = size; + fDataPtr = new GrGLchar[size]; + if (dataPtr) { + memcpy(fDataPtr, dataPtr, fSize); + } + // TODO: w/ no dataPtr the data is unitialized - this could be tracked + } + GrGLint getSize() const { return fSize; } + GrGLchar *getDataPtr() { return fDataPtr; } + + GrGLint getUsage() const { return fUsage; } + void setUsage(GrGLint usage) { fUsage = usage; } + + virtual void deleteAction() SK_OVERRIDE { + + // buffers are automatically unmapped when deleted + this->resetMapped(); + + this->INHERITED::deleteAction(); + } + + +protected: +private: + + GrGLchar* fDataPtr; + bool fMapped; // is the buffer object mapped via "glMapBuffer"? + bool fBound; // is the buffer object bound via "glBindBuffer"? + GrGLint fSize; // size in bytes + GrGLint fUsage; // one of: GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrBufferObj_DEFINED diff --git a/src/gpu/gl/debug/GrDebugGL.cpp b/src/gpu/gl/debug/GrDebugGL.cpp new file mode 100644 index 0000000000..60971eb270 --- /dev/null +++ b/src/gpu/gl/debug/GrDebugGL.cpp @@ -0,0 +1,196 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrDebugGL.h" +#include "GrTextureObj.h" +#include "GrBufferObj.h" +#include "GrRenderBufferObj.h" +#include "GrFrameBufferObj.h" +#include "GrShaderObj.h" +#include "GrProgramObj.h" +#include "GrTextureUnitObj.h" + + +GrDebugGL GrDebugGL::Obj; +GrDebugGL::Create GrDebugGL::gFactoryFunc[kObjTypeCount] = { + GrTextureObj::createGrTextureObj, + GrBufferObj::createGrBufferObj, + GrRenderBufferObj::createGrRenderBufferObj, + GrFrameBufferObj::createGrFrameBufferObj, + GrShaderObj::createGrShaderObj, + GrProgramObj::createGrProgramObj, + GrTextureUnitObj::createGrTextureUnitObj, +}; + + +GrDebugGL::GrDebugGL() + : fCurTextureUnit(0) + , fArrayBuffer(NULL) + , fElementArrayBuffer(NULL) + , fFrameBuffer(NULL) + , fRenderBuffer(NULL) + , fProgram(NULL) + , fTexture(NULL) { + + for (int i = 0; i < kDefaultMaxTextureUnits; ++i) { + fTextureUnits[i] = GR_CREATE(GrTextureUnitObj, GrDebugGL::kTextureUnit_ObjTypes); + fTextureUnits[i]->ref(); + + fTextureUnits[i]->setNumber(i); + } +} + +GrDebugGL::~GrDebugGL() { + // unref & delete the texture units first so they don't show up on the leak report + for (int i = 0; i < kDefaultMaxTextureUnits; ++i) { + fTextureUnits[i]->unref(); + fTextureUnits[i]->deleteAction(); + } + + this->report(); + + for (int i = 0; i < fObjects.count(); ++i) { + delete fObjects[i]; + } + fObjects.reset(); + + fArrayBuffer = NULL; + fElementArrayBuffer = NULL; + fFrameBuffer = NULL; + fRenderBuffer = NULL; + fProgram = NULL; + fTexture = NULL; +} + +GrFakeRefObj *GrDebugGL::findObject(GrGLuint ID, GrObjTypes type) { + for (int i = 0; i < fObjects.count(); ++i) { + if (fObjects[i]->getID() == ID) { // && fObjects[i]->getType() == type) { + // The application shouldn't be accessing objects + // that (as far as OpenGL knows) were already deleted + GrAlwaysAssert(!fObjects[i]->getDeleted()); + GrAlwaysAssert(!fObjects[i]->getMarkedForDeletion()); + return fObjects[i]; + } + } + + return NULL; +} + +void GrDebugGL::setArrayBuffer(GrBufferObj *arrayBuffer) { + if (fArrayBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fArrayBuffer->getBound()); + fArrayBuffer->resetBound(); + + GrAlwaysAssert(!fArrayBuffer->getDeleted()); + fArrayBuffer->unref(); + } + + fArrayBuffer = arrayBuffer; + + if (fArrayBuffer) { + GrAlwaysAssert(!fArrayBuffer->getDeleted()); + fArrayBuffer->ref(); + + GrAlwaysAssert(!fArrayBuffer->getBound()); + fArrayBuffer->setBound(); + } +} + +void GrDebugGL::setElementArrayBuffer(GrBufferObj *elementArrayBuffer) { + if (fElementArrayBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fElementArrayBuffer->getBound()); + fElementArrayBuffer->resetBound(); + + GrAlwaysAssert(!fElementArrayBuffer->getDeleted()); + fElementArrayBuffer->unref(); + } + + fElementArrayBuffer = elementArrayBuffer; + + if (fElementArrayBuffer) { + GrAlwaysAssert(!fElementArrayBuffer->getDeleted()); + fElementArrayBuffer->ref(); + + GrAlwaysAssert(!fElementArrayBuffer->getBound()); + fElementArrayBuffer->setBound(); + } +} + +void GrDebugGL::setTexture(GrTextureObj *texture) { + fTextureUnits[fCurTextureUnit]->setTexture(texture); +} + +void GrDebugGL::setFrameBuffer(GrFrameBufferObj *frameBuffer) { + if (fFrameBuffer) { + GrAlwaysAssert(fFrameBuffer->getBound()); + fFrameBuffer->resetBound(); + + GrAlwaysAssert(!fFrameBuffer->getDeleted()); + fFrameBuffer->unref(); + } + + fFrameBuffer = frameBuffer; + + if (fFrameBuffer) { + GrAlwaysAssert(!fFrameBuffer->getDeleted()); + fFrameBuffer->ref(); + + GrAlwaysAssert(!fFrameBuffer->getBound()); + fFrameBuffer->setBound(); + } +} + +void GrDebugGL::setRenderBuffer(GrRenderBufferObj *renderBuffer) { + if (fRenderBuffer) { + GrAlwaysAssert(fRenderBuffer->getBound()); + fRenderBuffer->resetBound(); + + GrAlwaysAssert(!fRenderBuffer->getDeleted()); + fRenderBuffer->unref(); + } + + fRenderBuffer = renderBuffer; + + if (fRenderBuffer) { + GrAlwaysAssert(!fRenderBuffer->getDeleted()); + fRenderBuffer->ref(); + + GrAlwaysAssert(!fRenderBuffer->getBound()); + fRenderBuffer->setBound(); + } +} + +void GrDebugGL::useProgram(GrProgramObj *program) { + if (fProgram) { + GrAlwaysAssert(fProgram->getInUse()); + fProgram->resetInUse(); + + GrAlwaysAssert(!fProgram->getDeleted()); + fProgram->unref(); + } + + fProgram = program; + + if (fProgram) { + GrAlwaysAssert(!fProgram->getDeleted()); + fProgram->ref(); + + GrAlwaysAssert(!fProgram->getInUse()); + fProgram->setInUse(); + } +} + +void GrDebugGL::report() const { + for (int i = 0; i < fObjects.count(); ++i) { + GrAlwaysAssert(0 == fObjects[i]->getRefCount()); + GrAlwaysAssert(0 < fObjects[i]->getHighRefCount()); + GrAlwaysAssert(fObjects[i]->getDeleted()); + } +} diff --git a/src/gpu/gl/debug/GrDebugGL.h b/src/gpu/gl/debug/GrDebugGL.h new file mode 100644 index 0000000000..d6af98ecad --- /dev/null +++ b/src/gpu/gl/debug/GrDebugGL.h @@ -0,0 +1,124 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrDebugGL_DEFINED +#define GrDebugGL_DEFINED + +#include "SkTArray.h" +#include "gl/GrGLInterface.h" + +class GrFakeRefObj; +class GrTextureUnitObj; +class GrBufferObj; +class GrTextureObj; +class GrFrameBufferObj; +class GrRenderBufferObj; +class GrProgramObj; + +//////////////////////////////////////////////////////////////////////////////// +// This is the main debugging object. It is a singleton and keeps track of +// all the other debug objects. +class GrDebugGL { +public: + enum GrObjTypes { + kTexture_ObjTypes = 0, + kBuffer_ObjTypes, + kRenderBuffer_ObjTypes, + kFrameBuffer_ObjTypes, + kShader_ObjTypes, + kProgram_ObjTypes, + kTextureUnit_ObjTypes, + kObjTypeCount + }; + + GrFakeRefObj *createObj(GrObjTypes type) { + GrFakeRefObj *temp = (*gFactoryFunc[type])(); + + fObjects.push_back(temp); + + return temp; + } + + GrFakeRefObj *findObject(GrGLuint ID, GrObjTypes type); + + GrGLuint getMaxTextureUnits() const { return kDefaultMaxTextureUnits; } + + void setCurTextureUnit(GrGLuint curTextureUnit) { fCurTextureUnit = curTextureUnit; } + GrGLuint getCurTextureUnit() const { return fCurTextureUnit; } + + GrTextureUnitObj *getTextureUnit(int iUnit) { + GrAlwaysAssert(0 <= iUnit && kDefaultMaxTextureUnits > iUnit); + + return fTextureUnits[iUnit]; + } + + void setArrayBuffer(GrBufferObj *arrayBuffer); + GrBufferObj *getArrayBuffer() { return fArrayBuffer; } + + void setElementArrayBuffer(GrBufferObj *elementArrayBuffer); + GrBufferObj *getElementArrayBuffer() { return fElementArrayBuffer; } + + void setTexture(GrTextureObj *texture); + + void setFrameBuffer(GrFrameBufferObj *frameBuffer); + GrFrameBufferObj *getFrameBuffer() { return fFrameBuffer; } + + void setRenderBuffer(GrRenderBufferObj *renderBuffer); + GrRenderBufferObj *getRenderBuffer() { return fRenderBuffer; } + + void useProgram(GrProgramObj *program); + + static GrDebugGL *getInstance() { +// static GrDebugGL Obj; + + return &Obj; + } + + void report() const; + +protected: + +private: + // the OpenGLES 2.0 spec says this must be >= 2 + static const GrGLint kDefaultMaxTextureUnits = 8; + + GrGLuint fMaxTextureUnits; + GrGLuint fCurTextureUnit; + GrBufferObj * fArrayBuffer; + GrBufferObj * fElementArrayBuffer; + GrFrameBufferObj *fFrameBuffer; + GrRenderBufferObj *fRenderBuffer; + GrProgramObj * fProgram; + GrTextureObj * fTexture; + GrTextureUnitObj *fTextureUnits[kDefaultMaxTextureUnits]; + + typedef GrFakeRefObj *(*Create)(); + + static Create gFactoryFunc[kObjTypeCount]; + + static GrDebugGL Obj; + + // global store of all objects + SkTArray fObjects; + + GrDebugGL(); + ~GrDebugGL(); +}; + +//////////////////////////////////////////////////////////////////////////////// +// Helper macro to make creating an object (where you need to get back a derived +// type) easier +#define GR_CREATE(className, classEnum) \ + reinterpret_cast(GrDebugGL::getInstance()->createObj(classEnum)) + +//////////////////////////////////////////////////////////////////////////////// +// Helper macro to make finding objects less painful +#define GR_FIND(id, className, classEnum) \ + reinterpret_cast(GrDebugGL::getInstance()->findObject(id, classEnum)) + +#endif // GrDebugGL_DEFINED diff --git a/src/gpu/gl/debug/GrFBBindableObj.cpp b/src/gpu/gl/debug/GrFBBindableObj.cpp new file mode 100644 index 0000000000..dbab2d7397 --- /dev/null +++ b/src/gpu/gl/debug/GrFBBindableObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrFBBindableObj.h" \ No newline at end of file diff --git a/src/gpu/gl/debug/GrFBBindableObj.h b/src/gpu/gl/debug/GrFBBindableObj.h new file mode 100644 index 0000000000..38c86380a2 --- /dev/null +++ b/src/gpu/gl/debug/GrFBBindableObj.h @@ -0,0 +1,88 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrFBBindableObj_DEFINED +#define GrFBBindableObj_DEFINED + +#include "SkTDArray.h" +#include "GrFakeRefObj.h" + +//////////////////////////////////////////////////////////////////////////////// +// A common base class for render buffers and textures +class GrFBBindableObj : public GrFakeRefObj { + +public: + GrFBBindableObj() + : GrFakeRefObj() { + } + + virtual ~GrFBBindableObj() { + GrAlwaysAssert(0 == fColorReferees.count()); + GrAlwaysAssert(0 == fDepthReferees.count()); + GrAlwaysAssert(0 == fStencilReferees.count()); + } + + void setColorBound(GrFakeRefObj *referee) { + fColorReferees.append(1, &referee); + } + void resetColorBound(GrFakeRefObj *referee) { + int index = fColorReferees.find(referee); + GrAlwaysAssert(0 <= index); + fColorReferees.removeShuffle(index); + } + bool getColorBound(GrFakeRefObj *referee) const { + int index = fColorReferees.find(referee); + return 0 <= index; + } + bool getColorBound() const { + return 0 != fColorReferees.count(); + } + + void setDepthBound(GrFakeRefObj *referee) { + fDepthReferees.append(1, &referee); + } + void resetDepthBound(GrFakeRefObj *referee) { + int index = fDepthReferees.find(referee); + GrAlwaysAssert(0 <= index); + fDepthReferees.removeShuffle(index); + } + bool getDepthBound(GrFakeRefObj *referee) const { + int index = fDepthReferees.find(referee); + return 0 <= index; + } + bool getDepthBound() const { + return 0 != fDepthReferees.count(); + } + + void setStencilBound(GrFakeRefObj *referee) { + fStencilReferees.append(1, &referee); + } + void resetStencilBound(GrFakeRefObj *referee) { + int index = fStencilReferees.find(referee); + GrAlwaysAssert(0 <= index); + fStencilReferees.removeShuffle(index); + } + bool getStencilBound(GrFakeRefObj *referee) const { + int index = fStencilReferees.find(referee); + return 0 <= index; + } + bool getStencilBound() const { + return 0 != fStencilReferees.count(); + } + + +protected: +private: + SkTDArray fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") + SkTDArray fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") + SkTDArray fStencilReferees; // frame buffers that use this as a stencil buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrFBBindableObj_DEFINED diff --git a/src/gpu/gl/debug/GrFakeRefObj.cpp b/src/gpu/gl/debug/GrFakeRefObj.cpp new file mode 100644 index 0000000000..508f5c34ae --- /dev/null +++ b/src/gpu/gl/debug/GrFakeRefObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrFakeRefObj.h" \ No newline at end of file diff --git a/src/gpu/gl/debug/GrFakeRefObj.h b/src/gpu/gl/debug/GrFakeRefObj.h new file mode 100644 index 0000000000..8dbef9cb59 --- /dev/null +++ b/src/gpu/gl/debug/GrFakeRefObj.h @@ -0,0 +1,93 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrFakeRefObj_DEFINED +#define GrFakeRefObj_DEFINED + +#include "gl/GrGLInterface.h" + +//////////////////////////////////////////////////////////////////////////////// +// This object is used to track the OpenGL objects. We don't use real +// reference counting (i.e., we don't free the objects when their ref count +// goes to 0) so that we can detect invalid memory accesses. The refs we +// are tracking in this class are actually OpenGL's references to the objects +// not "ours" +// Each object also gets a unique globally identifying ID +class GrFakeRefObj { +public: + GrFakeRefObj() + : fRef(0) + , fHighRefCount(0) + , fMarkedForDeletion(false) + , fDeleted(false) { + + static int fNextID = 0; // source for globally unique IDs - 0 is reserved! + + fID = ++fNextID; + } + virtual ~GrFakeRefObj() {}; + + void ref() { + fRef++; + if (fHighRefCount < fRef) { + fHighRefCount = fRef; + } + } + void unref() { + fRef--; + GrAlwaysAssert(fRef >= 0); + + // often in OpenGL a given object may still be in use when the + // delete call is made. In these cases the object is marked + // for deletion and then freed when it is no longer in use + if (0 == fRef && fMarkedForDeletion) { + this->deleteAction(); + } + } + int getRefCount() const { return fRef; } + int getHighRefCount() const { return fHighRefCount; } + + GrGLuint getID() const { return fID; } + + void setMarkedForDeletion() { fMarkedForDeletion = true; } + bool getMarkedForDeletion() const { return fMarkedForDeletion; } + + bool getDeleted() const { return fDeleted; } + + // The deleteAction fires if the object has been marked for deletion but + // couldn't be deleted earlier due to refs + virtual void deleteAction() { + this->setDeleted(); + } + +protected: +private: + int fRef; + int fHighRefCount; // high water mark of the ref count + GrGLuint fID; + bool fMarkedForDeletion; + // The deleted flag is only set when OpenGL thinks the object is deleted + // It is obviously still allocated w/in this framework + bool fDeleted; + + // setDeleted should only ever appear in the deleteAction method! + void setDeleted() { fDeleted = true; } +}; + +//////////////////////////////////////////////////////////////////////////////// +// Each class derived from GrFakeRefObj should use this macro to add a +// factory creation entry point. This entry point is used by the GrGLDebug +// object to instantiate the various objects +// all globally unique IDs +#define GR_DEFINE_CREATOR(className) \ + public: \ + static GrFakeRefObj *create ## className() { \ + return SkNEW(className); \ + } + +#endif // GrFakeRefObj_DEFINED diff --git a/src/gpu/gl/debug/GrFrameBufferObj.cpp b/src/gpu/gl/debug/GrFrameBufferObj.cpp new file mode 100644 index 0000000000..331be8a702 --- /dev/null +++ b/src/gpu/gl/debug/GrFrameBufferObj.cpp @@ -0,0 +1,67 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrFrameBufferObj.h" +#include "GrFBBindableObj.h" + +void GrFrameBufferObj::setColor(GrFBBindableObj *buffer) { + if (fColorBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fColorBuffer->getColorBound(this)); + fColorBuffer->resetColorBound(this); + + GrAlwaysAssert(!fColorBuffer->getDeleted()); + fColorBuffer->unref(); + } + fColorBuffer = buffer; + if (fColorBuffer) { + GrAlwaysAssert(!fColorBuffer->getDeleted()); + fColorBuffer->ref(); + + GrAlwaysAssert(!fColorBuffer->getColorBound(this)); + fColorBuffer->setColorBound(this); + } +} + +void GrFrameBufferObj::setDepth(GrFBBindableObj *buffer) { + if (fDepthBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fDepthBuffer->getDepthBound(this)); + fDepthBuffer->resetDepthBound(this); + + GrAlwaysAssert(!fDepthBuffer->getDeleted()); + fDepthBuffer->unref(); + } + fDepthBuffer = buffer; + if (fDepthBuffer) { + GrAlwaysAssert(!fDepthBuffer->getDeleted()); + fDepthBuffer->ref(); + + GrAlwaysAssert(!fDepthBuffer->getDepthBound(this)); + fDepthBuffer->setDepthBound(this); + } +} + +void GrFrameBufferObj::setStencil(GrFBBindableObj *buffer) { + if (fStencilBuffer) { + // automatically break the binding of the old buffer + GrAlwaysAssert(fStencilBuffer->getStencilBound(this)); + fStencilBuffer->resetStencilBound(this); + + GrAlwaysAssert(!fStencilBuffer->getDeleted()); + fStencilBuffer->unref(); + } + fStencilBuffer = buffer; + if (fStencilBuffer) { + GrAlwaysAssert(!fStencilBuffer->getDeleted()); + fStencilBuffer->ref(); + + GrAlwaysAssert(!fStencilBuffer->getStencilBound(this)); + fStencilBuffer->setStencilBound(this); + } +} \ No newline at end of file diff --git a/src/gpu/gl/debug/GrFrameBufferObj.h b/src/gpu/gl/debug/GrFrameBufferObj.h new file mode 100644 index 0000000000..33af4f7a97 --- /dev/null +++ b/src/gpu/gl/debug/GrFrameBufferObj.h @@ -0,0 +1,68 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrFrameBufferObj_DEFINED +#define GrFrameBufferObj_DEFINED + +#include "GrFakeRefObj.h" +class GrFBBindableObj; + +//////////////////////////////////////////////////////////////////////////////// +// TODO: when a framebuffer obj is bound the GL_SAMPLES query must return 0 +// TODO: GL_STENCIL_BITS must also be redirected to the framebuffer +class GrFrameBufferObj : public GrFakeRefObj { + GR_DEFINE_CREATOR(GrFrameBufferObj); + +public: + GrFrameBufferObj() + : GrFakeRefObj() + , fBound(false) + , fColorBuffer(NULL) + , fDepthBuffer(NULL) + , fStencilBuffer(NULL) { + } + + virtual ~GrFrameBufferObj() { + fColorBuffer = NULL; + fDepthBuffer = NULL; + fStencilBuffer = NULL; + } + + void setBound() { fBound = true; } + void resetBound() { fBound = false; } + bool getBound() const { return fBound; } + + void setColor(GrFBBindableObj *buffer); + GrFBBindableObj *getColor() { return fColorBuffer; } + + void setDepth(GrFBBindableObj *buffer); + GrFBBindableObj *getDepth() { return fDepthBuffer; } + + void setStencil(GrFBBindableObj *buffer); + GrFBBindableObj *getStencil() { return fStencilBuffer; } + + virtual void deleteAction() SK_OVERRIDE { + + setColor(NULL); + setDepth(NULL); + setStencil(NULL); + + this->INHERITED::deleteAction(); + } + +protected: +private: + bool fBound; // is this frame buffer currently bound via "glBindFramebuffer"? + GrFBBindableObj * fColorBuffer; + GrFBBindableObj * fDepthBuffer; + GrFBBindableObj * fStencilBuffer; + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrFrameBufferObj_DEFINED diff --git a/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp b/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp index 5b8c315414..a9adf7d017 100644 --- a/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp +++ b/src/gpu/gl/debug/GrGLCreateDebugInterface.cpp @@ -8,9 +8,14 @@ #include "gl/GrGLInterface.h" - -#include "SkTArray.h" -#include "SkTDArray.h" +#include "GrDebugGL.h" +#include "GrShaderObj.h" +#include "GrProgramObj.h" +#include "GrBufferObj.h" +#include "GrTextureUnitObj.h" +#include "GrTextureObj.h" +#include "GrFrameBufferObj.h" +#include "GrRenderBufferObj.h" // the OpenGLES 2.0 spec says this must be >= 128 static const GrGLint kDefaultMaxVertexUniformVectors = 128; @@ -24,785 +29,6 @@ static const GrGLint kDefaultMaxVertexAttribs = 8; // the OpenGLES 2.0 spec says this must be >= 8 static const GrGLint kDefaultMaxVaryingVectors = 8; -//////////////////////////////////////////////////////////////////////////////// -// Each class derived from GrFakeRefObj should use this macro to add a -// factory creation entry point. This entry point is used by the GrGLDebug -// object to instantiate the various objects -// all globally unique IDs -#define GR_DEFINE_CREATOR(className) \ - public: \ - static GrFakeRefObj *create ## className() { \ - return SkNEW(className); \ - } - -//////////////////////////////////////////////////////////////////////////////// -// Helper macro to make creating an object (where you need to get back a derived -// type) easier -#define GR_CREATE(className, classEnum) \ - reinterpret_cast(GrDebugGL::getInstance()->createObj(classEnum)) - -//////////////////////////////////////////////////////////////////////////////// -// Helper macro to make finding objects less painful -#define GR_FIND(id, className, classEnum) \ - reinterpret_cast(GrDebugGL::getInstance()->findObject(id, classEnum)) - - - -//////////////////////////////////////////////////////////////////////////////// -// This object is used to track the OpenGL objects. We don't use real -// reference counting (i.e., we don't free the objects when their ref count -// goes to 0) so that we can detect invalid memory accesses. The refs we -// are tracking in this class are actually OpenGL's references to the objects -// not "ours" -// Each object also gets a unique globally identifying ID -class GrFakeRefObj { -public: - GrFakeRefObj() - : fRef(0) - , fHighRefCount(0) - , fMarkedForDeletion(false) - , fDeleted(false) { - - static int fNextID = 0; // source for globally unique IDs - 0 is reserved! - - fID = ++fNextID; - } - virtual ~GrFakeRefObj() {}; - - void ref() { - fRef++; - if (fHighRefCount < fRef) { - fHighRefCount = fRef; - } - } - void unref() { - fRef--; - GrAlwaysAssert(fRef >= 0); - - // often in OpenGL a given object may still be in use when the - // delete call is made. In these cases the object is marked - // for deletion and then freed when it is no longer in use - if (0 == fRef && fMarkedForDeletion) { - this->deleteAction(); - } - } - int getRefCount() const { return fRef; } - int getHighRefCount() const { return fHighRefCount; } - - GrGLuint getID() const { return fID; } - - void setMarkedForDeletion() { fMarkedForDeletion = true; } - bool getMarkedForDeletion() const { return fMarkedForDeletion; } - - bool getDeleted() const { return fDeleted; } - - // The deleteAction fires if the object has been marked for deletion but - // couldn't be deleted earlier due to refs - virtual void deleteAction() { - this->setDeleted(); - } - -protected: -private: - int fRef; - int fHighRefCount; // high water mark of the ref count - GrGLuint fID; - bool fMarkedForDeletion; - // The deleted flag is only set when OpenGL thinks the object is deleted - // It is obviously still allocated w/in this framework - bool fDeleted; - - // setDeleted should only ever appear in the deleteAction method! - void setDeleted() { fDeleted = true; } -}; - -//////////////////////////////////////////////////////////////////////////////// -class GrBufferObj : public GrFakeRefObj { - GR_DEFINE_CREATOR(GrBufferObj); - -public: - GrBufferObj() - : GrFakeRefObj() - , fDataPtr(NULL) - , fMapped(false) - , fBound(false) - , fSize(0) - , fUsage(GR_GL_STATIC_DRAW) { - } - virtual ~GrBufferObj() { - delete[] fDataPtr; - } - - void access() { - // cannot access the buffer if it is currently mapped - GrAlwaysAssert(!fMapped); - } - - void setMapped() { fMapped = true; } - void resetMapped() { fMapped = false; } - bool getMapped() const { return fMapped; } - - void setBound() { fBound = true; } - void resetBound() { fBound = false; } - bool getBound() const { return fBound; } - - void allocate(GrGLint size, const GrGLchar *dataPtr) { - GrAlwaysAssert(size >= 0); - - // delete pre-existing data - delete[] fDataPtr; - - fSize = size; - fDataPtr = new GrGLchar[size]; - if (dataPtr) { - memcpy(fDataPtr, dataPtr, fSize); - } - // TODO: w/ no dataPtr the data is unitialized - this could be tracked - } - GrGLint getSize() const { return fSize; } - GrGLchar *getDataPtr() { return fDataPtr; } - - GrGLint getUsage() const { return fUsage; } - void setUsage(GrGLint usage) { fUsage = usage; } - - virtual void deleteAction() SK_OVERRIDE { - - // buffers are automatically unmapped when deleted - this->resetMapped(); - - this->INHERITED::deleteAction(); - } - - -protected: -private: - - GrGLchar* fDataPtr; - bool fMapped; // is the buffer object mapped via "glMapBuffer"? - bool fBound; // is the buffer object bound via "glBindBuffer"? - GrGLint fSize; // size in bytes - GrGLint fUsage; // one of: GL_STREAM_DRAW, GL_STATIC_DRAW, GL_DYNAMIC_DRAW - - typedef GrFakeRefObj INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// -// A common base class for render buffers and textures -class GrFBBindable : public GrFakeRefObj { - -public: - GrFBBindable() - : GrFakeRefObj() { - } - - virtual ~GrFBBindable() { - GrAlwaysAssert(0 == fColorReferees.count()); - GrAlwaysAssert(0 == fDepthReferees.count()); - GrAlwaysAssert(0 == fStencilReferees.count()); - } - - void setColorBound(GrFakeRefObj *referee) { - fColorReferees.append(1, &referee); - } - void resetColorBound(GrFakeRefObj *referee) { - int index = fColorReferees.find(referee); - GrAlwaysAssert(0 <= index); - fColorReferees.removeShuffle(index); - } - bool getColorBound(GrFakeRefObj *referee) const { - int index = fColorReferees.find(referee); - return 0 <= index; - } - bool getColorBound() const { - return 0 != fColorReferees.count(); - } - - void setDepthBound(GrFakeRefObj *referee) { - fDepthReferees.append(1, &referee); - } - void resetDepthBound(GrFakeRefObj *referee) { - int index = fDepthReferees.find(referee); - GrAlwaysAssert(0 <= index); - fDepthReferees.removeShuffle(index); - } - bool getDepthBound(GrFakeRefObj *referee) const { - int index = fDepthReferees.find(referee); - return 0 <= index; - } - bool getDepthBound() const { - return 0 != fDepthReferees.count(); - } - - void setStencilBound(GrFakeRefObj *referee) { - fStencilReferees.append(1, &referee); - } - void resetStencilBound(GrFakeRefObj *referee) { - int index = fStencilReferees.find(referee); - GrAlwaysAssert(0 <= index); - fStencilReferees.removeShuffle(index); - } - bool getStencilBound(GrFakeRefObj *referee) const { - int index = fStencilReferees.find(referee); - return 0 <= index; - } - bool getStencilBound() const { - return 0 != fStencilReferees.count(); - } - - -protected: -private: - SkTDArray fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") - SkTDArray fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") - SkTDArray fStencilReferees; // frame buffers that use this as a stencil buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D") - - typedef GrFakeRefObj INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// -class GrRenderBufferObj : public GrFBBindable { - GR_DEFINE_CREATOR(GrRenderBufferObj); - -public: - GrRenderBufferObj() - : GrFBBindable() - , fBound(false) { - } - - void setBound() { fBound = true; } - void resetBound() { fBound = false; } - bool getBound() const { return fBound; } - - virtual void deleteAction() SK_OVERRIDE { - - this->INHERITED::deleteAction(); - } - -protected: -private: - bool fBound; // is this render buffer currently bound via "glBindRenderbuffer"? - - typedef GrFBBindable INHERITED; -}; - -class GrTextureUnitObj; - -//////////////////////////////////////////////////////////////////////////////// -class GrTextureObj : public GrFBBindable { - GR_DEFINE_CREATOR(GrTextureObj); - -public: - GrTextureObj() - : GrFBBindable() { - } - - virtual ~GrTextureObj() { - GrAlwaysAssert(0 == fTextureUnitReferees.count()); - } - - void setBound(GrTextureUnitObj *referee) { - fTextureUnitReferees.append(1, &referee); - } - - void resetBound(GrTextureUnitObj *referee) { - int index = fTextureUnitReferees.find(referee); - GrAlwaysAssert(0 <= index); - fTextureUnitReferees.removeShuffle(index); - } - bool getBound(GrTextureUnitObj *referee) const { - int index = fTextureUnitReferees.find(referee); - return 0 <= index; - } - bool getBound() const { - return 0 != fTextureUnitReferees.count(); - } - - virtual void deleteAction() SK_OVERRIDE { - - this->INHERITED::deleteAction(); - } - -protected: - -private: - SkTDArray fTextureUnitReferees; // texture units that bind this texture (via "glBindTexture") - - typedef GrFBBindable INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// -// Although texture unit objects are allocated & deallocated like the other -// GL emulation objects they are derived from GrFakeRefObj to provide some -// uniformity in how the GrDebugGL class manages resources -class GrTextureUnitObj : public GrFakeRefObj { - GR_DEFINE_CREATOR(GrTextureUnitObj); - -public: - GrTextureUnitObj() - : GrFakeRefObj() - , fNumber(0) - , fTexture(NULL) { - } - - void setNumber(GrGLenum number) { - fNumber = number; - } - GrGLenum getNumber() const { return fNumber; } - - void setTexture(GrTextureObj *texture) { - - if (fTexture) { - GrAlwaysAssert(fTexture->getBound(this)); - fTexture->resetBound(this); - - GrAlwaysAssert(!fTexture->getDeleted()); - fTexture->unref(); - } - - fTexture = texture; - - if (fTexture) { - GrAlwaysAssert(!fTexture->getDeleted()); - fTexture->ref(); - - GrAlwaysAssert(!fTexture->getBound(this)); - fTexture->setBound(this); - } - } - - GrTextureObj *getTexture() { return fTexture; } - -protected: -private: - GrGLenum fNumber; - GrTextureObj *fTexture; - - typedef GrFakeRefObj INHERITED; -}; - - -//////////////////////////////////////////////////////////////////////////////// -// TODO: when a framebuffer obj is bound the GL_SAMPLES query must return 0 -// TODO: GL_STENCIL_BITS must also be redirected to the framebuffer -class GrFrameBufferObj : public GrFakeRefObj { - GR_DEFINE_CREATOR(GrFrameBufferObj); - -public: - GrFrameBufferObj() - : GrFakeRefObj() - , fBound(false) - , fColorBuffer(NULL) - , fDepthBuffer(NULL) - , fStencilBuffer(NULL) { - } - - virtual ~GrFrameBufferObj() { - fColorBuffer = NULL; - fDepthBuffer = NULL; - fStencilBuffer = NULL; - } - - void setBound() { fBound = true; } - void resetBound() { fBound = false; } - bool getBound() const { return fBound; } - - void setColor(GrFBBindable *buffer) { - if (fColorBuffer) { - // automatically break the binding of the old buffer - GrAlwaysAssert(fColorBuffer->getColorBound(this)); - fColorBuffer->resetColorBound(this); - - GrAlwaysAssert(!fColorBuffer->getDeleted()); - fColorBuffer->unref(); - } - fColorBuffer = buffer; - if (fColorBuffer) { - GrAlwaysAssert(!fColorBuffer->getDeleted()); - fColorBuffer->ref(); - - GrAlwaysAssert(!fColorBuffer->getColorBound(this)); - fColorBuffer->setColorBound(this); - } - } - GrFBBindable *getColor() { return fColorBuffer; } - - void setDepth(GrFBBindable *buffer) { - if (fDepthBuffer) { - // automatically break the binding of the old buffer - GrAlwaysAssert(fDepthBuffer->getDepthBound(this)); - fDepthBuffer->resetDepthBound(this); - - GrAlwaysAssert(!fDepthBuffer->getDeleted()); - fDepthBuffer->unref(); - } - fDepthBuffer = buffer; - if (fDepthBuffer) { - GrAlwaysAssert(!fDepthBuffer->getDeleted()); - fDepthBuffer->ref(); - - GrAlwaysAssert(!fDepthBuffer->getDepthBound(this)); - fDepthBuffer->setDepthBound(this); - } - } - GrFBBindable *getDepth() { return fDepthBuffer; } - - void setStencil(GrFBBindable *buffer) { - if (fStencilBuffer) { - // automatically break the binding of the old buffer - GrAlwaysAssert(fStencilBuffer->getStencilBound(this)); - fStencilBuffer->resetStencilBound(this); - - GrAlwaysAssert(!fStencilBuffer->getDeleted()); - fStencilBuffer->unref(); - } - fStencilBuffer = buffer; - if (fStencilBuffer) { - GrAlwaysAssert(!fStencilBuffer->getDeleted()); - fStencilBuffer->ref(); - - GrAlwaysAssert(!fStencilBuffer->getStencilBound(this)); - fStencilBuffer->setStencilBound(this); - } - } - GrFBBindable *getStencil() { return fStencilBuffer; } - - virtual void deleteAction() SK_OVERRIDE { - - setColor(NULL); - setDepth(NULL); - setStencil(NULL); - - this->INHERITED::deleteAction(); - } - -protected: -private: - bool fBound; // is this frame buffer currently bound via "glBindFramebuffer"? - GrFBBindable * fColorBuffer; - GrFBBindable * fDepthBuffer; - GrFBBindable * fStencilBuffer; - - typedef GrFakeRefObj INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// -class GrShaderObj : public GrFakeRefObj { - GR_DEFINE_CREATOR(GrShaderObj); - -public: - GrShaderObj() - : GrFakeRefObj() - , fType(GR_GL_VERTEX_SHADER) {} - - void setType(GrGLenum type) { fType = type; } - GrGLenum getType() { return fType; } - - virtual void deleteAction() SK_OVERRIDE { - - this->INHERITED::deleteAction(); - } - -protected: -private: - GrGLenum fType; // either GR_GL_VERTEX_SHADER or GR_GL_FRAGMENT_SHADER - - typedef GrFakeRefObj INHERITED; -}; - - -//////////////////////////////////////////////////////////////////////////////// -class GrProgramObj : public GrFakeRefObj { - GR_DEFINE_CREATOR(GrProgramObj); - -public: - GrProgramObj() - : GrFakeRefObj() - , fInUse(false) {} - - void AttachShader(GrShaderObj *shader) { - shader->ref(); - fShaders.push_back(shader); - } - - virtual void deleteAction() SK_OVERRIDE { - - // shaders are automatically detached from a deleted program. They will only be - // deleted if they were marked for deletion by a prior call to glDeleteShader - for (int i = 0; i < fShaders.count(); ++i) { - fShaders[i]->unref(); - } - fShaders.reset(); - - this->INHERITED::deleteAction(); - } - - // TODO: this flag system won't work w/ multiple contexts! - void setInUse() { fInUse = true; } - void resetInUse() { fInUse = false; } - bool getInUse() const { return fInUse; } - -protected: - -private: - SkTArray fShaders; - bool fInUse; // has this program been activated by a glUseProgram call? - - typedef GrFakeRefObj INHERITED; -}; - -//////////////////////////////////////////////////////////////////////////////// -// This is the main debugging object. It is a singleton and keeps track of -// all the other debug objects. -class GrDebugGL { -public: - enum GrObjTypes { - kTexture_ObjTypes = 0, - kBuffer_ObjTypes, - kRenderBuffer_ObjTypes, - kFrameBuffer_ObjTypes, - kShader_ObjTypes, - kProgram_ObjTypes, - kTextureUnit_ObjTypes, - kObjTypeCount - }; - - GrFakeRefObj *createObj(GrObjTypes type) { - GrFakeRefObj *temp = (*gFactoryFunc[type])(); - - fObjects.push_back(temp); - - return temp; - } - - GrFakeRefObj *findObject(GrGLuint ID, GrObjTypes type) { - for (int i = 0; i < fObjects.count(); ++i) { - if (fObjects[i]->getID() == ID) { // && fObjects[i]->getType() == type) { - // The application shouldn't be accessing objects - // that (as far as OpenGL knows) were already deleted - GrAlwaysAssert(!fObjects[i]->getDeleted()); - GrAlwaysAssert(!fObjects[i]->getMarkedForDeletion()); - return fObjects[i]; - } - } - - return NULL; - } - - GrGLuint getMaxTextureUnits() const { return kDefaultMaxTextureUnits; } - - void setCurTextureUnit(GrGLuint curTextureUnit) { fCurTextureUnit = curTextureUnit; } - GrGLuint getCurTextureUnit() const { return fCurTextureUnit; } - - GrTextureUnitObj *getTextureUnit(int iUnit) { - GrAlwaysAssert(0 <= iUnit && kDefaultMaxTextureUnits > iUnit); - - return fTextureUnits[iUnit]; - } - - void setArrayBuffer(GrBufferObj *arrayBuffer) { - if (fArrayBuffer) { - // automatically break the binding of the old buffer - GrAlwaysAssert(fArrayBuffer->getBound()); - fArrayBuffer->resetBound(); - - GrAlwaysAssert(!fArrayBuffer->getDeleted()); - fArrayBuffer->unref(); - } - - fArrayBuffer = arrayBuffer; - - if (fArrayBuffer) { - GrAlwaysAssert(!fArrayBuffer->getDeleted()); - fArrayBuffer->ref(); - - GrAlwaysAssert(!fArrayBuffer->getBound()); - fArrayBuffer->setBound(); - } - } - GrBufferObj *getArrayBuffer() { return fArrayBuffer; } - - void setElementArrayBuffer(GrBufferObj *elementArrayBuffer) { - if (fElementArrayBuffer) { - // automatically break the binding of the old buffer - GrAlwaysAssert(fElementArrayBuffer->getBound()); - fElementArrayBuffer->resetBound(); - - GrAlwaysAssert(!fElementArrayBuffer->getDeleted()); - fElementArrayBuffer->unref(); - } - - fElementArrayBuffer = elementArrayBuffer; - - if (fElementArrayBuffer) { - GrAlwaysAssert(!fElementArrayBuffer->getDeleted()); - fElementArrayBuffer->ref(); - - GrAlwaysAssert(!fElementArrayBuffer->getBound()); - fElementArrayBuffer->setBound(); - } - } - - GrBufferObj *getElementArrayBuffer() { return fElementArrayBuffer; } - - void setTexture(GrTextureObj *texture) { - fTextureUnits[fCurTextureUnit]->setTexture(texture); - } - - void setFrameBuffer(GrFrameBufferObj *frameBuffer) { - if (fFrameBuffer) { - GrAlwaysAssert(fFrameBuffer->getBound()); - fFrameBuffer->resetBound(); - - GrAlwaysAssert(!fFrameBuffer->getDeleted()); - fFrameBuffer->unref(); - } - - fFrameBuffer = frameBuffer; - - if (fFrameBuffer) { - GrAlwaysAssert(!fFrameBuffer->getDeleted()); - fFrameBuffer->ref(); - - GrAlwaysAssert(!fFrameBuffer->getBound()); - fFrameBuffer->setBound(); - } - } - - GrFrameBufferObj *getFrameBuffer() { return fFrameBuffer; } - - void setRenderBuffer(GrRenderBufferObj *renderBuffer) { - if (fRenderBuffer) { - GrAlwaysAssert(fRenderBuffer->getBound()); - fRenderBuffer->resetBound(); - - GrAlwaysAssert(!fRenderBuffer->getDeleted()); - fRenderBuffer->unref(); - } - - fRenderBuffer = renderBuffer; - - if (fRenderBuffer) { - GrAlwaysAssert(!fRenderBuffer->getDeleted()); - fRenderBuffer->ref(); - - GrAlwaysAssert(!fRenderBuffer->getBound()); - fRenderBuffer->setBound(); - } - } - - GrRenderBufferObj *getRenderBuffer() { return fRenderBuffer; } - - void useProgram(GrProgramObj *program) { - if (fProgram) { - GrAlwaysAssert(fProgram->getInUse()); - fProgram->resetInUse(); - - GrAlwaysAssert(!fProgram->getDeleted()); - fProgram->unref(); - } - - fProgram = program; - - if (fProgram) { - GrAlwaysAssert(!fProgram->getDeleted()); - fProgram->ref(); - - GrAlwaysAssert(!fProgram->getInUse()); - fProgram->setInUse(); - } - } - - static GrDebugGL *getInstance() { -// static GrDebugGL Obj; - - return &Obj; - } - - void report() const { - for (int i = 0; i < fObjects.count(); ++i) { - GrAlwaysAssert(0 == fObjects[i]->getRefCount()); - GrAlwaysAssert(0 < fObjects[i]->getHighRefCount()); - GrAlwaysAssert(fObjects[i]->getDeleted()); - } - } - -protected: - -private: - // the OpenGLES 2.0 spec says this must be >= 2 - static const GrGLint kDefaultMaxTextureUnits = 8; - - GrGLuint fMaxTextureUnits; - GrGLuint fCurTextureUnit; - GrBufferObj * fArrayBuffer; - GrBufferObj * fElementArrayBuffer; - GrFrameBufferObj *fFrameBuffer; - GrRenderBufferObj *fRenderBuffer; - GrProgramObj * fProgram; - GrTextureObj * fTexture; - GrTextureUnitObj *fTextureUnits[kDefaultMaxTextureUnits]; - - typedef GrFakeRefObj *(*Create)(); - - static Create gFactoryFunc[kObjTypeCount]; - - static GrDebugGL Obj; - - // global store of all objects - SkTArray fObjects; - - GrDebugGL() - : fCurTextureUnit(0) - , fArrayBuffer(NULL) - , fElementArrayBuffer(NULL) - , fFrameBuffer(NULL) - , fRenderBuffer(NULL) - , fProgram(NULL) - , fTexture(NULL) { - - for (int i = 0; i < kDefaultMaxTextureUnits; ++i) { - fTextureUnits[i] = GR_CREATE(GrTextureUnitObj, GrDebugGL::kTextureUnit_ObjTypes); - fTextureUnits[i]->ref(); - - fTextureUnits[i]->setNumber(i); - } - } - - ~GrDebugGL() { - // unref & delete the texture units first so they don't show up on the leak report - for (int i = 0; i < kDefaultMaxTextureUnits; ++i) { - fTextureUnits[i]->unref(); - fTextureUnits[i]->deleteAction(); - } - - this->report(); - - for (int i = 0; i < fObjects.count(); ++i) { - delete fObjects[i]; - } - fObjects.reset(); - - fArrayBuffer = NULL; - fElementArrayBuffer = NULL; - fFrameBuffer = NULL; - fRenderBuffer = NULL; - fProgram = NULL; - fTexture = NULL; - } -}; - -GrDebugGL GrDebugGL::Obj; -GrDebugGL::Create GrDebugGL::gFactoryFunc[kObjTypeCount] = { - GrTextureObj::createGrTextureObj, - GrBufferObj::createGrBufferObj, - GrRenderBufferObj::createGrRenderBufferObj, - GrFrameBufferObj::createGrFrameBufferObj, - GrShaderObj::createGrShaderObj, - GrProgramObj::createGrProgramObj, - GrTextureUnitObj::createGrTextureUnitObj, -}; - - //////////////////////////////////////////////////////////////////////////////// GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture) { diff --git a/src/gpu/gl/debug/GrProgramObj.cpp b/src/gpu/gl/debug/GrProgramObj.cpp new file mode 100644 index 0000000000..aecec258a8 --- /dev/null +++ b/src/gpu/gl/debug/GrProgramObj.cpp @@ -0,0 +1,27 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrProgramObj.h" +#include "GrShaderObj.h" + +void GrProgramObj::AttachShader(GrShaderObj *shader) { + shader->ref(); + fShaders.push_back(shader); +} + +void GrProgramObj::deleteAction() { + + // shaders are automatically detached from a deleted program. They will only be + // deleted if they were marked for deletion by a prior call to glDeleteShader + for (int i = 0; i < fShaders.count(); ++i) { + fShaders[i]->unref(); + } + fShaders.reset(); + + this->INHERITED::deleteAction(); +} diff --git a/src/gpu/gl/debug/GrProgramObj.h b/src/gpu/gl/debug/GrProgramObj.h new file mode 100644 index 0000000000..d83eab8805 --- /dev/null +++ b/src/gpu/gl/debug/GrProgramObj.h @@ -0,0 +1,43 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrProgramObj_DEFINED +#define GrProgramObj_DEFINED + +#include "SkTArray.h" +#include "GrFakeRefObj.h" +class GrShaderObj; + +//////////////////////////////////////////////////////////////////////////////// +class GrProgramObj : public GrFakeRefObj { + GR_DEFINE_CREATOR(GrProgramObj); + +public: + GrProgramObj() + : GrFakeRefObj() + , fInUse(false) {} + + void AttachShader(GrShaderObj *shader); + + virtual void deleteAction() SK_OVERRIDE; + + // TODO: this flag system won't work w/ multiple contexts! + void setInUse() { fInUse = true; } + void resetInUse() { fInUse = false; } + bool getInUse() const { return fInUse; } + +protected: + +private: + SkTArray fShaders; + bool fInUse; // has this program been activated by a glUseProgram call? + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrProgramObj_DEFINED diff --git a/src/gpu/gl/debug/GrRenderBufferObj.cpp b/src/gpu/gl/debug/GrRenderBufferObj.cpp new file mode 100644 index 0000000000..b7641ca948 --- /dev/null +++ b/src/gpu/gl/debug/GrRenderBufferObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrRenderBufferObj.h" diff --git a/src/gpu/gl/debug/GrRenderBufferObj.h b/src/gpu/gl/debug/GrRenderBufferObj.h new file mode 100644 index 0000000000..344b90e5a9 --- /dev/null +++ b/src/gpu/gl/debug/GrRenderBufferObj.h @@ -0,0 +1,40 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrRenderBufferObj_DEFINED +#define GrRenderBufferObj_DEFINED + +#include "GrFBBindableObj.h" + +//////////////////////////////////////////////////////////////////////////////// +class GrRenderBufferObj : public GrFBBindableObj { + GR_DEFINE_CREATOR(GrRenderBufferObj); + +public: + GrRenderBufferObj() + : GrFBBindableObj() + , fBound(false) { + } + + void setBound() { fBound = true; } + void resetBound() { fBound = false; } + bool getBound() const { return fBound; } + + virtual void deleteAction() SK_OVERRIDE { + + this->INHERITED::deleteAction(); + } + +protected: +private: + bool fBound; // is this render buffer currently bound via "glBindRenderbuffer"? + + typedef GrFBBindableObj INHERITED; +}; + +#endif // GrRenderBufferObj_DEFINED diff --git a/src/gpu/gl/debug/GrShaderObj.cpp b/src/gpu/gl/debug/GrShaderObj.cpp new file mode 100644 index 0000000000..60c6903ecb --- /dev/null +++ b/src/gpu/gl/debug/GrShaderObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrShaderObj.h" diff --git a/src/gpu/gl/debug/GrShaderObj.h b/src/gpu/gl/debug/GrShaderObj.h new file mode 100644 index 0000000000..ca6ccdc048 --- /dev/null +++ b/src/gpu/gl/debug/GrShaderObj.h @@ -0,0 +1,38 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrShaderObj_DEFINED +#define GrShaderObj_DEFINED + +#include "GrFakeRefObj.h" + +//////////////////////////////////////////////////////////////////////////////// +class GrShaderObj : public GrFakeRefObj { + GR_DEFINE_CREATOR(GrShaderObj); + +public: + GrShaderObj() + : GrFakeRefObj() + , fType(GR_GL_VERTEX_SHADER) {} + + void setType(GrGLenum type) { fType = type; } + GrGLenum getType() { return fType; } + + virtual void deleteAction() SK_OVERRIDE { + + this->INHERITED::deleteAction(); + } + +protected: +private: + GrGLenum fType; // either GR_GL_VERTEX_SHADER or GR_GL_FRAGMENT_SHADER + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrShaderObj_DEFINED diff --git a/src/gpu/gl/debug/GrTextureObj.cpp b/src/gpu/gl/debug/GrTextureObj.cpp new file mode 100644 index 0000000000..24284d43be --- /dev/null +++ b/src/gpu/gl/debug/GrTextureObj.cpp @@ -0,0 +1,9 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrTextureObj.h" \ No newline at end of file diff --git a/src/gpu/gl/debug/GrTextureObj.h b/src/gpu/gl/debug/GrTextureObj.h new file mode 100644 index 0000000000..922c9853cb --- /dev/null +++ b/src/gpu/gl/debug/GrTextureObj.h @@ -0,0 +1,60 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrTextureObj_DEFINED +#define GrTextureObj_DEFINED + +#include "GrFBBindableObj.h" + +class GrTextureUnitObj; + +//////////////////////////////////////////////////////////////////////////////// +class GrTextureObj : public GrFBBindableObj { + GR_DEFINE_CREATOR(GrTextureObj); + +public: + GrTextureObj() + : GrFBBindableObj() { + } + + virtual ~GrTextureObj() { + GrAlwaysAssert(0 == fTextureUnitReferees.count()); + } + + void setBound(GrTextureUnitObj *referee) { + fTextureUnitReferees.append(1, &referee); + } + + void resetBound(GrTextureUnitObj *referee) { + int index = fTextureUnitReferees.find(referee); + GrAlwaysAssert(0 <= index); + fTextureUnitReferees.removeShuffle(index); + } + bool getBound(GrTextureUnitObj *referee) const { + int index = fTextureUnitReferees.find(referee); + return 0 <= index; + } + bool getBound() const { + return 0 != fTextureUnitReferees.count(); + } + + virtual void deleteAction() SK_OVERRIDE { + + this->INHERITED::deleteAction(); + } + +protected: + +private: + // texture units that bind this texture (via "glBindTexture") + SkTDArray fTextureUnitReferees; + + typedef GrFBBindableObj INHERITED; +}; + +#endif // GrTextureObj_DEFINED diff --git a/src/gpu/gl/debug/GrTextureUnitObj.cpp b/src/gpu/gl/debug/GrTextureUnitObj.cpp new file mode 100644 index 0000000000..05c149a1c0 --- /dev/null +++ b/src/gpu/gl/debug/GrTextureUnitObj.cpp @@ -0,0 +1,32 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrTextureUnitObj.h" +#include "GrTextureObj.h" + +void GrTextureUnitObj::setTexture(GrTextureObj *texture) { + + if (fTexture) { + GrAlwaysAssert(fTexture->getBound(this)); + fTexture->resetBound(this); + + GrAlwaysAssert(!fTexture->getDeleted()); + fTexture->unref(); + } + + fTexture = texture; + + if (fTexture) { + GrAlwaysAssert(!fTexture->getDeleted()); + fTexture->ref(); + + GrAlwaysAssert(!fTexture->getBound(this)); + fTexture->setBound(this); + } +} + diff --git a/src/gpu/gl/debug/GrTextureUnitObj.h b/src/gpu/gl/debug/GrTextureUnitObj.h new file mode 100644 index 0000000000..a1dab11ddc --- /dev/null +++ b/src/gpu/gl/debug/GrTextureUnitObj.h @@ -0,0 +1,45 @@ + +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrTextreUnitObj_DEFINED +#define GrTextureUnitObj_DEFINED + +#include "GrFakeRefObj.h" +class GrTextureObj; + +//////////////////////////////////////////////////////////////////////////////// +// Although texture unit objects are allocated & deallocated like the other +// GL emulation objects they are derived from GrFakeRefObj to provide some +// uniformity in how the GrDebugGL class manages resources +class GrTextureUnitObj : public GrFakeRefObj { + GR_DEFINE_CREATOR(GrTextureUnitObj); + +public: + GrTextureUnitObj() + : GrFakeRefObj() + , fNumber(0) + , fTexture(NULL) { + } + + void setNumber(GrGLenum number) { + fNumber = number; + } + GrGLenum getNumber() const { return fNumber; } + + void setTexture(GrTextureObj *texture); + GrTextureObj *getTexture() { return fTexture; } + +protected: +private: + GrGLenum fNumber; + GrTextureObj *fTexture; + + typedef GrFakeRefObj INHERITED; +}; + +#endif // GrTextureUnitObj_DEFINED