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:
parent
5b7757530f
commit
063b1c0dfc
6 changed files with 123 additions and 72 deletions
|
@ -1971,30 +1971,13 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
|
||||||
h2/=TILE_SIZE;
|
h2/=TILE_SIZE;
|
||||||
tpos.x -= w2;
|
tpos.x -= w2;
|
||||||
tpos.y -= h2;
|
tpos.y -= h2;
|
||||||
GLuint id = q->texture->textures[0];
|
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
unsigned int size = 0;
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
|
||||||
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);
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
errorLog("Game::fillGridFromQuad allocation failure");
|
debugLog("Failed to get buffer in Game::fillGridFromQuad()");
|
||||||
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.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2041,11 +2024,7 @@ void Game::fillGridFromQuad(Quad *q, ObsType obsType, bool trim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data)
|
free(data);
|
||||||
{
|
|
||||||
free(data);
|
|
||||||
data = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trim)
|
if (trim)
|
||||||
{
|
{
|
||||||
|
@ -2803,25 +2782,15 @@ void Game::generateCollisionMask(Quad *q, int overrideCollideRadius)
|
||||||
h2/=TILE_SIZE;
|
h2/=TILE_SIZE;
|
||||||
tpos.x -= w2;
|
tpos.x -= w2;
|
||||||
tpos.y -= h2;
|
tpos.y -= h2;
|
||||||
GLuint id = q->texture->textures[0];
|
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
unsigned int size = 0;
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
unsigned char *data = q->texture->getBufferAndSize(&w, &h, &size);
|
||||||
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);
|
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
{
|
||||||
debugLog("Could not malloc in Game::generateCollisionMask");
|
debugLog("Failed to get buffer in Game::generateCollisionMask()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
q->collisionMaskRadius = 0;
|
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++)
|
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 = h2*2;
|
||||||
*/
|
*/
|
||||||
//q->collisionMaskRadius = sqrtf(sqr(w2)+sqr(h2));
|
//q->collisionMaskRadius = sqrtf(sqr(w2)+sqr(h2));
|
||||||
q->collisionMaskRadius = 512;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
free(data);
|
|
||||||
/*
|
/*
|
||||||
int rot = rotation.z;
|
int rot = rotation.z;
|
||||||
while (rot > 360)
|
while (rot > 360)
|
||||||
|
|
|
@ -274,6 +274,12 @@ void UserSettings::save()
|
||||||
}
|
}
|
||||||
doc.InsertEndChild(xml_net);
|
doc.InsertEndChild(xml_net);
|
||||||
|
|
||||||
|
TiXmlElement xml_debug("Debug");
|
||||||
|
{
|
||||||
|
xml_debug.SetAttribute("textureMemoryMultiplier", debug.textureMemoryMultiplier);
|
||||||
|
}
|
||||||
|
doc.InsertEndChild(xml_debug);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BBGE_BUILD_UNIX)
|
#if defined(BBGE_BUILD_UNIX)
|
||||||
|
@ -555,7 +561,15 @@ void UserSettings::load(bool doApply, const std::string &overrideFile)
|
||||||
TiXmlElement *xml_net = doc.FirstChildElement("Network");
|
TiXmlElement *xml_net = doc.FirstChildElement("Network");
|
||||||
if (xml_net)
|
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())
|
if (system.locale.empty())
|
||||||
|
@ -603,6 +617,10 @@ void UserSettings::apply()
|
||||||
dsq->bindInput();
|
dsq->bindInput();
|
||||||
|
|
||||||
core->settings.prebufferSounds = audio.prebuffer;
|
core->settings.prebufferSounds = audio.prebuffer;
|
||||||
|
|
||||||
|
if (debug.textureMemoryMultiplier >= 1)
|
||||||
|
Texture::textureMemoryMultiplier = debug.textureMemoryMultiplier;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,12 @@ public:
|
||||||
std::string masterServer;
|
std::string masterServer;
|
||||||
} network;
|
} network;
|
||||||
|
|
||||||
|
struct Debug
|
||||||
|
{
|
||||||
|
Debug() { textureMemoryMultiplier = 1; }
|
||||||
|
int textureMemoryMultiplier;
|
||||||
|
} debug;
|
||||||
|
|
||||||
void loadDefaults(bool doApply=true);
|
void loadDefaults(bool doApply=true);
|
||||||
void load(bool doApply=true, const std::string &overrideFile="");
|
void load(bool doApply=true, const std::string &overrideFile="");
|
||||||
void save();
|
void save();
|
||||||
|
|
|
@ -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
|
// putenv(), which takes a (char *), and freaks out newer GCC releases
|
||||||
// when you try to pass a (const!) string literal here... --ryan.
|
// when you try to pass a (const!) string literal here... --ryan.
|
||||||
SDL_putenv((char *) "SDL_VIDEO_CENTERED=1");
|
SDL_putenv((char *) "SDL_VIDEO_CENTERED=1");
|
||||||
|
SDL_putenv((char *) "LIBGL_DEBUG=verbose"); // temp, to track errors on linux with nouveau drivers.
|
||||||
|
|
||||||
if (recreate)
|
if (recreate)
|
||||||
{
|
{
|
||||||
|
|
108
BBGE/Texture.cpp
108
BBGE/Texture.cpp
|
@ -56,6 +56,8 @@ bool Texture::useMipMaps = true;
|
||||||
|
|
||||||
TexErr Texture::textureError = TEXERR_OK;
|
TexErr Texture::textureError = TEXERR_OK;
|
||||||
|
|
||||||
|
int Texture::textureMemoryMultiplier = 1;
|
||||||
|
|
||||||
Texture::Texture() : Resource()
|
Texture::Texture() : Resource()
|
||||||
{
|
{
|
||||||
#ifdef BBGE_BUILD_OPENGL
|
#ifdef BBGE_BUILD_OPENGL
|
||||||
|
@ -195,22 +197,10 @@ int Texture::getPixelWidth()
|
||||||
{
|
{
|
||||||
#ifdef BBGE_BUILD_OPENGL
|
#ifdef BBGE_BUILD_OPENGL
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
unsigned int size = 0;
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
unsigned char *data = getBufferAndSize(&w, &h, &size);
|
||||||
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));
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
|
||||||
debugLog("Texture::getPixelWidth() malloc failed");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
||||||
|
|
||||||
int smallestx = -1, largestx = -1;
|
int smallestx = -1, largestx = -1;
|
||||||
for (unsigned int x = 0; x < unsigned(w); x++)
|
for (unsigned int x = 0; x < unsigned(w); x++)
|
||||||
|
@ -227,7 +217,6 @@ int Texture::getPixelWidth()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
free(data);
|
free(data);
|
||||||
return largestx - smallestx;
|
return largestx - smallestx;
|
||||||
#elif defined(BBGE_BUILD_DIRECTX)
|
#elif defined(BBGE_BUILD_DIRECTX)
|
||||||
|
@ -239,20 +228,11 @@ int Texture::getPixelHeight()
|
||||||
{
|
{
|
||||||
#ifdef BBGE_BUILD_OPENGL
|
#ifdef BBGE_BUILD_OPENGL
|
||||||
int w = 0, h = 0;
|
int w = 0, h = 0;
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[0]);
|
unsigned int size = 0;
|
||||||
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
|
unsigned char *data = getBufferAndSize(&w, &h, &size);
|
||||||
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));
|
|
||||||
if (!data)
|
if (!data)
|
||||||
{
|
|
||||||
debugLog("Texture::getPixelHeight() malloc failed");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
||||||
int smallesty = -1, largesty = -1;
|
int smallesty = -1, largesty = -1;
|
||||||
for (unsigned int x = 0; x < unsigned(w); x++)
|
for (unsigned int x = 0; x < unsigned(w); x++)
|
||||||
{
|
{
|
||||||
|
@ -268,7 +248,6 @@ int Texture::getPixelHeight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
free(data);
|
free(data);
|
||||||
return largesty - smallesty;
|
return largesty - smallesty;
|
||||||
#elif defined(BBGE_BUILD_DIRECTX)
|
#elif defined(BBGE_BUILD_DIRECTX)
|
||||||
|
@ -827,3 +806,76 @@ ImageTGA *Texture::TGAloadMem(void *mem, int size)
|
||||||
return pImageData;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -80,6 +80,10 @@ public:
|
||||||
|
|
||||||
void write(int tx, int ty, int w, int h, const unsigned char *pixels);
|
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);
|
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:
|
protected:
|
||||||
std::string loadName;
|
std::string loadName;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue