Hi,

I have a problem with the fglrx driver. When doing simple things like showing a single texture, the driver takes somewhere between 300MB and 900MB. I think the memory is allocated from the kernel module, because the process shows small amount of memory used, but the free memory of the system decreases. I can see in /proc/meminfo that the "HighFree:" field decreases when I run a sample program. The decrease is relatively slow, at around 10MB/sec.

I am attaching the sample program so that it is seen exactly what I am doing. The program requires a parameter that tells it how many lines from the image to transfer at once. I noticed, that when the texture is loaded in smaller chunks (800kB or so) the problem dissapears. Only when I load the texture with chunks of 1MB or more the problem is seen.

In other words if the program is run with parameter 200 - no problem. If the parameter is 300 or more the problem appears.

Can someone see if I am doing something wrong or is this a bug in the driver? Is there a workaround in this situation?
Thanks, Venci

My hardware:
AMD Athlon Neo dual core 1.5GHz
Video card: ATI RADEON E4690
Memory: 3GB of RAM

Software configuration:
Debian Squeeze with linux 2.6.32 (32bit)
Ati catalyst driver 11.8
X.Org X Server 1.7.7
KDE 4.4.5

//compile with g++ -o mvplayer -lGL `sdl-config --libs` `sdl-config --cflags` -lSDL_image

mvplayer.cpp
#include <GL/glu.h>
#include <string>
#include <iostream>
#include "SDL.h"
#include <signal.h>
#include "SDL_image.h"
#include <cstdlib>
#include <cmath>

using namespace std;
static unsigned int MainLoopSleepTime = 15000;

void quitplayer(){ SDL_Quit(); exit(0); }

void sighandler(int sig) { quitplayer(); }

int main(int argc, char *argv[]) {

if (argc < 2) {
printf("mmoooo!\n");
exit(-1);
}

const int dy0 = atoi(argv[1]);
signal(SIGABRT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGINT, sighandler);
unsigned int nScreenWidth = 1280;
unsigned int nScreenHeight = 1024;

SDL_Init( SDL_INIT_EVERYTHING );

if (!( SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO)){ return 1; }

SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_Surface* screen = SDL_SetVideoMode(nScreenWidth, nScreenHeight, 24, SDL_OPENGL);

if ( screen == NULL ){
fprintf(stderr, "Couldn't set GL mode: %s", SDL_GetError());
SDL_Quit();
return 1;
}

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, nScreenWidth, nScreenHeight, 0, 0, -10000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glAlphaFunc(GL_GREATER,0.1f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

SDL_Surface* image[4];
image[0] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1);
// image[1] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1);
// image[2] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1);
// image[3] = IMG_Load_RW(SDL_RWFromFile("Untitled-1_02.png", "rb"), 1);

GLuint arrGlTexIds[100];
srand(time(NULL));
glGenTextures( 1, arrGlTexIds );
glBindTexture(GL_TEXTURE_2D, arrGlTexIds[0]);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, image[0]->w, image[0]->h, 0, GL_RGB, GL_UNSIGNED_BYTE, image[0]->pixels); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R, GL_NEAREST);

int sz = 3 * image[0]->w * dy0;
printf("--> max transfer: %d %.3f MiB\n", sz, sz / pow(2.0,20));

while(1) {
// SDL_PumpEvents();
glBindTexture(GL_TEXTURE_2D, arrGlTexIds[0]);
for (int i=0; ; i++) {
int dy = dy0; int y = dy0 * i;
if ((y + dy) > image[0]->h) dy = image[0]->h - y;
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, image[0]->w, dy, GL_RGB, GL_UNSIGNED_BYTE, image[0]->pixels + 3*(image[0]->w * y));
if ( y + dy >= image[0]->h ) break;
}

glBegin(GL_QUADS);
glTexCoord2d(0.0,0.0);
glVertex2i(0, 0);
glTexCoord2d(1.0,0.0);
glVertex2i(0 + image[0]->w, 0);
glTexCoord2d(1.0,1.0);
glVertex2i(0 + image[0]->w, 0 + image[0]->h);
glTexCoord2d(0.0,1.0);
glVertex2i(0, 0 + image[0]->h);
glEnd();

SDL_GL_SwapBuffers();

usleep(10000);
}
}