xm_buffer.c revision 374e7fd6cc95d3d91629a6e1c951d77e8a29c31c
1e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/* 2e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Mesa 3-D graphics library 3d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Version: 6.5.2 4e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * 5d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 6e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * 7e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a 8e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * copy of this software and associated documentation files (the "Software"), 9e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * to deal in the Software without restriction, including without limitation 10e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * and/or sell copies of the Software, and to permit persons to whom the 12e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * Software is furnished to do so, subject to the following conditions: 13e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * 14e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * The above copyright notice and this permission notice shall be included 15e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * in all copies or substantial portions of the Software. 16e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * 17e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */ 24e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 25e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 26d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/** 27d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * \file xm_buffer.h 28d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Framebuffer and renderbuffer-related functions. 29d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */ 30d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 31d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 32e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul#include "glxheader.h" 33e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul#include "GL/xmesa.h" 34e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul#include "xmesaP.h" 35374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/imports.h" 36374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/framebuffer.h" 37374e7fd6cc95d3d91629a6e1c951d77e8a29c31cBrian Paul#include "main/renderbuffer.h" 38e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 39e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 407439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis#if defined(USE_XSHM) && !defined(XFree86Server) 41d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic volatile int mesaXErrorFlag = 0; 42d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 43d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/** 44d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Catches potential Xlib errors. 45d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */ 46d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic int 47d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian PaulmesaHandleXError(XMesaDisplay *dpy, XErrorEvent *event) 48d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{ 49d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul (void) dpy; 50d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul (void) event; 51d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul mesaXErrorFlag = 1; 52d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return 0; 53d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul} 54d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 55d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/** 56d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Allocate a shared memory XImage back buffer for the given XMesaBuffer. 57d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Return: GL_TRUE if success, GL_FALSE if error 58d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */ 59d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic GLboolean 60d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulalloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height) 61d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{ 62d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* 63d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * We have to do a _lot_ of error checking here to be sure we can 64d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * really use the XSHM extension. It seems different servers trigger 65d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * errors at different points if the extension won't work. Therefore 66d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * we have to be very careful... 67d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */ 68d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul GC gc; 69d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul int (*old_handler)(XMesaDisplay *, XErrorEvent *); 70d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 71d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (width == 0 || height == 0) { 72d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* this will be true the first time we're called on 'b' */ 73d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 74d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 75d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 76d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = XShmCreateImage(b->xm_visual->display, 77d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->xm_visual->visinfo->visual, 78d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->xm_visual->visinfo->depth, 79d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul ZPixmap, NULL, &b->shminfo, 80d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul width, height); 81d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->backxrb->ximage == NULL) { 82d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling.\n"); 83d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shm = 0; 84d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 85d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 86d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 87d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shminfo.shmid = shmget(IPC_PRIVATE, b->backxrb->ximage->bytes_per_line 88d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * b->backxrb->ximage->height, IPC_CREAT|0777); 89d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->shminfo.shmid < 0) { 90d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "shmget failed while allocating back buffer.\n"); 91d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XDestroyImage(b->backxrb->ximage); 92d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 93d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling.\n"); 94d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shm = 0; 95d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 96d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 97d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 98d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shminfo.shmaddr = b->backxrb->ximage->data 99d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul = (char*)shmat(b->shminfo.shmid, 0, 0); 100d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->shminfo.shmaddr == (char *) -1) { 101d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "shmat() failed while allocating back buffer.\n"); 102d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XDestroyImage(b->backxrb->ximage); 103d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmctl(b->shminfo.shmid, IPC_RMID, 0); 104d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 105d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling.\n"); 106d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shm = 0; 107d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 108d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 109d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 110d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shminfo.readOnly = False; 111d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul mesaXErrorFlag = 0; 112d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul old_handler = XSetErrorHandler(mesaHandleXError); 113d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* This may trigger the X protocol error we're ready to catch: */ 114d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XShmAttach(b->xm_visual->display, &b->shminfo); 115d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XSync(b->xm_visual->display, False); 116d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 117d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (mesaXErrorFlag) { 118d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* we are on a remote display, this error is normal, don't print it */ 119d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XFlush(b->xm_visual->display); 120d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul mesaXErrorFlag = 0; 121d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XDestroyImage(b->backxrb->ximage); 122d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmdt(b->shminfo.shmaddr); 123d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmctl(b->shminfo.shmid, IPC_RMID, 0); 124d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 125d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shm = 0; 126d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul (void) XSetErrorHandler(old_handler); 127d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 128d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 129d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 130d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmctl(b->shminfo.shmid, IPC_RMID, 0); /* nobody else needs it */ 131d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 132d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Finally, try an XShmPutImage to be really sure the extension works */ 133d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul gc = XCreateGC(b->xm_visual->display, b->frontxrb->drawable, 0, NULL); 134d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XShmPutImage(b->xm_visual->display, b->frontxrb->drawable, gc, 135d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False); 136d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XSync(b->xm_visual->display, False); 137d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XFreeGC(b->xm_visual->display, gc); 138d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul (void) XSetErrorHandler(old_handler); 139d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (mesaXErrorFlag) { 140d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XFlush(b->xm_visual->display); 141d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul mesaXErrorFlag = 0; 142d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XDestroyImage(b->backxrb->ximage); 143d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmdt(b->shminfo.shmaddr); 144d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmctl(b->shminfo.shmid, IPC_RMID, 0); 145d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 146d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->shm = 0; 147d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 148d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 149d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 150d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_TRUE; 1517439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis} 152d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#else 1537439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzisstatic GLboolean 1547439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzisalloc_back_shm_ximage(XMesaBuffer b, GLuint width, GLuint height) 1557439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis{ 156d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Can't compile XSHM support */ 157d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return GL_FALSE; 158d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul} 159d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#endif 160d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 161d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 162d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 163d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul/** 164d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Setup an off-screen pixmap or Ximage to use as the back buffer. 165d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * Input: b - the X/Mesa buffer 166d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul */ 167d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulstatic void 168d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paulalloc_back_buffer(XMesaBuffer b, GLuint width, GLuint height) 169d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul{ 170d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->db_mode == BACK_XIMAGE) { 171d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Deallocate the old backxrb->ximage, if any */ 172d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->backxrb->ximage) { 173d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#if defined(USE_XSHM) && !defined(XFree86Server) 174d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->shm) { 175d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XShmDetach(b->xm_visual->display, &b->shminfo); 176d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XDestroyImage(b->backxrb->ximage); 177d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul shmdt(b->shminfo.shmaddr); 178d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 179d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul else 180d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#endif 181d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XMesaDestroyImage(b->backxrb->ximage); 182d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 183d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 184d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 185e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian if (width == 0 || height == 0) 186e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian return; 187e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian 188d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Allocate new back buffer */ 189d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->shm == 0 || !alloc_back_shm_ximage(b, width, height)) { 190d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Allocate a regular XImage for the back buffer. */ 1917439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis#ifdef XFree86Server 1927439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis b->backxrb->ximage = XMesaCreateImage(b->xm_visual->BitsPerPixel, 1937439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis width, height, NULL); 1947439a36785b6a2783e80a40a96c09db8f56dc2bcGeorge Sapountzis#else 195d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = XCreateImage(b->xm_visual->display, 196d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->xm_visual->visinfo->visual, 197d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul GET_VISUAL_DEPTH(b->xm_visual), 198d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul ZPixmap, 0, /* format, offset */ 199d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul NULL, 200d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul width, height, 201d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 8, 0); /* pad, bytes_per_line */ 202d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul#endif 203d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (!b->backxrb->ximage) { 204d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed.\n"); 205d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul return; 206d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 207d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage->data = (char *) MALLOC(b->backxrb->ximage->height 208d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul * b->backxrb->ximage->bytes_per_line); 209d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (!b->backxrb->ximage->data) { 210d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed.\n"); 211d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul XMesaDestroyImage(b->backxrb->ximage); 212d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 213d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 214d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 215d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->pixmap = None; 216d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 217d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul else if (b->db_mode == BACK_PIXMAP) { 218d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* Free the old back pixmap */ 219d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul if (b->backxrb->pixmap) { 220e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian XMesaFreePixmap(b->xm_visual->display, b->backxrb->pixmap); 221e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian b->backxrb->pixmap = 0; 222d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 223e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian 224e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian if (width > 0 && height > 0) { 225e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian /* Allocate new back pixmap */ 226e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian b->backxrb->pixmap = XMesaCreatePixmap(b->xm_visual->display, 227e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian b->frontxrb->drawable, 228e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian width, height, 229e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian GET_VISUAL_DEPTH(b->xm_visual)); 230e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian } 231e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian 232d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul b->backxrb->ximage = NULL; 233d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul } 234d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul} 235d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 236d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 237e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic void 238e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulxmesa_delete_renderbuffer(struct gl_renderbuffer *rb) 239e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 240d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul /* XXX Note: the ximage or Pixmap attached to this renderbuffer 241d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul * should probably get freed here, but that's currently done in 242d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul * XMesaDestroyBuffer(). 243d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul */ 244d2e289c70f2b9fb882f5b3992b610a9ea5c8357cBrian Paul _mesa_free(rb); 245e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 246e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 247e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 248e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul/** 249692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul * Reallocate renderbuffer storage for front color buffer. 250e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian * Called via gl_renderbuffer::AllocStorage() 251e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul */ 252e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstatic GLboolean 253692147ebf7f09d56a7de1659de2449478da4d1baBrian Paulxmesa_alloc_front_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 254692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul GLenum internalFormat, GLuint width, GLuint height) 255e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 256444cd293fd69d1848b2c55f75674d563e0582fbaBrian Paul struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); 257e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 258692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul /* just clear these to be sure we don't accidentally use them */ 259692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->origin1 = NULL; 260692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->origin2 = NULL; 261e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->origin3 = NULL; 262692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->origin4 = NULL; 263692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 264692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul /* for the FLIP macro: */ 265692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->bottom = height - 1; 266692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 267692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul rb->Width = width; 268692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul rb->Height = height; 269692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul rb->InternalFormat = internalFormat; 270692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 271692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul return GL_TRUE; 272692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul} 273692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 274692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 275692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul/** 276692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul * Reallocate renderbuffer storage for back color buffer. 277e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian * Called via gl_renderbuffer::AllocStorage() 278692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul */ 279692147ebf7f09d56a7de1659de2449478da4d1baBrian Paulstatic GLboolean 280692147ebf7f09d56a7de1659de2449478da4d1baBrian Paulxmesa_alloc_back_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 281692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul GLenum internalFormat, GLuint width, GLuint height) 282692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul{ 283444cd293fd69d1848b2c55f75674d563e0582fbaBrian Paul struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb); 284692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 285d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* reallocate the back buffer XImage or Pixmap */ 286d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul assert(xrb->Parent); 287d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul alloc_back_buffer(xrb->Parent, width, height); 288d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul 289692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul /* same as front buffer */ 290d21fa9cd79e4198b673c1453b8bc05749f8a73ebBrian Paul /* XXX why is this here? */ 291692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul (void) xmesa_alloc_front_storage(ctx, rb, internalFormat, width, height); 292692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul 293692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul /* plus... */ 294e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul if (xrb->ximage) { 295e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul /* Needed by PIXELADDR1 macro */ 296e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->width1 = xrb->ximage->bytes_per_line; 297e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->origin1 = (GLubyte *) xrb->ximage->data + xrb->width1 * (height - 1); 298e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 299e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul /* Needed by PIXELADDR2 macro */ 300e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->width2 = xrb->ximage->bytes_per_line / 2; 301e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->origin2 = (GLushort *) xrb->ximage->data + xrb->width2 * (height - 1); 302e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 303e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul /* Needed by PIXELADDR3 macro */ 304e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->width3 = xrb->ximage->bytes_per_line; 305e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->origin3 = (GLubyte *) xrb->ximage->data + xrb->width3 * (height - 1); 306e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 307e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul /* Needed by PIXELADDR4 macro */ 308e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->width4 = xrb->ximage->width; 309e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->origin4 = (GLuint *) xrb->ximage->data + xrb->width4 * (height - 1); 310e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 311e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul else { 312e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian /* out of memory or buffer size is 0 x 0 */ 313e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->width1 = xrb->width2 = xrb->width3 = xrb->width4 = 0; 314e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->origin1 = NULL; 315e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->origin2 = NULL; 316e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->origin3 = NULL; 317e5070bc3ca75dee31034cc543f3d2ee04e5dc032Brian xrb->origin4 = NULL; 318e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 319e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 320e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul return GL_TRUE; 321e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 322e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 323e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 324e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paulstruct xmesa_renderbuffer * 3259e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paulxmesa_new_renderbuffer(GLcontext *ctx, GLuint name, const GLvisual *visual, 326692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul GLboolean backBuffer) 327e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul{ 328e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul struct xmesa_renderbuffer *xrb = CALLOC_STRUCT(xmesa_renderbuffer); 329e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul if (xrb) { 330e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul GLuint name = 0; 331e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul _mesa_init_renderbuffer(&xrb->Base, name); 332e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 333e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base.Delete = xmesa_delete_renderbuffer; 334692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul if (backBuffer) 335692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->Base.AllocStorage = xmesa_alloc_back_storage; 336692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul else 337692147ebf7f09d56a7de1659de2449478da4d1baBrian Paul xrb->Base.AllocStorage = xmesa_alloc_front_storage; 338e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 3399e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul if (visual->rgbMode) { 340e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base.InternalFormat = GL_RGBA; 341e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base._BaseFormat = GL_RGBA; 342e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base.DataType = GL_UNSIGNED_BYTE; 3439e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul xrb->Base.RedBits = visual->redBits; 3449e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul xrb->Base.GreenBits = visual->greenBits; 3459e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul xrb->Base.BlueBits = visual->blueBits; 3469e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul xrb->Base.AlphaBits = visual->alphaBits; 347e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 348e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul else { 349e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base.InternalFormat = GL_COLOR_INDEX; 350e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base._BaseFormat = GL_COLOR_INDEX; 351e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul xrb->Base.DataType = GL_UNSIGNED_INT; 3529e81d6ae3a6db9831d6aea0fe4d92722176e9f74Brian Paul xrb->Base.IndexBits = visual->indexBits; 353e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 354676d0accf5cc43e86057b14cfb8bba9316932582Brian Paul /* only need to set Red/Green/EtcBits fields for user-created RBs */ 355e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul } 356e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul return xrb; 357e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul} 358e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 359e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 360928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian/** 361928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian * Called via gl_framebuffer::Delete() method when this buffer 36259e56ee3e5c8f9aa9ec74e1817065a7ae14012eaBrian * is _really_ being deleted. 363928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian */ 364928a70e4354d4884e2918ec67ddc6d8baf942c8aBrianvoid 365928a70e4354d4884e2918ec67ddc6d8baf942c8aBrianxmesa_delete_framebuffer(struct gl_framebuffer *fb) 366928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian{ 367928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XMesaBuffer b = XMESA_BUFFER(fb); 368e4b2356c07d31fbeeabb13b2fb47db703b473080Brian Paul 369928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->num_alloced > 0) { 370928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian /* If no other buffer uses this X colormap then free the colors. */ 371928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (!xmesa_find_buffer(b->display, b->cmap, b)) { 372928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#ifdef XFree86Server 37347e0b606a85059ff29fe311dc2f1bcafdefe4cdbBrian int client = 0; 37447e0b606a85059ff29fe311dc2f1bcafdefe4cdbBrian if (b->frontxrb->drawable) 37547e0b606a85059ff29fe311dc2f1bcafdefe4cdbBrian client = CLIENT_ID(b->frontxrb->drawable->id); 376928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian (void)FreeColors(b->cmap, client, 377928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian b->num_alloced, b->alloced_colors, 0); 378928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#else 379928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XFreeColors(b->display, b->cmap, 380928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian b->alloced_colors, b->num_alloced, 0); 381928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#endif 382928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 383928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 384928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian 385928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->gc) 386e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XMesaFreeGC(b->display, b->gc); 387928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->cleargc) 388e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XMesaFreeGC(b->display, b->cleargc); 389928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->swapgc) 390e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XMesaFreeGC(b->display, b->swapgc); 391928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian 392e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian if (fb->Visual.doubleBufferMode) { 393928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian /* free back ximage/pixmap/shmregion */ 394928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->backxrb->ximage) { 395928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#if defined(USE_XSHM) && !defined(XFree86Server) 396928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->shm) { 397e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XShmDetach( b->display, &b->shminfo ); 398928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XDestroyImage( b->backxrb->ximage ); 399928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian shmdt( b->shminfo.shmaddr ); 400928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 401928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian else 402928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian#endif 403928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XMesaDestroyImage( b->backxrb->ximage ); 404928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian b->backxrb->ximage = NULL; 405928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 406928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->backxrb->pixmap) { 407e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XMesaFreePixmap( b->display, b->backxrb->pixmap ); 408928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->xm_visual->hpcr_clear_flag) { 409e812a2a484660c87383e7e7d8897a9bcf85cf9ccBrian XMesaFreePixmap( b->display, 410928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian b->xm_visual->hpcr_clear_pixmap ); 411928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); 412928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 413928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 414928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 415928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian 416928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian if (b->rowimage) { 417928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian _mesa_free( b->rowimage->data ); 418928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian b->rowimage->data = NULL; 419928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian XMesaDestroyImage( b->rowimage ); 420928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian } 421928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian 422928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian _mesa_free_framebuffer_data(fb); 423928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian _mesa_free(fb); 424928a70e4354d4884e2918ec67ddc6d8baf942c8aBrian} 425