In the course of my application I create a 2048x2048 texture which then gets updated periodically. Every few times this texture gets updated via a glTexSubImage2D call there is a significant hit on the available memory of the system which never appears to be released.
I’ve attached a full application that demonstrates how I’m using this texture in my real application and having tested it find that this has the same memory issue as my real application. Can anyone see something I’m not doing properly that might account for this memory growth?
#define GL_GLEXT_PROTOTYPES
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
GLuint texid(0);
unsigned char rawTex[2048*2048*3];
int totalMem(0), freeMem(0);
void GetMemUsage (void)
{
unsigned char rawData[512];
memset(rawData, 0, sizeof(rawData));
fstream f;
f.open("/proc/meminfo", ios::in|ios::binary);
if (f.is_open()) {
f.read((char*) rawData, 512);
f.close();
char *ptr(0);
ptr = strstr((char*)rawData, (const char*)"MemTotal:");
if (ptr != 0) {
totalMem = atoi(ptr+strlen("MemTotal:"));
}
ptr = 0;
ptr = strstr((char*) rawData, (const char*)"MemFree:");
if (ptr != 0) {
freeMem = atoi(ptr+strlen("MemFree:"));
}
}
}
void SetBitmap(void)
{
static int init(0);
if (!init) {
memset(rawTex, 0xA0, sizeof(rawTex));
} else {
memset(rawTex, 0xFF, sizeof(rawTex));
}
init ^= 1;
}
void Display (void)
{
char txtString[120];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texid);
glBegin(GL_TRIANGLES);
glTexCoord2f(0.0, 0.0);
glVertex2f(-1, 0);
glTexCoord2f(0.0, 1.0);
glVertex2f(-1, 1);
glTexCoord2f(1.0, 0.0);
glVertex2f(0, 0);
glTexCoord2f(0.0, 1.0);
glVertex2f(-1, 1);
glTexCoord2f(1.0, 0.0);
glVertex2f(0, 0);
glTexCoord2f(1.0, 1.0);
glVertex2f(0, 1);
glEnd();
glDisable(GL_TEXTURE_2D);
GetMemUsage();
snprintf(txtString, 120, "Total(%d) Free(%d) Per(%f)", totalMem, freeMem, freeMem / ((float) totalMem));
glRasterPos2i(0, 0);
glColor4f(1.0f, 0.0f, 1.0f, 1.0f);
glutBitmapString(GLUT_BITMAP_HELVETICA_18, (const unsigned char*) txtString);
glutSwapBuffers();
glutPostRedisplay();
return;
}
void Keyboard(unsigned char key, int x, int y)
{
switch(key) {
case 'n':
SetBitmap();
glBindTexture(GL_TEXTURE_2D, texid); // Bind the texture
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2048, 2048, GL_RGB, GL_UNSIGNED_BYTE, rawTex);
break;
default:
break;
}
return;
}
void InitTexture (void)
{
// Initially Load the texture
glGenTextures(1, &texid); // Creates the texture
glBindTexture(GL_TEXTURE_2D, texid); // Bind the texture
/*
* Set edge handling
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
/*
* Set filtering
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/*
* Upload the texture to GL
*/
glTexImage2D(GL_TEXTURE_2D, // 2D Texture
0, // level
GL_RGB, // internal formal
2048, // width
2048, // height
0, // border
GL_RGB, // format
GL_UNSIGNED_BYTE, // type
rawTex); // data
}
int main (int argc, char *argv[])
{
GLint mainWindow;
glutInit (&argc, argv);
SetBitmap();
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize (1024, 768);
mainWindow = glutCreateWindow("Texture Test");
glutDisplayFunc(Display);
glutKeyboardFunc(Keyboard);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glEnable(GL_NORMALIZE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glCullFace(GL_FRONT);
InitTexture();
glutPostRedisplay();
glutMainLoop();
cout << "Freeing Memory!" << endl;
glDeleteTextures(1, &texid);
return 0;
}