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;
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
108
BBGE/Texture.cpp
108
BBGE/Texture.cpp
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue