/*
* 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"
#include "GrVertexArrayObj.h"
GrDebugGL* GrDebugGL::gObj = nullptr;
int GrDebugGL::gStaticRefCount = 0;
GrDebugGL::Create GrDebugGL::gFactoryFunc[kObjTypeCount] = {
GrTextureObj::createGrTextureObj,
GrBufferObj::createGrBufferObj,
GrRenderBufferObj::createGrRenderBufferObj,
GrFrameBufferObj::createGrFrameBufferObj,
GrShaderObj::createGrShaderObj,
GrProgramObj::createGrProgramObj,
GrTextureUnitObj::createGrTextureUnitObj,
GrVertexArrayObj::createGrVertexArrayObj,
};
GrDebugGL::GrDebugGL()
: fPackRowLength(0)
, fUnPackRowLength(0)
, fCurTextureUnit(0)
, fArrayBuffer(nullptr)
, fElementArrayBuffer(nullptr)
, fFrameBuffer(nullptr)
, fRenderBuffer(nullptr)
, fProgram(nullptr)
, fTexture(nullptr)
, fVertexArray(nullptr)
, fAbandoned(false) {
for (int i = 0; i < kDefaultMaxTextureUnits; ++i) {
fTextureUnits[i] = reinterpret_cast<GrTextureUnitObj *>(
createObj(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 = nullptr;
fElementArrayBuffer = nullptr;
fFrameBuffer = nullptr;
fRenderBuffer = nullptr;
fProgram = nullptr;
fTexture = nullptr;
fVertexArray = nullptr;
}
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 nullptr;
}
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::setVertexArray(GrVertexArrayObj* vertexArray) {
if (vertexArray) {
SkASSERT(!vertexArray->getDeleted());
}
SkRefCnt_SafeAssign(fVertexArray, vertexArray);
}
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) {
if (!fAbandoned) {
GrAlwaysAssert(0 == fObjects[i]->getRefCount());
GrAlwaysAssert(fObjects[i]->getDeleted());
}
}
}