Added tracking of frame buffer objects to debug GL interface

http://codereview.appspot.com/5866043/




git-svn-id: http://skia.googlecode.com/svn/trunk@3455 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2012-03-21 17:57:55 +00:00
parent 008c498b58
commit f6f123d236
4 changed files with 268 additions and 75 deletions

View File

@ -21,6 +21,7 @@
#include "SkImageEncoder.h"
#include "gl/SkNativeGLContext.h"
#include "gl/SkMesaGLContext.h"
#include "gl/SkDebugGLContext.h"
#include "SkPicture.h"
#include "SkStream.h"
#include "SkRefCnt.h"
@ -606,11 +607,12 @@ static void usage(const char * argv0) {
SkDebugf(
"%s [-w writePath] [-r readPath] [-d diffPath] [-i resourcePath]\n"
" [--noreplay] [--serialize] [--forceBWtext] [--nopdf] \n"
" [--nodeferred] [--match substring] [--notexturecache]"
" [--nodeferred] [--match substring] [--notexturecache]\n"
" "
#if SK_MESA
" [--mesagl]"
"[--mesagl]"
#endif
"\n\n", argv0);
" [--debuggl]\n\n", argv0);
SkDebugf(" writePath: directory to write rendered images in.\n");
SkDebugf(
" readPath: directory to read reference images from;\n"
@ -627,6 +629,7 @@ static void usage(const char * argv0) {
#if SK_MESA
SkDebugf(" --mesagl will run using the osmesa sw gl rasterizer.\n");
#endif
SkDebugf(" --debuggl will run using the debugging gl utility.\n");
SkDebugf(" --notexturecache: disable the gpu texture cache.\n");
}
@ -684,6 +687,7 @@ int main(int argc, char * const argv[]) {
bool doReplay = true;
bool doSerialize = false;
bool useMesa = false;
bool useDebugGL = false;
bool doDeferred = true;
bool disableTextureCache = false;
@ -730,6 +734,8 @@ int main(int argc, char * const argv[]) {
} else if (strcmp(*argv, "--mesagl") == 0) {
useMesa = true;
#endif
} else if (strcmp(*argv, "--debuggl") == 0) {
useDebugGL = true;
} else if (strcmp(*argv, "--notexturecache") == 0) {
disableTextureCache = true;
} else {
@ -763,7 +769,9 @@ int main(int argc, char * const argv[]) {
glContext.reset(new SkMesaGLContext());
} else
#endif
{
if (useDebugGL) {
glContext.reset(new SkDebugGLContext());
} else {
glContext.reset(new SkNativeGLContext());
}
@ -893,5 +901,9 @@ int main(int argc, char * const argv[]) {
}
printf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
SkDELETE(skiagm::gGrContext);
skiagm::gGrContext = NULL;
return (0 == testsFailed) ? 0 : -1;
}

View File

@ -14,6 +14,18 @@
// the OpenGLES 2.0 spec says this must be >= 2
static const GrGLint kDefaultMaxTextureUnits = 8;
// the OpenGLES 2.0 spec says this must be >= 128
static const GrGLint kDefaultMaxVertexUniformVectors = 128;
// the OpenGLES 2.0 spec says this must be >=16
static const GrGLint kDefaultMaxFragmentUniformVectors = 16;
// the OpenGLES 2.0 spec says this must be >= 8
static const GrGLint kDefaultMaxVertexAttribs = 8;
// the OpenGLES 2.0 spec says this must be >= 8
static const GrGLint kDefaultMaxVaryingVectors = 8;
////////////////////////////////////////////////////////////////////////////////
// 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
@ -26,15 +38,23 @@ class GrFakeRefObj
public:
GrFakeRefObj(GrGLuint ID)
: fRef(0)
, fHighRefCount(0)
, fID(ID)
, fMarkedForDeletion(false)
, fDeleted(false) {
}
virtual ~GrFakeRefObj() {};
void ref() { fRef++; }
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
@ -43,6 +63,7 @@ public:
}
}
int getRefCount() const { return fRef; }
int getHighRefCount() const { return fHighRefCount; }
GrGLuint getID() const { return fID; }
@ -60,6 +81,7 @@ public:
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
@ -96,14 +118,14 @@ public:
void resetBound() { fBound = false; }
bool getBound() const { return fBound; }
void allocate(GrGLint size, const GrGLvoid *dataPtr) {
void allocate(GrGLint size, const GrGLchar *dataPtr) {
GrAlwaysAssert(size >= 0);
// delete pre-existing data
delete fDataPtr;
fSize = size;
fDataPtr = new char[size];
fDataPtr = new GrGLchar[size];
if (dataPtr) {
memcpy(fDataPtr, dataPtr, fSize);
}
@ -126,7 +148,7 @@ public:
protected:
private:
GrGLvoid* fDataPtr;
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
@ -135,6 +157,32 @@ private:
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
{
public:
GrFrameBufferObj(GrGLuint ID)
: GrFakeRefObj(ID)
, fBound(false) {
}
void setBound() { fBound = true; }
void resetBound() { fBound = false; }
bool getBound() const { return fBound; }
virtual void deleteAction() SK_OVERRIDE {
this->setDeleted();
}
protected:
private:
bool fBound; // is this frame buffer currently bound via "glBindFramebuffer"?
typedef GrFakeRefObj INHERITED;
};
////////////////////////////////////////////////////////////////////////////////
class GrShaderObj : public GrFakeRefObj
@ -167,8 +215,7 @@ public:
: GrFakeRefObj(ID)
, fInUse(false) {}
void AttachShader(GrShaderObj *shader)
{
void AttachShader(GrShaderObj *shader) {
shader->ref();
fShaders.push_back(shader);
}
@ -185,7 +232,9 @@ public:
this->setDeleted();
}
// TODO: this flag system won't work w/ multiple contexts!
void setInUse() { fInUse = true; }
void resetInUse() { fInUse = false; }
bool getInUse() const { return fInUse; }
protected:
@ -203,9 +252,8 @@ private:
class GrDebugGL
{
public:
// TODO: merge findBuffer, findShader & findProgram??
GrBufferObj *findBuffer(GrGLuint ID)
{
// TODO: merge findBuffer, findFrameBuffer, findShader & findProgram??
GrBufferObj *findBuffer(GrGLuint ID) {
GrFakeRefObj *obj = this->findObject(ID);
if (NULL == obj) {
return NULL;
@ -214,8 +262,16 @@ public:
return reinterpret_cast<GrBufferObj *>(obj);
}
GrShaderObj *findShader(GrGLuint ID)
{
GrFrameBufferObj *findFrameBuffer(GrGLuint ID) {
GrFakeRefObj *obj = this->findObject(ID);
if (NULL == obj) {
return NULL;
}
return reinterpret_cast<GrFrameBufferObj *>(obj);
}
GrShaderObj *findShader(GrGLuint ID) {
GrFakeRefObj *obj = this->findObject(ID);
if (NULL == obj) {
return NULL;
@ -224,8 +280,7 @@ public:
return reinterpret_cast<GrShaderObj *>(obj);
}
GrProgramObj *findProgram(GrGLuint ID)
{
GrProgramObj *findProgram(GrGLuint ID) {
GrFakeRefObj *obj = this->findObject(ID);
if (NULL == obj) {
return NULL;
@ -235,8 +290,7 @@ public:
}
// TODO: merge createBuffer, createShader, createProgram??
GrBufferObj *createBuffer()
{
GrBufferObj *createBuffer() {
GrBufferObj *buffer = new GrBufferObj(++fNextID);
fObjects.push_back(buffer);
@ -244,8 +298,15 @@ public:
return buffer;
}
GrShaderObj *createShader(GrGLenum type)
{
GrFrameBufferObj *createFrameBuffer() {
GrFrameBufferObj *buffer = new GrFrameBufferObj(++fNextID);
fObjects.push_back(buffer);
return buffer;
}
GrShaderObj *createShader(GrGLenum type) {
GrShaderObj *shader = new GrShaderObj(++fNextID, type);
fObjects.push_back(shader);
@ -253,8 +314,7 @@ public:
return shader;
}
GrProgramObj *createProgram()
{
GrProgramObj *createProgram() {
GrProgramObj *program = new GrProgramObj(++fNextID);
fObjects.push_back(program);
@ -262,8 +322,7 @@ public:
return program;
}
GrFakeRefObj *findObject(GrGLuint ID)
{
GrFakeRefObj *findObject(GrGLuint ID) {
for (int i = 0; i < fObjects.count(); ++i) {
if (fObjects[i]->getID() == ID) {
// The application shouldn't be accessing objects
@ -284,14 +343,97 @@ public:
void setCurTextureUnit(GrGLuint curTextureUnit) { fCurTextureUnit = curTextureUnit; }
GrGLuint getCurTextureUnit() const { return fCurTextureUnit; }
void setArrayBuffer(GrBufferObj *arrayBuffer) { fArrayBuffer = arrayBuffer; }
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) { fElementArrayBuffer = elementArrayBuffer; }
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; }
static GrDebugGL *getInstance()
{
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 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;
@ -299,6 +441,8 @@ public:
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());
}
}
@ -310,6 +454,8 @@ private:
GrGLuint fCurTextureUnit;
GrBufferObj * fArrayBuffer;
GrBufferObj * fElementArrayBuffer;
GrFrameBufferObj *fFrameBuffer;
GrProgramObj * fProgram;
static int fNextID; // source for globally unique IDs
@ -320,10 +466,11 @@ private:
GrDebugGL()
: fMaxTextureUnits(kDefaultMaxTextureUnits)
, fCurTextureUnit(0)
, fArrayBuffer(NULL)
, fElementArrayBuffer(NULL)
{
, fCurTextureUnit(0)
, fArrayBuffer(NULL)
, fElementArrayBuffer(NULL)
, fFrameBuffer(NULL)
, fProgram(NULL) {
}
~GrDebugGL() {
@ -333,8 +480,11 @@ private:
delete fObjects[i];
}
fObjects.reset();
fArrayBuffer = NULL;
fElementArrayBuffer = NULL;
fFrameBuffer = NULL;
fProgram = NULL;
}
};
@ -342,8 +492,7 @@ int GrDebugGL::fNextID = 0;
GrDebugGL GrDebugGL::Obj;
////////////////////////////////////////////////////////////////////////////////
GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture)
{
GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture) {
GrAlwaysAssert(0 <= texture);
// GrAlwaysAssert(texture < GrDebugGL::getInstance()->getMaxTextureUnits());
@ -352,8 +501,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLActiveTexture(GrGLenum texture)
}
////////////////////////////////////////////////////////////////////////////////
GrGLvoid GR_GL_FUNCTION_TYPE debugGLAttachShader(GrGLuint programID, GrGLuint shaderID)
{
GrGLvoid GR_GL_FUNCTION_TYPE debugGLAttachShader(GrGLuint programID, GrGLuint shaderID) {
GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
GrAlwaysAssert(program);
@ -371,8 +519,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFragDataLocation(GrGLuint program, GrGLu
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBlendFunc(GrGLenum sfactor, GrGLenum dfactor) {}
////////////////////////////////////////////////////////////////////////////////
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage)
{
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target, GrGLsizeiptr size, const GrGLvoid* data, GrGLenum usage) {
GrAlwaysAssert(GR_GL_ARRAY_BUFFER == target || GR_GL_ELEMENT_ARRAY_BUFFER == target);
GrAlwaysAssert(size >= 0);
GrAlwaysAssert(GR_GL_STREAM_DRAW == usage || GR_GL_STATIC_DRAW == usage || GR_GL_DYNAMIC_DRAW == usage);
@ -393,7 +540,7 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBufferData(GrGLenum target, GrGLsizeiptr siz
GrAlwaysAssert(buffer);
GrAlwaysAssert(buffer->getBound());
buffer->allocate(size, data);
buffer->allocate(size, reinterpret_cast<const GrGLchar *>(data));
buffer->setUsage(usage);
}
@ -458,17 +605,51 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLUniformMatrix4fv(GrGLint location, GrGLsizei
GrGLvoid GR_GL_FUNCTION_TYPE debugGLUseProgram(GrGLuint programID) {
// A programID of 0 is legal
GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
GrAlwaysAssert(program);
program->setInUse();
GrDebugGL::getInstance()->useProgram(program);
}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLVertexAttrib4fv(GrGLuint indx, const GrGLfloat* values) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLVertexAttribPointer(GrGLuint indx, GrGLint size, GrGLenum type, GrGLboolean normalized, GrGLsizei stride, const GrGLvoid* ptr) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLViewport(GrGLint x, GrGLint y, GrGLsizei width, GrGLsizei height) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFramebuffer(GrGLenum target, GrGLuint framebuffer) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindFramebuffer(GrGLenum target, GrGLuint frameBufferID) {
GrAlwaysAssert(GR_GL_FRAMEBUFFER == target);
// a frameBufferID of 0 is acceptable - it binds to the default frame buffer
GrFrameBufferObj *framebuffer = GrDebugGL::getInstance()->findFrameBuffer(frameBufferID);
GrDebugGL::getInstance()->setFrameBuffer(framebuffer);
}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindRenderbuffer(GrGLenum target, GrGLuint renderbuffer) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteFramebuffers(GrGLsizei n, const GrGLuint *framebuffers) {
// first potentially unbind the buffers
if (GrDebugGL::getInstance()->getFrameBuffer()) {
for (int i = 0; i < n; ++i) {
if (framebuffers[i] == GrDebugGL::getInstance()->getFrameBuffer()->getID()) {
// this ID is the current frame buffer - rebind to the default
GrDebugGL::getInstance()->setFrameBuffer(NULL);
}
}
}
// then actually "delete" the buffers
for (int i = 0; i < n; ++i) {
GrFrameBufferObj *buffer = GrDebugGL::getInstance()->findFrameBuffer(framebuffers[i]);
GrAlwaysAssert(buffer);
GrAlwaysAssert(!buffer->getDeleted());
buffer->deleteAction();
}
}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteRenderbuffers(GrGLsizei n, const GrGLuint *renderbuffers) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferRenderbuffer(GrGLenum target, GrGLenum attachment, GrGLenum renderbuffertarget, GrGLuint renderbuffer) {}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLFramebufferTexture2D(GrGLenum target, GrGLenum attachment, GrGLenum textarget, GrGLuint texture, GrGLint level) {}
@ -505,8 +686,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteProgram(GrGLuint programID) {
GrProgramObj *program = GrDebugGL::getInstance()->findProgram(programID);
GrAlwaysAssert(program);
program->unref();
if (program->getRefCount()) {
// someone is still using this program so we can't delete it here
program->setMarkedForDeletion();
@ -520,8 +699,6 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteShader(GrGLuint shaderID) {
GrShaderObj *shader = GrDebugGL::getInstance()->findShader(shaderID);
GrAlwaysAssert(shader);
shader->unref();
if (shader->getRefCount()) {
// someone is still using this shader so we can't delete it here
shader->setMarkedForDeletion();
@ -547,6 +724,15 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenBuffers(GrGLsizei n, GrGLuint* ids) {
}
}
GrGLvoid GR_GL_FUNCTION_TYPE debugGLGenFramebuffers(GrGLsizei n, GrGLuint* ids) {
for (int i = 0; i < n; ++i) {
GrFrameBufferObj *buffer = GrDebugGL::getInstance()->createFrameBuffer();
GrAlwaysAssert(buffer);
ids[i] = buffer->getID();
}
}
// same delete function for all glDelete*(GLsize i, const GLuint*) except buffers
GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteIds(GrGLsizei n, const GrGLuint* ids) {}
@ -560,30 +746,10 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLBindBuffer(GrGLenum target, GrGLuint bufferI
switch (target) {
case GR_GL_ARRAY_BUFFER:
if (GrDebugGL::getInstance()->getArrayBuffer()) {
// automatically break the binding of the old buffer
GrDebugGL::getInstance()->getArrayBuffer()->resetBound();
}
if (buffer) {
GrAlwaysAssert(!buffer->getBound());
}
GrDebugGL::getInstance()->setArrayBuffer(buffer);
if (buffer) {
buffer->setBound();
}
break;
case GR_GL_ELEMENT_ARRAY_BUFFER:
if (GrDebugGL::getInstance()->getElementArrayBuffer()) {
// automatically break the binding of the old buffer
GrDebugGL::getInstance()->getElementArrayBuffer()->resetBound();
}
if (buffer) {
GrAlwaysAssert(!buffer->getBound());
}
GrDebugGL::getInstance()->setElementArrayBuffer(buffer);
if (buffer) {
buffer->setBound();
}
break;
default:
GrCrash("Unexpected target to glBindBuffer");
@ -599,15 +765,11 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLDeleteBuffers(GrGLsizei n, const GrGLuint* i
if (GrDebugGL::getInstance()->getArrayBuffer() &&
ids[i] == GrDebugGL::getInstance()->getArrayBuffer()->getID()) {
// this ID is the current array buffer
GrAlwaysAssert(GrDebugGL::getInstance()->getArrayBuffer()->getBound());
GrDebugGL::getInstance()->getArrayBuffer()->resetBound();
GrDebugGL::getInstance()->setArrayBuffer(NULL);
}
if (GrDebugGL::getInstance()->getElementArrayBuffer() &&
ids[i] == GrDebugGL::getInstance()->getElementArrayBuffer()->getID()) {
// this ID is the current element array buffer
GrAlwaysAssert(GrDebugGL::getInstance()->getElementArrayBuffer()->getBound());
GrDebugGL::getInstance()->getElementArrayBuffer()->resetBound();
GrDebugGL::getInstance()->setElementArrayBuffer(NULL);
}
}
@ -745,8 +907,11 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetIntegerv(GrGLenum pname, GrGLint* params)
case GR_GL_MAX_TEXTURE_IMAGE_UNITS:
*params = 8;
break;
case GR_GL_MAX_VERTEX_UNIFORM_VECTORS:
*params = kDefaultMaxVertexUniformVectors;
break;
case GR_GL_MAX_FRAGMENT_UNIFORM_VECTORS:
*params = 16;
*params = kDefaultMaxFragmentUniformVectors;
break;
case GR_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
*params = 16 * 4;
@ -766,7 +931,10 @@ GrGLvoid GR_GL_FUNCTION_TYPE debugGLGetIntegerv(GrGLenum pname, GrGLint* params)
*params = 32;
break;
case GR_GL_MAX_VERTEX_ATTRIBS:
*params = 16;
*params = kDefaultMaxVertexAttribs;
break;
case GR_GL_MAX_VARYING_VECTORS:
*params = kDefaultMaxVaryingVectors;
break;
case GR_GL_MAX_TEXTURE_UNITS:
*params = GrDebugGL::getInstance()->getMaxTextureUnits();
@ -983,7 +1151,7 @@ const GrGLInterface* GrGLCreateDebugInterface() {
interface->fDeleteRenderbuffers = debugGLDeleteRenderbuffers;
interface->fFramebufferRenderbuffer = debugGLFramebufferRenderbuffer;
interface->fFramebufferTexture2D = debugGLFramebufferTexture2D;
interface->fGenFramebuffers = debugGLGenIds;
interface->fGenFramebuffers = debugGLGenFramebuffers;
interface->fGenRenderbuffers = debugGLGenIds;
interface->fGetFramebufferAttachmentParameteriv = debugGLGetFramebufferAttachmentParameteriv;
interface->fGetRenderbufferParameteriv = debugGLGetRenderbufferParameteriv;

View File

@ -125,6 +125,7 @@ public:
void GrGpuGLShaders::abandonResources(){
INHERITED::abandonResources();
fProgramCache->abandon();
fHWProgramID = 0;
}
void GrGpuGLShaders::DeleteProgram(const GrGLInterface* gl,
@ -326,6 +327,13 @@ GrGpuGLShaders::GrGpuGLShaders(const GrGLContextInfo& ctxInfo)
}
GrGpuGLShaders::~GrGpuGLShaders() {
if (fProgramData && 0 != fHWProgramID) {
// detach the current program so there is no confusion on OpenGL's part
// that we want it to be deleted
SkASSERT(fHWProgramID == fProgramData->fProgramID);
GL_CALL(UseProgram(0));
}
delete fProgramCache;
}

View File

@ -13,6 +13,11 @@ SkGLContext::SkGLContext()
}
SkGLContext::~SkGLContext() {
if (fGL) {
SK_GL(*this, DeleteFramebuffers(1, &fFBO));
}
SkSafeUnref(fGL);
}