Here's what's happening in my game: I'll start my game up and load a level. This takes up about 40 megs of system memory. When I exit the level, I call glDeleteTextures on all my textures. The 40 megs will still be used by my game, but this isn't the problem. When I load the exact same level, my game will use 50 megs instead of 40. I'll repeat this process and the memory usage will go up 10 megs every time. I can completely drain all my system memory by doing this. (Because of this, I don't think it's a problem with Java garbage collection. I'd probably throw an OutOfMemoryException long before I drained my system memory). All the memory will be given back when the game closes.
What I think is happening is that I'm doing something stupid when I load my textures. I'd really appreciate any help.
here's my texture loading code:
public Texture loadTexture(String name, boolean DXT1, boolean need_bitmask)
{
Texture t = null;
boolean loaded = textureWasLoaded(name);
boolean has_mask = textureHasBitmask(name);
if(!loaded || (need_bitmask && !has_mask))
{
IntBuffer image = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
IL.ilGenImages(image);
IL.ilBindImage(image.get(0));
int il_handle = image.get(0);
IL.ilLoadImage(name);
int texture_width = IL.ilGetInteger(IL.IL_IMAGE_WIDTH);
int texture_height = IL.ilGetInteger(IL.IL_IMAGE_HEIGHT);
if(lowResolutionTextures && !need_bitmask)
{ ILU.iluScale(IL.ilGetInteger(IL.IL_IMAGE_WIDTH)/2,IL.ilGetInteger(IL.IL_IMAGE_HEIGHT)/2,IL.ilGetInteger(IL.IL_IMAGE_BPP));
}
ByteBuffer scratch = ByteBuffer.allocateDirect(IL.ilGetInteger(IL.IL_IMAGE_WIDTH) * IL.ilGetInteger(IL.IL_IMAGE_HEIGHT) * 4);
IL.ilCopyPixels(0, 0, 0, IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 1, IL.IL_RGBA, IL.IL_BYTE, scratch);
if(!loaded)
{
int texture_pointer = loadIntoGL(scratch,DXT1);
t = new Texture(texture_width, texture_height, name, texture_pointer);
textureMap.put(name,t);
}
else
{
t = textureMap.get(name);
}
if(need_bitmask && !has_mask)
{
ByteBuffer bitmask_data = IL.ilGetData();
boolean bitmask[][] = createBitmask(t.getWidth(),t.getHeight(),bitmask_data);
t.setBitmask(bitmask);
}
image.put(0, il_handle);
IL.ilDeleteImages(image);
}
else
{
t = textureMap.get(name);
}
return t;
}
//actually loads the texture into openGL, returns the pointer to the texture data
private int loadIntoGL(ByteBuffer scratch, boolean DXT1)
{
IntBuffer buf = ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
GL11.glGenTextures(buf); // Create Texture In OpenGL
GL11.glBindTexture(GL11.GL_TEXTURE_2D, buf.get(0));
//linear filtering
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
ContextCapabilities cc = GLContext.getCapabilities();
if(cc.GL_EXT_texture_compression_s3tc)
{
if(DXT1)
{
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,
EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}
else
{
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0,
EXTTextureCompressionS3TC.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
IL.ilGetInteger(IL.IL_IMAGE_WIDTH), IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0,
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}
}
else
{
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, IL.ilGetInteger(IL.IL_IMAGE_WIDTH),
IL.ilGetInteger(IL.IL_IMAGE_HEIGHT), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, scratch);
}
buf.clear();
return buf.get(0);
}
Looks fine to me...
The only thing that I can see that might do what you are seeing is this:
image.put(0, il_handle)
might need to be:
image.put(0, il_handle).rewind()
But that seems unlikely as I think it throws an exception if this is not the case :lol:
Maybe someone else has some more insights :wink:
I found the problem. My texture loading code is fine. The problem was that when I put my openGL texture handle integers in an IntBuffer, I wasn't calling the "rewind()" method on the buffer before I passed it to "glDeleteTextures()".
Thanks, I woulnd't have thought of trying that without your post. :D