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
This commit is contained in:
robertphillips@google.com 2012-04-05 14:40:53 +00:00
parent ded33215f6
commit dd743fefad
22 changed files with 1087 additions and 782 deletions

View File

@ -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',

View File

@ -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"

View File

@ -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

View File

@ -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());
}
}

View File

@ -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<GrFakeRefObj *> 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<className *>(GrDebugGL::getInstance()->createObj(classEnum))
////////////////////////////////////////////////////////////////////////////////
// Helper macro to make finding objects less painful
#define GR_FIND(id, className, classEnum) \
reinterpret_cast<className *>(GrDebugGL::getInstance()->findObject(id, classEnum))
#endif // GrDebugGL_DEFINED

View File

@ -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"

View File

@ -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<GrFakeRefObj *> fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
SkTDArray<GrFakeRefObj *> fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
SkTDArray<GrFakeRefObj *> fStencilReferees; // frame buffers that use this as a stencil buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
typedef GrFakeRefObj INHERITED;
};
#endif // GrFBBindableObj_DEFINED

View File

@ -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"

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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<className *>(GrDebugGL::getInstance()->createObj(classEnum))
////////////////////////////////////////////////////////////////////////////////
// Helper macro to make finding objects less painful
#define GR_FIND(id, className, classEnum) \
reinterpret_cast<className *>(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<GrFakeRefObj *> fColorReferees; // frame buffers that use this as a color buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
SkTDArray<GrFakeRefObj *> fDepthReferees; // frame buffers that use this as a depth buffer (via "glFramebufferRenderbuffer" or "glFramebufferTexture2D")
SkTDArray<GrFakeRefObj *> 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<GrTextureUnitObj *> 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<GrShaderObj *> 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<GrFakeRefObj *> 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) {

View File

@ -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();
}

View File

@ -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<GrShaderObj *> fShaders;
bool fInUse; // has this program been activated by a glUseProgram call?
typedef GrFakeRefObj INHERITED;
};
#endif // GrProgramObj_DEFINED

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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<GrTextureUnitObj *> fTextureUnitReferees;
typedef GrFBBindableObj INHERITED;
};
#endif // GrTextureObj_DEFINED

View File

@ -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);
}
}

View File

@ -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