1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-12-25 14:15:46 +00:00

Moved most uses of glGetTexImage() into a single function with better error checking.

Also small config addition to optionally increase memory allocation size
for temporary texture pixel data; the nouveau drivers seem notoriously
awkward and keep writing over the buffer.
This commit is contained in:
fgenesis 2012-06-15 04:12:20 +02:00
parent 5b7757530f
commit 063b1c0dfc
6 changed files with 123 additions and 72 deletions

View file

@ -1971,30 +1971,13 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
h2/=TILE_SIZE;
tpos.x -= w2;
tpos.y -= h2;
GLuint id = q->texture->textures[0];
int w = 0, h = 0;
glBindTexture(GL_TEXTURE_2D, id);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &c);// assume 4
unsigned int size = w*h*4;
if (!size || w <= 0 || h <= 0)
return;
unsigned char *data = (unsigned char*)malloc(size + 6);
memcpy(data + size, "SAFE", 5);
unsigned int size = 0;
unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
if (!data)
{
errorLog("Game::fillGridFromQuad allocation failure");
return;
}
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
// Not sure but this might be the case with nouveau drivers on linux... still investigating. -- fg
if(memcmp(data + size, "SAFE", 5))
{
errorLog("Game::fillGridFromQuad(): Broken graphics driver! Wrote past end of buffer!");
free(data); // in case we are here, this will most likely cause a crash.
debugLog("Failed to get buffer in Game::fillGridFromQuad()");
return;
}
@ -2041,11 +2024,7 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
}
}
if (data)
{
free(data);
data = 0;
}
free(data);
if (trim)
{
@ -2803,25 +2782,15 @@ void Game::generateCollisionMask(Quad *q, int overrideCollideRadius)
h2/=TILE_SIZE;
tpos.x -= w2;
tpos.y -= h2;
GLuint id = q->texture->textures[0];
int w = 0, h = 0;
glBindTexture(GL_TEXTURE_2D, id);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &c);// assume 4
unsigned int size = w*h*4;
if (!size || w <= 0 || h <= 0)
return;
unsigned char *data = (unsigned char*)malloc(size);
unsigned int size = 0;
unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
if (!data)
{
debugLog("Could not malloc in Game::generateCollisionMask");
debugLog("Failed to get buffer in Game::generateCollisionMask()");
return;
}
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
q->collisionMaskRadius = 0;
@ -2865,6 +2834,10 @@ void Game::generateCollisionMask(Quad *q, int overrideCollideRadius)
}
}
q->collisionMaskRadius = 512;
free(data);
/*
for (int i = 0; i < q->collisionMask.size(); i++)
@ -2887,10 +2860,7 @@ void Game::generateCollisionMask(Quad *q, int overrideCollideRadius)
q->collisionMaskRadius = h2*2;
*/
//q->collisionMaskRadius = sqrtf(sqr(w2)+sqr(h2));
q->collisionMaskRadius = 512;
glBindTexture(GL_TEXTURE_2D, 0);
free(data);
/*
int rot = rotation.z;
while (rot > 360)

View file

@ -274,6 +274,12 @@ void UserSettings::save()
}
doc.InsertEndChild(xml_net);
TiXmlElement xml_debug("Debug");
{
xml_debug.SetAttribute("textureMemoryMultiplier", debug.textureMemoryMultiplier);
}
doc.InsertEndChild(xml_debug);
}
#if defined(BBGE_BUILD_UNIX)
@ -555,7 +561,15 @@ void UserSettings::load(bool doApply, const std::string &overrideFile)
TiXmlElement *xml_net = doc.FirstChildElement("Network");
if (xml_net)
{
network.masterServer = xml_net->Attribute("masterServer");
const char *serv = xml_net->Attribute("masterServer");
if (serv)
network.masterServer = serv;
}
TiXmlElement *xml_debug = doc.FirstChildElement("Debug");
if (xml_debug)
{
xml_debug->Attribute("textureMemoryMultiplier", &debug.textureMemoryMultiplier);
}
if (system.locale.empty())
@ -603,6 +617,10 @@ void UserSettings::apply()
dsq->bindInput();
core->settings.prebufferSounds = audio.prebuffer;
if (debug.textureMemoryMultiplier >= 1)
Texture::textureMemoryMultiplier = debug.textureMemoryMultiplier;
#endif
}

View file

@ -178,6 +178,12 @@ public:
std::string masterServer;
} network;
struct Debug
{
Debug() { textureMemoryMultiplier = 1; }
int textureMemoryMultiplier;
} debug;
void loadDefaults(bool doApply=true);
void load(bool doApply=true, const std::string &overrideFile="");
void save();

View file

@ -1903,6 +1903,7 @@ bool Core::initGraphicsLibrary(int width, int height, bool fullscreen, int vsync
// putenv(), which takes a (char *), and freaks out newer GCC releases
// when you try to pass a (const!) string literal here... --ryan.
SDL_putenv((char *) "SDL_VIDEO_CENTERED=1");
SDL_putenv((char *) "LIBGL_DEBUG=verbose"); // temp, to track errors on linux with nouveau drivers.
if (recreate)
{

View file

@ -56,6 +56,8 @@ bool Texture::useMipMaps = true;
TexErr Texture::textureError = TEXERR_OK;
int Texture::textureMemoryMultiplier = 1;
Texture::Texture() : Resource()
{
#ifdef BBGE_BUILD_OPENGL
@ -195,22 +197,10 @@ int Texture::getPixelWidth()
{
#ifdef BBGE_BUILD_OPENGL
int w = 0, h = 0;
glBindTexture(GL_TEXTURE_2D, textures[0]);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &c);// assume 4
unsigned int size = w*h*4;
if (!size || w <= 0 || h <= 0)
return 0;
unsigned char *data = (unsigned char*)malloc(size*sizeof(char));
unsigned int size = 0;
unsigned char *data = getBufferAndSize(&w, &h, &size);
if (!data)
{
debugLog("Texture::getPixelWidth() malloc failed");
return 0;
}
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
int smallestx = -1, largestx = -1;
for (unsigned int x = 0; x < unsigned(w); x++)
@ -227,7 +217,6 @@ int Texture::getPixelWidth()
}
}
}
glBindTexture(GL_TEXTURE_2D, 0);
free(data);
return largestx - smallestx;
#elif defined(BBGE_BUILD_DIRECTX)
@ -239,20 +228,11 @@ int Texture::getPixelHeight()
{
#ifdef BBGE_BUILD_OPENGL
int w = 0, h = 0;
glBindTexture(GL_TEXTURE_2D, textures[0]);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
//glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_COMPONENTS, &c);// assume 4
unsigned int size = w*h*4;
if (!size || w <= 0 || h <= 0)
return 0;
unsigned char *data = (unsigned char*)malloc(size*sizeof(char));
unsigned int size = 0;
unsigned char *data = getBufferAndSize(&w, &h, &size);
if (!data)
{
debugLog("Texture::getPixelHeight() malloc failed");
return 0;
}
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
int smallesty = -1, largesty = -1;
for (unsigned int x = 0; x < unsigned(w); x++)
{
@ -268,7 +248,6 @@ int Texture::getPixelHeight()
}
}
}
glBindTexture(GL_TEXTURE_2D, 0);
free(data);
return largesty - smallesty;
#elif defined(BBGE_BUILD_DIRECTX)
@ -827,3 +806,76 @@ ImageTGA *Texture::TGAloadMem(void *mem, int size)
return pImageData;
}
// ceil to next power of 2
static unsigned int clp2(unsigned int x)
{
--x;
x |= (x >> 1);
x |= (x >> 2);
x |= (x >> 4);
x |= (x >> 8);
x |= (x >> 16);
return x + 1;
}
unsigned char * Texture::getBufferAndSize(int *wparam, int *hparam, unsigned int *sizeparam)
{
// This can't happen. If it does we're doomed.
if(width <= 0 || height <= 0)
goto fail;
glBindTexture(GL_TEXTURE_2D, textures[0]);
// As returned by graphics driver
int w = 0, h = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
// As we know it - but round to nearest power of 2 OpenGL does this internally anyways.
int tw = clp2(width); // known to be > 0.
int th = clp2(height);
if (w != tw || h != th)
{
debugLog("Texture::getBufferAndSize() WARNING: width/height disagree");
// choose max. for size calculation
w = w > tw ? w : tw;
h = h > th ? h : th;
}
unsigned int size = w * h * 4 * textureMemoryMultiplier;
if (!size)
goto fail;
unsigned char *data = (unsigned char*)malloc(size + 32);
memcpy(data + size, "SAFE", 5);
if (!data)
{
std::ostringstream os;
os << "Game::fillGridFromQuad allocation failure, size = " << size;
errorLog(os.str());
goto fail;
}
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glBindTexture(GL_TEXTURE_2D, 0);
// Not sure but this might be the case with nouveau drivers on linux... still investigating. -- fg
if(memcmp(data + size, "SAFE", 5))
{
errorLog("Texture::getBufferAndSize(): Broken graphics driver! Wrote past end of buffer!");
free(data); // in case we are here, this will most likely cause a crash.
goto fail;
}
*wparam = w;
*hparam = h;
*sizeparam = size;
return data;
fail:
*wparam = 0;
*hparam = 0;
*sizeparam = 0;
return NULL;
}

View file

@ -80,6 +80,10 @@ public:
void write(int tx, int ty, int w, int h, const unsigned char *pixels);
void read(int tx, int ty, int w, int h, unsigned char *pixels);
unsigned char *getBufferAndSize(int *w, int *h, unsigned int *size); // returned memory must be free()'d
static int textureMemoryMultiplier; // 1. More for buggy drivers.
protected:
std::string loadName;