/* * Small program creating 1000 small textures, meant to show that Vendor : Tungsten Graphics, Inc Renderer : Mesa DRI Intel(R) 915GM GEM 20100330 DEVELOPMENT x86/MMX/SSE2 Version : 1.4 Mesa 7.9 is not handling texture memory properly. On my computer, the 1000 64x64 textures that should be 20MB in size have the driver take up to 1GB of memory (readings taken by top). Increasing this will trigger a OOM-kill by the Kernel (after 1800 textures with 2GB of memory). Compile with: gcc a.c -o a -g -lGL This program is based on https://bugs.freedesktop.org/attachment.cgi?id=28923, but the bug is completely unrelated. */ #include #include #include #include #include #include static void create_window (Display *dpy, const char *name, int x, int y, int width, int height, Window *window, GLXContext *context) { int attrib[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, None }; int scrnum; XSetWindowAttributes attr; unsigned long mask; Window root; Window win; GLXContext ctx; XVisualInfo *visinfo; XSizeHints sizehints; scrnum = DefaultScreen (dpy); root = RootWindow (dpy, scrnum); visinfo = glXChooseVisual (dpy, scrnum, attrib); if (!visinfo) { fprintf (stderr, "error: cannot get an RGB double-buffered visual\n"); exit (1); } attr.background_pixel = 0; attr.border_pixel = 0; attr.colormap = XCreateColormap (dpy, root, visinfo->visual, AllocNone); attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; win = XCreateWindow (dpy, root, 0, 0, width, height, 0, visinfo->depth, InputOutput, visinfo->visual, mask, &attr); sizehints.x = x; sizehints.y = y; sizehints.width = width; sizehints.height = height; sizehints.flags = USSize | USPosition; XSetNormalHints (dpy, win, &sizehints); XSetStandardProperties (dpy, win, name, name, None, (char**) NULL, 0, &sizehints); ctx = glXCreateContext (dpy, visinfo, NULL, True); if (!ctx) { fprintf (stderr, "error: glXCreateContext failed\n"); exit (1); } XFree (visinfo); *window = win; *context = ctx; } static void loop (Display *dpy, Window win) { unsigned int i, tex; unsigned int *buffer; int count = 0; buffer = malloc ( 64 * 64 * 4); for (i = 0; i < 64 * 64; i++) buffer[i] = 0xFFFF0000; while (count++ < 3000) { while (XPending (dpy) > 0) { XEvent event; XNextEvent (dpy, &event); switch (event.type) { case Expose: break; case ConfigureNotify: glViewport (0, 0, event.xconfigure.width, event.xconfigure.height); break; default: break; } } /* Create a 64x64 RGBA texture */ glGenTextures (1, &tex); glBindTexture (GL_TEXTURE_2D, tex); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*) buffer); printf("Created %d textures\n", count); } free (buffer); } int main (int argc, char *argv[]) { Display *dpy; Window win; GLXContext ctx; dpy = XOpenDisplay (NULL); if (!dpy) { fprintf (stderr, "error: cannot open display\n"); return -1; } /* Create the X11 window and OpenGL context */ create_window (dpy, "i965 texture handling mem leak", 0, 0, 400, 400, &win, &ctx); XMapWindow (dpy, win); glXMakeCurrent (dpy, win, ctx); /* Initialize some states */ glMatrixMode (GL_PROJECTION); glLoadIdentity (); glOrtho (0.0f, 1.0f, 0.0f, 1.0f, 0.5f, -0.5f); glMatrixMode (GL_MODELVIEW); glViewport (0, 0, 512, 512); glEnable (GL_TEXTURE_2D); /* Enter the rendering loop */ loop (dpy, win); glXDestroyContext (dpy, ctx); XDestroyWindow (dpy, win); XCloseDisplay (dpy); return 0; }