X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fx11%2Fxm_api.c;h=edaa71508fc5713f430278fabe50b1c6dba8fe31;hb=fd54564f78d4aeae2c39ada7502ec659c14b3eca;hp=bdf6f1d42861090465ecaf2b4c1869c952161b9d;hpb=c45b7364dab6c3daebc1f1d8d11124af4129074a;p=mesa.git diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c index bdf6f1d4286..edaa71508fc 100644 --- a/src/mesa/drivers/x11/xm_api.c +++ b/src/mesa/drivers/x11/xm_api.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 7.1 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,8 +22,10 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* - * This file contains the implementations of all the XMesa* functions. +/** + * \file xm_api.c + * + * All the XMesa* API functions. * * * NOTES: @@ -65,34 +67,28 @@ #include "xmesaP.h" #include "context.h" #include "extensions.h" +#include "framebuffer.h" #include "glthread.h" #include "imports.h" -#include "matrix.h" -#include "mtypes.h" #include "macros.h" -#include "texformat.h" -#include "texobj.h" -#include "texstore.h" +#include "renderbuffer.h" +#include "teximage.h" #include "swrast/swrast.h" #include "swrast_setup/swrast_setup.h" -#include "array_cache/acache.h" +#include "vbo/vbo.h" #include "tnl/tnl.h" #include "tnl/t_context.h" #include "tnl/t_pipeline.h" #include "drivers/common/driverfuncs.h" -#ifdef XFree86Server -#include -#endif - -/* +/** * Global X driver lock */ _glthread_Mutex _xmesa_lock; -/* +/** * Lookup tables for HPCR pixel format: */ static short hpcr_rgbTbl[3][256] = { @@ -159,7 +155,7 @@ static short hpcr_rgbTbl[3][256] = { /**********************************************************************/ -/* +/** * Return the host's byte order as LSBFirst or MSBFirst ala X. */ #ifndef XFree86Server @@ -172,32 +168,15 @@ static int host_byte_order( void ) #endif -/* - * Error handling. - */ -#ifndef XFree86Server -static volatile int mesaXErrorFlag = 0; - -static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event ) -{ - (void) dpy; - (void) event; - mesaXErrorFlag = 1; - return 0; -} -#endif - - -/* +/** * Check if the X Shared Memory extension is available. * Return: 0 = not available * 1 = shared XImage support available * 2 = shared Pixmap support available also */ -#ifndef XFree86Server static int check_for_xshm( XMesaDisplay *display ) { -#ifdef USE_XSHM +#if defined(USE_XSHM) && !defined(XFree86Server) int major, minor, ignore; Bool pixmaps; @@ -213,40 +192,18 @@ static int check_for_xshm( XMesaDisplay *display ) return 0; } #else - /* Can't compile XSHM support */ + /* No XSHM support */ return 0; #endif } -#endif -/* - * Return the width and height of the given drawable. - */ -static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d, - unsigned int *width, unsigned int *height) -{ -#ifdef XFree86Server - (void) dpy; - *width = d->width; - *height = d->height; -#else - Window root; - int x, y; - unsigned int bw, depth; - - _glthread_LOCK_MUTEX(_xmesa_lock); - XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth ); - _glthread_UNLOCK_MUTEX(_xmesa_lock); -#endif -} - - -/* +/** * Apply gamma correction to an intensity value in [0..max]. Return the * new intensity value. */ -static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) +static GLint +gamma_adjust( GLfloat gamma, GLint value, GLint max ) { if (gamma == 1.0) { return value; @@ -259,7 +216,7 @@ static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) -/* +/** * Return the true number of bits per pixel for XImages. * For example, if we request a 24-bit deep visual we may actually need/get * 32bpp XImages. This function returns the appropriate bpp. @@ -267,23 +224,19 @@ static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) * visinfo - desribes the visual to be used for XImages * Return: true number of bits per pixel for XImages */ -#ifdef XFree86Server - -static int bits_per_pixel( XMesaVisual xmv ) +static int +bits_per_pixel( XMesaVisual xmv ) { +#ifdef XFree86Server const int depth = xmv->nplanes; int i; + assert(depth > 0); for (i = 0; i < screenInfo.numPixmapFormats; i++) { if (screenInfo.formats[i].depth == depth) return screenInfo.formats[i].bitsPerPixel; } return depth; /* should never get here, but this should be safe */ -} - #else - -static int bits_per_pixel( XMesaVisual xmv ) -{ XMesaDisplay *dpy = xmv->display; XMesaVisualInfo visinfo = xmv->visinfo; XMesaImage *img; @@ -300,12 +253,12 @@ static int bits_per_pixel( XMesaVisual xmv ) /* grab the bits/pixel value */ bitsPerPixel = img->bits_per_pixel; /* free the XImage */ - FREE( img->data ); + _mesa_free( img->data ); img->data = NULL; XMesaDestroyImage( img ); return bitsPerPixel; -} #endif +} @@ -343,33 +296,166 @@ static GLboolean window_exists( XMesaDisplay *dpy, Window win ) #endif +static Status +get_drawable_size(Display *dpy, Drawable d, GLuint *width, GLuint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +/** + * Return the size of the window (or pixmap) that corresponds to the + * given XMesaBuffer. + * \param width returns width in pixels + * \param height returns height in pixels + */ +void +xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b, + GLuint *width, GLuint *height) +{ +#ifdef XFree86Server + *width = MIN2(b->frontxrb->drawable->width, MAX_WIDTH); + *height = MIN2(b->frontxrb->drawable->height, MAX_HEIGHT); +#else + Status stat; + + _glthread_LOCK_MUTEX(_xmesa_lock); + XSync(b->xm_visual->display, 0); /* added for Chromium */ + stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height); + _glthread_UNLOCK_MUTEX(_xmesa_lock); + + if (!stat) { + /* probably querying a window that's recently been destroyed */ + _mesa_warning(NULL, "XGetGeometry failed!\n"); + *width = *height = 1; + } +#endif +} + + /**********************************************************************/ /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -static XMesaBuffer XMesaBufferList = NULL; +XMesaBuffer XMesaBufferList = NULL; -/* Allocate a new XMesaBuffer, add to linked list */ -static XMesaBuffer alloc_xmesa_buffer(void) +/** + * Allocate a new XMesaBuffer object which corresponds to the given drawable. + * Note that XMesaBuffer is derived from GLframebuffer. + * The new XMesaBuffer will not have any size (Width=Height=0). + * + * \param d the corresponding X drawable (window or pixmap) + * \param type either WINDOW, PIXMAP or PBUFFER, describing d + * \param vis the buffer's visual + * \param cmap the window's colormap, if known. + * \return new XMesaBuffer or NULL if any problem + */ +static XMesaBuffer +create_xmesa_buffer(XMesaDrawable d, BufferType type, + XMesaVisual vis, XMesaColormap cmap) { - XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); - if (b) { - b->Next = XMesaBufferList; - XMesaBufferList = b; + XMesaBuffer b; + + ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); + if (!b) + return NULL; + + b->display = vis->display; + b->xm_visual = vis; + b->type = type; + b->cmap = cmap; + + _mesa_initialize_framebuffer(&b->mesa_buffer, &vis->mesa_visual); + b->mesa_buffer.Delete = xmesa_delete_framebuffer; + + /* + * Front renderbuffer + */ + b->frontxrb = xmesa_new_renderbuffer(NULL, 0, &vis->mesa_visual, GL_FALSE); + if (!b->frontxrb) { + _mesa_free(b); + return NULL; + } + b->frontxrb->Parent = b; + b->frontxrb->drawable = d; + b->frontxrb->pixmap = (XMesaPixmap) d; + _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT, + &b->frontxrb->Base); + + /* + * Back renderbuffer + */ + if (vis->mesa_visual.doubleBufferMode) { + b->backxrb = xmesa_new_renderbuffer(NULL, 0, &vis->mesa_visual, GL_TRUE); + if (!b->backxrb) { + /* XXX free front xrb too */ + _mesa_free(b); + return NULL; + } + b->backxrb->Parent = b; + /* determine back buffer implementation */ + b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP; + + _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT, + &b->backxrb->Base); } + + /* + * Software alpha planes + */ + if (vis->mesa_visual.alphaBits > 0 + && vis->undithered_pf != PF_8A8B8G8R + && vis->undithered_pf != PF_8A8R8G8B) { + /* Visual has alpha, but pixel format doesn't support it. + * We'll use an alpha renderbuffer wrapper. + */ + b->swAlpha = GL_TRUE; + } + else { + b->swAlpha = GL_FALSE; + } + + /* + * Other renderbuffer (depth, stencil, etc) + */ + _mesa_add_soft_renderbuffers(&b->mesa_buffer, + GL_FALSE, /* color */ + vis->mesa_visual.haveDepthBuffer, + vis->mesa_visual.haveStencilBuffer, + vis->mesa_visual.haveAccumBuffer, + b->swAlpha, + vis->mesa_visual.numAuxBuffers > 0 ); + + /* GLX_EXT_texture_from_pixmap */ + b->TextureTarget = 0; + b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; + b->TextureMipmap = 0; + + /* insert buffer into linked list */ + b->Next = XMesaBufferList; + XMesaBufferList = b; + return b; } -/* +/** * Find an XMesaBuffer by matching X display and colormap but NOT matching * the notThis buffer. */ -static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, - XMesaColormap cmap, - XMesaBuffer notThis) +XMesaBuffer +xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis) { XMesaBuffer b; for (b=XMesaBufferList; b; b=b->Next) { @@ -381,38 +467,34 @@ static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, } -/* - * Free an XMesaBuffer, remove from linked list, perhaps free X colormap - * entries. +/** + * Remove buffer from linked list, delete if no longer referenced. */ -static void free_xmesa_buffer(int client, XMesaBuffer buffer) +static void +xmesa_free_buffer(XMesaBuffer buffer) { XMesaBuffer prev = NULL, b; - (void) client; - for (b=XMesaBufferList; b; b=b->Next) { - if (b==buffer) { - /* unlink bufer from list */ + + for (b = XMesaBufferList; b; b = b->Next) { + if (b == buffer) { + struct gl_framebuffer *fb = &buffer->mesa_buffer; + + /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; - /* Check to free X colors */ - if (buffer->num_alloced>0) { - /* If no other buffer uses this X colormap then free the colors. */ - if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) { -#ifdef XFree86Server - (void)FreeColors(buffer->cmap, client, - buffer->num_alloced, buffer->alloced_colors, - 0); -#else - XFreeColors(buffer->display, buffer->cmap, - buffer->alloced_colors, buffer->num_alloced, 0); -#endif - } - } - _mesa_free_framebuffer_data(&buffer->mesa_buffer); - FREE(buffer); + /* mark as delete pending */ + fb->DeletePending = GL_TRUE; + + /* Since the X window for the XMesaBuffer is going away, we don't + * want to dereference this pointer in the future. + */ + b->frontxrb->drawable = 0; + + /* Unreference. If count = zero we'll really delete the buffer */ + _mesa_unreference_framebuffer(&fb); return; } @@ -420,12 +502,15 @@ static void free_xmesa_buffer(int client, XMesaBuffer buffer) prev = b; } /* buffer not found in XMesaBufferList */ - _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n"); + _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); } -/* Copy X color table stuff from one XMesaBuffer to another. */ -static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) +/** + * Copy X color table stuff from one XMesaBuffer to another. + */ +static void +copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) { MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); @@ -443,214 +528,7 @@ static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) /**********************************************************************/ -/* - * Return number of bits set in n. - */ -static int bitcount( unsigned long n ) -{ - int bits; - for (bits=0; n>0; n=n>>1) { - if (n&1) { - bits++; - } - } - return bits; -} - - - -/* - * Allocate a shared memory XImage back buffer for the given XMesaBuffer. - * Return: GL_TRUE if success, GL_FALSE if error - */ -#ifndef XFree86Server -static GLboolean alloc_shm_back_buffer( XMesaBuffer b ) -{ -#ifdef USE_XSHM - /* - * We have to do a _lot_ of error checking here to be sure we can - * really use the XSHM extension. It seems different servers trigger - * errors at different points if the extension won't work. Therefore - * we have to be very careful... - */ - GC gc; - int (*old_handler)( XMesaDisplay *, XErrorEvent * ); - - b->backimage = XShmCreateImage( b->xm_visual->display, - b->xm_visual->visinfo->visual, - b->xm_visual->visinfo->depth, - ZPixmap, NULL, &b->shminfo, - b->width, b->height ); - if (b->backimage == NULL) { - _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling."); - b->shm = 0; - return GL_FALSE; - } - - b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line - * b->backimage->height, IPC_CREAT|0777 ); - if (b->shminfo.shmid < 0) { - _mesa_warning(NULL, "shmget failed while allocating back buffer"); - XDestroyImage( b->backimage ); - b->backimage = NULL; - _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling."); - b->shm = 0; - return GL_FALSE; - } - - b->shminfo.shmaddr = b->backimage->data - = (char*)shmat( b->shminfo.shmid, 0, 0 ); - if (b->shminfo.shmaddr == (char *) -1) { - _mesa_warning(NULL, "shmat() failed while allocating back buffer"); - XDestroyImage( b->backimage ); - shmctl( b->shminfo.shmid, IPC_RMID, 0 ); - b->backimage = NULL; - _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling."); - b->shm = 0; - return GL_FALSE; - } - - b->shminfo.readOnly = False; - mesaXErrorFlag = 0; - old_handler = XSetErrorHandler( mesaHandleXError ); - /* This may trigger the X protocol error we're ready to catch: */ - XShmAttach( b->xm_visual->display, &b->shminfo ); - XSync( b->xm_visual->display, False ); - - if (mesaXErrorFlag) { - /* we are on a remote display, this error is normal, don't print it */ - XFlush( b->xm_visual->display ); - mesaXErrorFlag = 0; - XDestroyImage( b->backimage ); - shmdt( b->shminfo.shmaddr ); - shmctl( b->shminfo.shmid, IPC_RMID, 0 ); - b->backimage = NULL; - b->shm = 0; - (void) XSetErrorHandler( old_handler ); - return GL_FALSE; - } - - shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ - - /* Finally, try an XShmPutImage to be really sure the extension works */ - gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL ); - XShmPutImage( b->xm_visual->display, b->frontbuffer, gc, - b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); - XSync( b->xm_visual->display, False ); - XFreeGC( b->xm_visual->display, gc ); - (void) XSetErrorHandler( old_handler ); - if (mesaXErrorFlag) { - XFlush( b->xm_visual->display ); - mesaXErrorFlag = 0; - XDestroyImage( b->backimage ); - shmdt( b->shminfo.shmaddr ); - shmctl( b->shminfo.shmid, IPC_RMID, 0 ); - b->backimage = NULL; - b->shm = 0; - return GL_FALSE; - } - - if (b->backimage) { - int height = b->backimage->height; - /* Needed by PIXELADDR1 macro */ - b->ximage_width1 = b->backimage->bytes_per_line; - b->ximage_origin1 = (GLubyte *) b->backimage->data - + b->ximage_width1 * (height-1); - /* Needed by PIXELADDR2 macro */ - b->ximage_width2 = b->backimage->bytes_per_line / 2; - b->ximage_origin2 = (GLushort *) b->backimage->data - + b->ximage_width2 * (height-1); - /* Needed by PIXELADDR3 macro */ - b->ximage_width3 = b->backimage->bytes_per_line; - b->ximage_origin3 = (GLubyte *) b->backimage->data - + b->ximage_width3 * (height-1); - /* Needed by PIXELADDR4 macro */ - b->ximage_width4 = b->backimage->width; - b->ximage_origin4 = (GLuint *) b->backimage->data - + b->ximage_width4 * (height-1); - } - - return GL_TRUE; -#else - /* Can't compile XSHM support */ - return GL_FALSE; -#endif -} -#endif - - - -/* - * Setup an off-screen pixmap or Ximage to use as the back buffer. - * Input: b - the X/Mesa buffer - */ -void xmesa_alloc_back_buffer( XMesaBuffer b ) -{ - if (b->db_state==BACK_XIMAGE) { - /* Deallocate the old backimage, if any */ - if (b->backimage) { -#if defined(USE_XSHM) && !defined(XFree86Server) - if (b->shm) { - XShmDetach( b->xm_visual->display, &b->shminfo ); - XDestroyImage( b->backimage ); - shmdt( b->shminfo.shmaddr ); - } - else -#endif - XMesaDestroyImage( b->backimage ); - b->backimage = NULL; - } - - /* Allocate new back buffer */ -#ifdef XFree86Server - { - /* Allocate a regular XImage for the back buffer. */ - b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel, - b->width, b->height, NULL); -#else - if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) { - /* Allocate a regular XImage for the back buffer. */ - b->backimage = XCreateImage( b->xm_visual->display, - b->xm_visual->visinfo->visual, - GET_VISUAL_DEPTH(b->xm_visual), - ZPixmap, 0, /* format, offset */ - NULL, b->width, b->height, - 8, 0 ); /* pad, bytes_per_line */ -#endif - if (!b->backimage) { - _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed."); - } - b->backimage->data = (char *) MALLOC( b->backimage->height - * b->backimage->bytes_per_line ); - if (!b->backimage->data) { - _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed."); - XMesaDestroyImage( b->backimage ); - b->backimage = NULL; - } - } - b->backpixmap = None; - } - else if (b->db_state==BACK_PIXMAP) { - XMesaPixmap old_pixmap = b->backpixmap; - /* Free the old back pixmap */ - if (b->backpixmap) { - XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); - } - /* Allocate new back pixmap */ - b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer, - b->width, b->height, - GET_VISUAL_DEPTH(b->xm_visual) ); - b->backimage = NULL; - /* update other references to backpixmap */ - if (b->buffer==(XMesaDrawable)old_pixmap) { - b->buffer = (XMesaDrawable)b->backpixmap; - } - } -} - - - -/* +/** * A replacement for XAllocColor. This function should never * fail to allocate a color. When XAllocColor fails, we return * the nearest matching color. If we have to allocate many colors @@ -693,10 +571,11 @@ noFaultXAllocColor( int client, if (AllocColor(cmap, &color->red, &color->green, &color->blue, &color->pixel, - client) == Success) { + client) == Success) #else - if (XAllocColor(dpy, cmap, color)) { + if (XAllocColor(dpy, cmap, color)) #endif + { *exact = 1; *alloced = 1; return; @@ -718,7 +597,7 @@ noFaultXAllocColor( int client, || prevCmapSize != cmapSize || !ctable) { /* free previously cached color table */ if (ctable) - FREE(ctable); + _mesa_free(ctable); /* Get the color table from X */ ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); assert(ctable); @@ -774,8 +653,8 @@ noFaultXAllocColor( int client, *alloced = 0; } #ifdef XFree86Server - FREE(ppixIn); - FREE(ctable); + _mesa_free(ppixIn); + _mesa_free(ctable); #else /* don't free table, save it for next time */ #endif @@ -786,13 +665,13 @@ noFaultXAllocColor( int client, - -/* +/** * Do setup for PF_GRAYSCALE pixel format. * Note that buffer may be NULL. */ -static GLboolean setup_grayscale( int client, XMesaVisual v, - XMesaBuffer buffer, XMesaColormap cmap ) +static GLboolean +setup_grayscale(int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap) { if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { return GL_FALSE; @@ -805,7 +684,7 @@ static GLboolean setup_grayscale( int client, XMesaVisual v, return GL_FALSE; } - prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + prevBuffer = xmesa_find_buffer(v->display, cmap, buffer); if (prevBuffer && (buffer->xm_visual->mesa_visual.rgbMode == prevBuffer->xm_visual->mesa_visual.rgbMode)) { @@ -871,7 +750,7 @@ static GLboolean setup_grayscale( int client, XMesaVisual v, -/* +/** * Setup RGB rendering for a window with a PseudoColor, StaticColor, * or 8-bit TrueColor visual visual. We try to allocate a palette of 225 * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB @@ -879,8 +758,9 @@ static GLboolean setup_grayscale( int client, XMesaVisual v, * visuals, it has also proven to work from 4-bit up to 16-bit visuals. * Dithering code contributed by Bob Mercier. */ -static GLboolean setup_dithered_color( int client, XMesaVisual v, - XMesaBuffer buffer, XMesaColormap cmap ) +static GLboolean +setup_dithered_color(int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap) { if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { return GL_FALSE; @@ -893,7 +773,7 @@ static GLboolean setup_dithered_color( int client, XMesaVisual v, return GL_FALSE; } - prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + prevBuffer = xmesa_find_buffer(v->display, cmap, buffer); if (prevBuffer && (buffer->xm_visual->mesa_visual.rgbMode == prevBuffer->xm_visual->mesa_visual.rgbMode)) { @@ -950,12 +830,13 @@ static GLboolean setup_dithered_color( int client, XMesaVisual v, } -/* +/** * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode. * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer. * Special dithering tables have to be initialized. */ -static void setup_8bit_hpcr( XMesaVisual v ) +static void +setup_8bit_hpcr(XMesaVisual v) { /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be) * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined @@ -1005,11 +886,11 @@ static void setup_8bit_hpcr( XMesaVisual v ) } -/* +/** * Setup RGB rendering for a window with a True/DirectColor visual. */ -static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, - XMesaColormap cmap ) +static void +setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap) { unsigned long rmask, gmask, bmask; (void) buffer; @@ -1049,9 +930,9 @@ static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, 3*16, 11*16, 1*16, 9*16, 15*16, 7*16, 13*16, 5*16, }; - GLint rBits = bitcount(rmask); - GLint gBits = bitcount(gmask); - GLint bBits = bitcount(bmask); + GLint rBits = _mesa_bitcount(rmask); + GLint gBits = _mesa_bitcount(gmask); + GLint bBits = _mesa_bitcount(bmask); GLint maxBits; GLuint i; @@ -1100,39 +981,33 @@ static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, && GET_BLUEMASK(v) ==0xff0000 && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==32 - && sizeof(GLuint)==4 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { /* common 32 bpp config used on SGI, Sun */ - v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; - } - else if (GET_REDMASK(v) ==0xff0000 - && GET_GREENMASK(v)==0x00ff00 - && GET_BLUEMASK(v) ==0x0000ff - && CHECK_BYTE_ORDER(v) - && v->BitsPerPixel==32 - && sizeof(GLuint)==4 - && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { - /* common 32 bpp config used on Linux, HP, IBM */ - v->undithered_pf = v->dithered_pf = PF_8R8G8B; - } - else if (GET_REDMASK(v) ==0xff0000 - && GET_GREENMASK(v)==0x00ff00 - && GET_BLUEMASK(v) ==0x0000ff - && CHECK_BYTE_ORDER(v) - && v->BitsPerPixel==24 - && sizeof(GLuint)==4 - && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { - /* common packed 24 bpp config used on Linux */ - v->undithered_pf = v->dithered_pf = PF_8R8G8B24; + v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */ + } + else if (GET_REDMASK(v) == 0xff0000 + && GET_GREENMASK(v)== 0x00ff00 + && GET_BLUEMASK(v) == 0x0000ff + && CHECK_BYTE_ORDER(v) + && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){ + if (v->BitsPerPixel==32) { + /* if 32 bpp, and visual indicates 8 bpp alpha channel */ + if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8) + v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */ + else + v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */ + } + else if (v->BitsPerPixel == 24) { + v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */ + } } else if (GET_REDMASK(v) ==0xf800 && GET_GREENMASK(v)==0x07e0 && GET_BLUEMASK(v) ==0x001f && CHECK_BYTE_ORDER(v) && v->BitsPerPixel==16 - && sizeof(GLushort)==2 && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { - /* 5-6-5 color weight on common PC VGA boards */ + /* 5-6-5 RGB */ v->undithered_pf = PF_5R6G5B; v->dithered_pf = PF_Dither_5R6G5B; } @@ -1140,16 +1015,18 @@ static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, && GET_GREENMASK(v)==0x1c && GET_BLUEMASK(v) ==0x03 && CHECK_FOR_HPCR(v)) { + /* 8-bit HP color recovery */ setup_8bit_hpcr( v ); } } -/* +/** * Setup RGB rendering for a window with a monochrome visual. */ -static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) +static void +setup_monochrome( XMesaVisual v, XMesaBuffer b ) { (void) b; v->dithered_pf = v->undithered_pf = PF_1Bit; @@ -1159,37 +1036,34 @@ static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) -/* - * When a context is "made current" for the first time, we can finally - * finish initializing the context's visual and buffer information. - * Input: v - the XMesaVisual to initialize - * b - the XMesaBuffer to initialize (may be NULL) - * rgb_flag - TRUE = RGBA mode, FALSE = color index mode - * window - the window/pixmap we're rendering into - * cmap - the colormap associated with the window/pixmap - * Return: GL_TRUE=success, GL_FALSE=failure +/** + * When a context is bound for the first time, we can finally finish + * initializing the context's visual and buffer information. + * \param v the XMesaVisual to initialize + * \param b the XMesaBuffer to initialize (may be NULL) + * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode + * \param window the window/pixmap we're rendering into + * \param cmap the colormap associated with the window/pixmap + * \return GL_TRUE=success, GL_FALSE=failure */ -static GLboolean initialize_visual_and_buffer( int client, - XMesaVisual v, - XMesaBuffer b, - GLboolean rgb_flag, - XMesaDrawable window, - XMesaColormap cmap ) +static GLboolean +initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, + GLboolean rgb_flag, XMesaDrawable window, + XMesaColormap cmap) { -#ifndef XFree86Server - XGCValues gcvalues; + int client = 0; + +#ifdef XFree86Server + client = (window) ? CLIENT_ID(window->id) : 0; #endif - if (b) { - assert(b->xm_visual == v); - } + ASSERT(!b || b->xm_visual == v); /* Save true bits/pixel */ v->BitsPerPixel = bits_per_pixel(v); assert(v->BitsPerPixel > 0); - - if (rgb_flag==GL_FALSE) { + if (rgb_flag == GL_FALSE) { /* COLOR-INDEXED WINDOW: * Even if the visual is TrueColor or DirectColor we treat it as * being color indexed. This is weird but might be useful to someone. @@ -1202,25 +1076,25 @@ static GLboolean initialize_visual_and_buffer( int client, * We support RGB rendering into almost any kind of visual. */ const int xclass = v->mesa_visual.visualType; - if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) { + if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { setup_truecolor( v, b, cmap ); } - else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) { + else if (xclass == GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v) == 1) { setup_monochrome( v, b ); } - else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) { + else if (xclass == GLX_GRAY_SCALE || xclass == GLX_STATIC_GRAY) { if (!setup_grayscale( client, v, b, cmap )) { return GL_FALSE; } } - else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR) + else if ((xclass == GLX_PSEUDO_COLOR || xclass == GLX_STATIC_COLOR) && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { if (!setup_dithered_color( client, v, b, cmap )) { return GL_FALSE; } } else { - _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual."); + _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n"); return GL_FALSE; } v->mesa_visual.indexBits = 0; @@ -1246,33 +1120,18 @@ static GLboolean initialize_visual_and_buffer( int client, } if (b && window) { - /* Do window-specific initializations */ + char *data; - /* Window dimensions */ - unsigned int w, h; - get_drawable_size( v->display, window, &w, &h ); - b->width = w; - b->height = h; + /* Do window-specific initializations */ - b->frontbuffer = window; + /* these should have been set in create_xmesa_buffer */ + ASSERT(b->frontxrb->drawable == window); + ASSERT(b->frontxrb->pixmap == (XMesaPixmap) window); /* Setup for single/double buffering */ if (v->mesa_visual.doubleBufferMode) { /* Double buffered */ -#ifndef XFree86Server b->shm = check_for_xshm( v->display ); -#endif - xmesa_alloc_back_buffer( b ); - if (b->db_state==BACK_PIXMAP) { - b->buffer = (XMesaDrawable)b->backpixmap; - } - else { - b->buffer = XIMAGE; - } - } - else { - /* Single Buffered */ - b->buffer = b->frontbuffer; } /* X11 graphics contexts */ @@ -1298,14 +1157,17 @@ static GLboolean initialize_visual_and_buffer( int client, #ifdef XFree86Server b->swapgc = CreateScratchGC(v->display, window->depth); { - CARD32 v[1]; - v[0] = FALSE; - dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); + CARD32 v[1]; + v[0] = FALSE; + dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); } #else - gcvalues.graphics_exposures = False; - b->swapgc = XCreateGC( v->display, window, - GCGraphicsExposures, &gcvalues); + { + XGCValues gcvalues; + gcvalues.graphics_exposures = False; + b->swapgc = XCreateGC(v->display, window, + GCGraphicsExposures, &gcvalues); + } #endif XMesaSetFunction( v->display, b->swapgc, GXcopy ); /* @@ -1314,33 +1176,34 @@ static GLboolean initialize_visual_and_buffer( int client, * Initialize whole stuff * Patch contributed by Jacques Leroy March 8, 1998. */ - if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { - int i; - for (i=0; i<16; i++) - { - XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); - XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); - } - XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, - b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); - XMesaSetFillStyle( v->display, b->cleargc, FillTiled); - XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); + if (v->hpcr_clear_flag && b->backxrb && b->backxrb->pixmap) { + int i; + for (i = 0; i < 16; i++) { + XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); + XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); + } + XMesaPutImage(b->display, (XMesaDrawable) v->hpcr_clear_pixmap, + b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); + XMesaSetFillStyle( v->display, b->cleargc, FillTiled); + XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); } /* Initialize the row buffer XImage for use in write_color_span() */ + data = (char*) MALLOC(MAX_WIDTH*4); #ifdef XFree86Server - b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, - (char *)MALLOC(MAX_WIDTH*4)); + b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, data); #else b->rowimage = XCreateImage( v->display, v->visinfo->visual, v->visinfo->depth, ZPixmap, 0, /*format, offset*/ - (char*) MALLOC(MAX_WIDTH*4), /*data*/ + data, /*data*/ MAX_WIDTH, 1, /*width, height*/ 32, /*bitmap_pad*/ 0 /*bytes_per_line*/ ); #endif + if (!b->rowimage) + return GL_FALSE; } return GL_TRUE; @@ -1352,9 +1215,11 @@ static GLboolean initialize_visual_and_buffer( int client, * Convert an RGBA color to a pixel value. */ unsigned long -xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, - GLuint pixelFormat) +xmesa_color_to_pixel(GLcontext *ctx, + GLubyte r, GLubyte g, GLubyte b, GLubyte a, + GLuint pixelFormat) { + XMesaContext xmesa = XMESA_CONTEXT(ctx); switch (pixelFormat) { case PF_Index: return 0; @@ -1366,6 +1231,8 @@ xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLuby } case PF_8A8B8G8R: return PACK_8A8B8G8R( r, g, b, a ); + case PF_8A8R8G8B: + return PACK_8A8R8G8B( r, g, b, a ); case PF_8R8G8B: /* fall through */ case PF_8R8G8B24: @@ -1398,7 +1265,7 @@ xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLuby return p; } default: - _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); + _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel"); } return 0; } @@ -1460,6 +1327,7 @@ xmesa_convert_from_x_visual_type( int visualType ) * visualCaveat - ala the GLX extension, usually GLX_NONE * Return; a new XMesaVisual or 0 if error. */ +PUBLIC XMesaVisual XMesaCreateVisual( XMesaDisplay *display, XMesaVisualInfo visinfo, GLboolean rgb_flag, @@ -1481,39 +1349,32 @@ XMesaVisual XMesaCreateVisual( XMesaDisplay *display, XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; +#ifndef XFree86Server /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. * In your debugger, set a breakpoint on _XError to stop when an * X protocol error is generated. */ -#ifdef XFree86Server - /* NOT_NEEDED */ -#else XSynchronize( display, 1 ); -#endif } +#endif v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); if (!v) { return NULL; } - /* - * In the X server, NULL is passed in for the display. It will have - * to be set before using this visual. See XMesaSetVisualDisplay() - * below. - */ v->display = display; - /* Save a copy of the XVisualInfo struct because the user may XFREE() + /* Save a copy of the XVisualInfo struct because the user may X_mesa_free() * the struct but we may need some of the information contained in it * at a later time. */ #ifndef XFree86Server v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); if(!v->visinfo) { - FREE(v); + _mesa_free(v); return NULL; } MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); @@ -1540,6 +1401,7 @@ XMesaVisual XMesaCreateVisual( XMesaDisplay *display, * ColormapEntries is either (1U << index_bits) or * (1U << max(redBits, greenBits, blueBits)). */ + assert(visinfo->nplanes > 0); v->nplanes = visinfo->nplanes; v->ColormapEntries = visinfo->ColormapEntries; @@ -1564,15 +1426,17 @@ XMesaVisual XMesaCreateVisual( XMesaDisplay *display, v->mesa_visual.visualRating = visualCaveat; - (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); + if (alpha_flag) + v->mesa_visual.alphaBits = 8; + + (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 ); { const int xclass = v->mesa_visual.visualType; - if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) { - red_bits = bitcount(GET_REDMASK(v)); - green_bits = bitcount(GET_GREENMASK(v)); - blue_bits = bitcount(GET_BLUEMASK(v)); - alpha_bits = 0; + if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { + red_bits = _mesa_bitcount(GET_REDMASK(v)); + green_bits = _mesa_bitcount(GET_GREENMASK(v)); + blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); } else { /* this is an approximation */ @@ -1586,11 +1450,9 @@ XMesaVisual XMesaCreateVisual( XMesaDisplay *display, alpha_bits = 0; assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); } + alpha_bits = v->mesa_visual.alphaBits; } - if (alpha_flag && alpha_bits == 0) - alpha_bits = 8; - _mesa_initialize_visual( &v->mesa_visual, rgb_flag, db_flag, stereo_flag, red_bits, green_bits, @@ -1608,18 +1470,13 @@ XMesaVisual XMesaCreateVisual( XMesaDisplay *display, } -void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) -{ - v->display = dpy; -} - - +PUBLIC void XMesaDestroyVisual( XMesaVisual v ) { #ifndef XFree86Server - FREE(v->visinfo); + _mesa_free(v->visinfo); #endif - FREE(v); + _mesa_free(v); } @@ -1631,6 +1488,7 @@ void XMesaDestroyVisual( XMesaVisual v ) * lists or NULL if no sharing is wanted. * \return an XMesaContext or NULL if error. */ +PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { static GLboolean firstTime = GL_TRUE; @@ -1657,7 +1515,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, share_list ? &(share_list->mesa) : (GLcontext *) NULL, &functions, (void *) c)) { - FREE(c); + _mesa_free(c); return NULL; } @@ -1665,12 +1523,28 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) _mesa_enable_1_3_extensions(mesaCtx); _mesa_enable_1_4_extensions(mesaCtx); _mesa_enable_1_5_extensions(mesaCtx); + _mesa_enable_2_0_extensions(mesaCtx); +#if ENABLE_EXT_texure_compression_s3tc + if (c->Mesa_DXTn) { + _mesa_enable_extension(mesaCtx, "GL_EXT_texture_compression_s3tc"); + _mesa_enable_extension(mesaCtx, "GL_S3_s3tc"); + } + _mesa_enable_extension(mesaCtx, "GL_3DFX_texture_compression_FXT1"); +#endif +#if ENABLE_EXT_timer_query + _mesa_enable_extension(mesaCtx, "GL_EXT_timer_query"); +#endif + +#ifdef XFree86Server + /* If we're running in the X server, do bounds checking to prevent + * segfaults and server crashes! + */ + mesaCtx->Const.CheckArrayBounds = GL_TRUE; +#endif /* finish up xmesa context initializations */ c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; c->xm_visual = v; - c->xm_draw_buffer = NULL; /* set later by XMesaMakeCurrent */ - c->xm_read_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->display = v->display; c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ @@ -1678,7 +1552,7 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) /* Initialize the software rasterizer and helper modules. */ if (!_swrast_CreateContext( mesaCtx ) || - !_ac_CreateContext( mesaCtx ) || + !_vbo_CreateContext( mesaCtx ) || !_tnl_CreateContext( mesaCtx ) || !_swsetup_CreateContext( mesaCtx )) { _mesa_free_context_data(&c->mesa); @@ -1698,191 +1572,87 @@ XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) +PUBLIC void XMesaDestroyContext( XMesaContext c ) { GLcontext *mesaCtx = &c->mesa; + #ifdef FX - if (c->xm_draw_buffer && c->xm_buffer->FXctx) - fxMesaDestroyContext(c->xm_draw_buffer->FXctx); + FXdestroyContext( XMESA_BUFFER(mesaCtx->DrawBuffer) ); #endif + _swsetup_DestroyContext( mesaCtx ); _swrast_DestroyContext( mesaCtx ); _tnl_DestroyContext( mesaCtx ); - _ac_DestroyContext( mesaCtx ); + _vbo_DestroyContext( mesaCtx ); _mesa_free_context_data( mesaCtx ); _mesa_free( c ); } -/* - * XXX this isn't a public function! It's a hack for the 3Dfx driver. - * Create a new XMesaBuffer from an X window. - * Input: v - the XMesaVisual - * w - the window - * c - the context - * Return: new XMesaBuffer or NULL if error +/** + * Private function for creating an XMesaBuffer which corresponds to an + * X window or pixmap. + * \param v the window's XMesaVisual + * \param w the window we're wrapping + * \return new XMesaBuffer or NULL if error */ -XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, - XMesaContext c ) +PUBLIC XMesaBuffer +XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w) { #ifndef XFree86Server XWindowAttributes attr; #endif -#ifdef FX - char *fxEnvVar; -#endif - int client = 0; - - XMesaBuffer b = alloc_xmesa_buffer(); - if (!b) { - return NULL; - } - - (void) c; - -#ifdef XFree86Server - client = CLIENT_ID(((XMesaDrawable)w)->id); -#endif + XMesaBuffer b; + XMesaColormap cmap; + int depth; assert(v); + assert(w); + /* Check that window depth matches visual depth */ #ifdef XFree86Server - if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { + depth = ((XMesaDrawable)w)->depth; #else XGetWindowAttributes( v->display, w, &attr ); - - if (GET_VISUAL_DEPTH(v) != attr.depth) { + depth = attr.depth; #endif - _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); + if (GET_VISUAL_DEPTH(v) != depth) { + _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", + GET_VISUAL_DEPTH(v), depth); return NULL; } - b->xm_visual = v; - b->type = WINDOW; - b->display = v->display; + /* Find colormap */ #ifdef XFree86Server - b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); + cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); #else if (attr.colormap) { - b->cmap = attr.colormap; + cmap = attr.colormap; } else { _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); /* this is weird, a window w/out a colormap!? */ /* OK, let's just allocate a new one and hope for the best */ - b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); + cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); } #endif - /* determine back buffer implementation */ - if (v->mesa_visual.doubleBufferMode) { - if (v->ximage_flag) { - b->db_state = BACK_XIMAGE; - } - else { - b->db_state = BACK_PIXMAP; - } - } - else { - b->db_state = 0; - } - - _mesa_initialize_framebuffer(&b->mesa_buffer, - &v->mesa_visual, - v->mesa_visual.depthBits > 0, - v->mesa_visual.stencilBits > 0, - v->mesa_visual.accumRedBits > 0, - v->mesa_visual.alphaBits > 0 ); - /* XXX hack */ - b->mesa_buffer.UseSoftwareAuxBuffers = GL_TRUE; + b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap); + if (!b) + return NULL; - if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, - (XMesaDrawable)w, b->cmap )) { - free_xmesa_buffer(client, b); + if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode, + (XMesaDrawable) w, cmap )) { + xmesa_free_buffer(b); return NULL; } -#ifdef FX - fxEnvVar = _mesa_getenv("MESA_GLX_FX"); - if (fxEnvVar) { - if (fxEnvVar[0]!='d') { - int attribs[100]; - int numAttribs = 0; - int hw; - if (v->mesa_visual.depthBits > 0) { - attribs[numAttribs++] = FXMESA_DEPTH_SIZE; - attribs[numAttribs++] = v->mesa_visual.depthBits; - } - if (v->mesa_visual.doubleBufferMode) { - attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; - } - if (v->mesa_visual.accumRedBits > 0) { - attribs[numAttribs++] = FXMESA_ACCUM_SIZE; - attribs[numAttribs++] = v->mesa_visual.accumRedBits; - } - if (v->mesa_visual.stencilBits > 0) { - attribs[numAttribs++] = FXMESA_STENCIL_SIZE; - attribs[numAttribs++] = v->mesa_visual.stencilBits; - } - if (v->mesa_visual.alphaBits > 0) { - attribs[numAttribs++] = FXMESA_ALPHA_SIZE; - attribs[numAttribs++] = v->mesa_visual.alphaBits; - } - if (1) { - attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; - attribs[numAttribs++] = (int) &(c->mesa); - } - attribs[numAttribs++] = FXMESA_NONE; - - /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ - hw = fxMesaSelectCurrentBoard(0); - if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { - b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); - if ((v->undithered_pf!=PF_Index) && (b->backimage)) { - b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; - if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { - b->FXwindowHack = GL_TRUE; - FX_grSstControl(GR_CONTROL_DEACTIVATE); - } - else { - b->FXwindowHack = GL_FALSE; - } - } - } - else { - if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') - b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, - GR_REFRESH_75Hz, attribs); - else - b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); - b->FXisHackUsable = GL_FALSE; - b->FXwindowHack = GL_FALSE; - } - /* - fprintf(stderr, - "voodoo %d, wid %d height %d hack: usable %d active %d\n", - hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); - */ - } - } - else { - _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); - _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); - _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); - _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); - } -#endif - return b; } -XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) -{ - return XMesaCreateWindowBuffer2( v, w, NULL ); -} - /** * Create a new XMesaBuffer from an X pixmap. @@ -1893,52 +1663,81 @@ XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) * \c GLX_DIRECT_COLOR visual for the pixmap * \returns new XMesaBuffer or NULL if error */ -XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, - XMesaPixmap p, XMesaColormap cmap ) +PUBLIC XMesaBuffer +XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap) { - int client = 0; - XMesaBuffer b = alloc_xmesa_buffer(); - if (!b) { + XMesaBuffer b; + + assert(v); + + b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + (XMesaDrawable) p, cmap)) { + xmesa_free_buffer(b); return NULL; } + return b; +} -#ifdef XFree86Server - client = CLIENT_ID(((XMesaDrawable)p)->id); -#endif + +/** + * For GLX_EXT_texture_from_pixmap + */ +XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p, + XMesaColormap cmap, + int format, int target, int mipmap) +{ + GET_CURRENT_CONTEXT(ctx); + XMesaBuffer b; + GLuint width, height; assert(v); - b->xm_visual = v; - b->type = PIXMAP; - b->display = v->display; - b->cmap = cmap; + b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; - /* determine back buffer implementation */ - if (v->mesa_visual.doubleBufferMode) { - if (v->ximage_flag) { - b->db_state = BACK_XIMAGE; + /* get pixmap size, update framebuffer/renderbuffer dims */ + get_drawable_size(v->display, p, &width, &height); + _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height); + + if (target == 0) { + /* examine dims */ + if (ctx->Extensions.ARB_texture_non_power_of_two) { + target = GLX_TEXTURE_2D_EXT; + } + else if ( _mesa_bitcount(width) == 1 + && _mesa_bitcount(height) == 1) { + /* power of two size */ + if (height == 1) { + target = GLX_TEXTURE_1D_EXT; + } + else { + target = GLX_TEXTURE_2D_EXT; + } + } + else if (ctx->Extensions.NV_texture_rectangle) { + target = GLX_TEXTURE_RECTANGLE_EXT; } else { - b->db_state = BACK_PIXMAP; + /* non power of two textures not supported */ + XMesaDestroyBuffer(b); + return 0; } } - else { - b->db_state = 0; - } - _mesa_initialize_framebuffer(&b->mesa_buffer, - &v->mesa_visual, - v->mesa_visual.depthBits > 0, - v->mesa_visual.stencilBits > 0, - v->mesa_visual.accumRedBits + - v->mesa_visual.accumGreenBits + - v->mesa_visual.accumBlueBits > 0, - v->mesa_visual.alphaBits > 0 ); + b->TextureTarget = target; + b->TextureFormat = format; + b->TextureMipmap = mipmap; - if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, - (XMesaDrawable)p, cmap)) { - free_xmesa_buffer(client, b); + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + (XMesaDrawable) p, cmap)) { + xmesa_free_buffer(b); return NULL; } @@ -1947,58 +1746,35 @@ XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, -XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, - unsigned int width, unsigned int height ) +XMesaBuffer +XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap, + unsigned int width, unsigned int height) { -#ifdef XFree86Server - return 0; -#else - int client = 0; +#ifndef XFree86Server XMesaWindow root; XMesaDrawable drawable; /* X Pixmap Drawable */ - XMesaBuffer b = alloc_xmesa_buffer(); - if (!b) { - return NULL; - } - - b->xm_visual = v; - b->type = PBUFFER; - b->display = v->display; - b->cmap = cmap; + XMesaBuffer b; /* allocate pixmap for front buffer */ root = RootWindow( v->display, v->visinfo->screen ); - drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth ); - - /* determine back buffer implementation */ - if (v->mesa_visual.doubleBufferMode) { - if (v->ximage_flag) { - b->db_state = BACK_XIMAGE; - } - else { - b->db_state = BACK_PIXMAP; - } - } - else { - b->db_state = 0; - } + drawable = XCreatePixmap(v->display, root, width, height, + v->visinfo->depth); + if (!drawable) + return NULL; - _mesa_initialize_framebuffer(&b->mesa_buffer, - &v->mesa_visual, - v->mesa_visual.depthBits > 0, - v->mesa_visual.stencilBits > 0, - v->mesa_visual.accumRedBits + - v->mesa_visual.accumGreenBits + - v->mesa_visual.accumBlueBits > 0, - v->mesa_visual.alphaBits > 0 ); + b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); + if (!b) + return NULL; - if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, drawable, cmap)) { - free_xmesa_buffer(client, b); + xmesa_free_buffer(b); return NULL; } return b; +#else + return 0; #endif } @@ -2007,49 +1783,37 @@ XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, /* * Deallocate an XMesaBuffer structure and all related info. */ -void XMesaDestroyBuffer( XMesaBuffer b ) +PUBLIC void +XMesaDestroyBuffer(XMesaBuffer b) { - int client = 0; - -#ifdef XFree86Server - if (b->frontbuffer) - client = CLIENT_ID(b->frontbuffer->id); -#endif + xmesa_free_buffer(b); +} - if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); - if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); - if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); - if (b->backimage) { -#if defined(USE_XSHM) && !defined(XFree86Server) - if (b->shm) { - XShmDetach( b->xm_visual->display, &b->shminfo ); - XDestroyImage( b->backimage ); - shmdt( b->shminfo.shmaddr ); - } - else -#endif - XMesaDestroyImage( b->backimage ); - } - if (b->backpixmap) { - XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); - if (b->xm_visual->hpcr_clear_flag) { - XMesaFreePixmap( b->xm_visual->display, - b->xm_visual->hpcr_clear_pixmap ); - XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); - } - } - if (b->rowimage) { - FREE( b->rowimage->data ); - b->rowimage->data = NULL; - XMesaDestroyImage( b->rowimage ); - } - - free_xmesa_buffer(client, b); +/** + * Query the current window size and update the corresponding GLframebuffer + * and all attached renderbuffers. + * Called when: + * 1. the first time a buffer is bound to a context. + * 2. from glViewport to poll for window size changes + * 3. from the XMesaResizeBuffers() API function. + * Note: it's possible (and legal) for xmctx to be NULL. That can happen + * when resizing a buffer when no rendering context is bound. + */ +void +xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +{ + GLuint width, height; + xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height); + if (drawBuffer->mesa_buffer.Width != width || + drawBuffer->mesa_buffer.Height != height) { + GLcontext *ctx = xmctx ? &xmctx->mesa : NULL; + _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height); + } + drawBuffer->mesa_buffer.Initialized = GL_TRUE; /* XXX TEMPORARY? */ } - /* * Bind buffer b to context c and make c the current rendering context. */ @@ -2062,6 +1826,7 @@ GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) /* * Bind buffer b to context c and make c the current rendering context. */ +PUBLIC GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, XMesaBuffer readBuffer ) { @@ -2069,60 +1834,54 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, if (!drawBuffer || !readBuffer) return GL_FALSE; /* must specify buffers! */ -#ifdef FX - if (drawBuffer->FXctx) { - fxMesaMakeCurrent(drawBuffer->FXctx); - - c->xm_draw_buffer = drawBuffer; - c->xm_read_buffer = readBuffer; - c->xm_buffer = drawBuffer; - - return GL_TRUE; - } -#endif if (&(c->mesa) == _mesa_get_current_context() - && c->xm_draw_buffer == drawBuffer - && c->xm_read_buffer == readBuffer - && c->xm_draw_buffer->wasCurrent) { + && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer + && c->mesa.ReadBuffer == &readBuffer->mesa_buffer + && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) { /* same context and buffer, do nothing */ return GL_TRUE; } - c->xm_draw_buffer = drawBuffer; - c->xm_read_buffer = readBuffer; c->xm_buffer = drawBuffer; - _mesa_make_current2(&(c->mesa), - &drawBuffer->mesa_buffer, - &readBuffer->mesa_buffer); +#ifdef FX + if (FXmakeCurrent( drawBuffer )) + return GL_TRUE; +#endif - if (c->mesa.Viewport.Width == 0) { - /* initialize viewport to window size */ - _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height ); - c->mesa.Scissor.Width = drawBuffer->width; - c->mesa.Scissor.Height = drawBuffer->height; - } + /* Call this periodically to detect when the user has begun using + * GL rendering from multiple threads. + */ + _glapi_check_multithread(); + + xmesa_check_and_update_buffer_size(c, drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_and_update_buffer_size(c, readBuffer); + + _mesa_make_current(&(c->mesa), + &drawBuffer->mesa_buffer, + &readBuffer->mesa_buffer); if (c->xm_visual->mesa_visual.rgbMode) { /* * Must recompute and set these pixel values because colormap * can be different for different windows. */ - c->clearpixel = xmesa_color_to_pixel( c, + c->clearpixel = xmesa_color_to_pixel( &c->mesa, c->clearcolor[0], c->clearcolor[1], c->clearcolor[2], c->clearcolor[3], c->xm_visual->undithered_pf); - XMesaSetForeground(c->display, c->xm_draw_buffer->cleargc, c->clearpixel); + XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel); } /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ - c->xm_draw_buffer->wasCurrent = GL_TRUE; + drawBuffer->wasCurrent = GL_TRUE; } else { /* Detach */ - _mesa_make_current2( NULL, NULL, NULL ); + _mesa_make_current( NULL, NULL, NULL ); } return GL_TRUE; } @@ -2155,8 +1914,8 @@ XMesaBuffer XMesaGetCurrentBuffer( void ) { GET_CURRENT_CONTEXT(ctx); if (ctx) { - XMesaContext xmesa = XMESA_CONTEXT(ctx); - return xmesa->xm_draw_buffer; + XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer); + return xmbuf; } else { return 0; @@ -2169,8 +1928,7 @@ XMesaBuffer XMesaGetCurrentReadBuffer( void ) { GET_CURRENT_CONTEXT(ctx); if (ctx) { - XMesaContext xmesa = XMESA_CONTEXT(ctx); - return xmesa->xm_read_buffer; + return XMESA_BUFFER(ctx->ReadBuffer); } else { return 0; @@ -2178,230 +1936,115 @@ XMesaBuffer XMesaGetCurrentReadBuffer( void ) } +#ifdef XFree86Server +PUBLIC GLboolean XMesaForceCurrent(XMesaContext c) { if (c) { + _glapi_set_dispatch(c->mesa.CurrentDispatch); + if (&(c->mesa) != _mesa_get_current_context()) { - _mesa_make_current(&(c->mesa), &c->xm_draw_buffer->mesa_buffer); + _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer); } } else { - _mesa_make_current(NULL, NULL); + _mesa_make_current(NULL, NULL, NULL); } return GL_TRUE; } +PUBLIC GLboolean XMesaLoseCurrent(XMesaContext c) { (void) c; - _mesa_make_current(NULL, NULL); + _mesa_make_current(NULL, NULL, NULL); return GL_TRUE; } -/* - * Switch 3Dfx support hack between window and full-screen mode. - */ -GLboolean XMesaSetFXmode( GLint mode ) +PUBLIC +GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask ) { -#ifdef FX - const char *fx = _mesa_getenv("MESA_GLX_FX"); - if (fx && fx[0] != 'd') { - GET_CURRENT_CONTEXT(ctx); - GrHwConfiguration hw; - if (!FX_grSstQueryHardware(&hw)) { - /*fprintf(stderr, "!grSstQueryHardware\n");*/ - return GL_FALSE; - } - if (hw.num_sst < 1) { - /*fprintf(stderr, "hw.num_sst < 1\n");*/ - return GL_FALSE; - } - if (ctx) { - /* [dBorca] Hack alert: - * oh, this is sooo wrong: ctx above is - * really an fxMesaContext, not an XMesaContext - */ - XMesaContext xmesa = XMESA_CONTEXT(ctx); - if (mode == XMESA_FX_WINDOW) { - if (xmesa->xm_draw_buffer->FXisHackUsable) { - FX_grSstControl(GR_CONTROL_DEACTIVATE); - xmesa->xm_draw_buffer->FXwindowHack = GL_TRUE; - return GL_TRUE; - } - } - else if (mode == XMESA_FX_FULLSCREEN) { - FX_grSstControl(GR_CONTROL_ACTIVATE); - xmesa->xm_draw_buffer->FXwindowHack = GL_FALSE; - return GL_TRUE; - } - else { - /* Error: Bad mode value */ - } - } - } - /*fprintf(stderr, "fallthrough\n");*/ -#else - (void) mode; -#endif - return GL_FALSE; + _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask); + return GL_TRUE; } +#endif /* XFree86Server */ - -#ifdef FX -/* - * Read image from VooDoo frame buffer into X/Mesa's back XImage. - */ -static void FXgetImage( XMesaBuffer b ) +#ifndef FX +GLboolean XMesaSetFXmode( GLint mode ) { - GET_CURRENT_CONTEXT(ctx); - static unsigned short pixbuf[MAX_WIDTH]; - GLuint x, y; - int xpos, ypos; - XMesaWindow root; - unsigned int bw, depth, width, height; - XMesaContext xmesa = XMESA_CONTEXT(ctx); - -#ifdef XFree86Server - x = b->frontbuffer->x; - y = b->frontbuffer->y; - width = b->frontbuffer->width; - height = b->frontbuffer->height; - depth = b->frontbuffer->depth; -#else - XGetGeometry( b->xm_visual->display, b->frontbuffer, - &root, &xpos, &ypos, &width, &height, &bw, &depth); -#endif - if (b->width != width || b->height != height) { - b->width = MIN2((int)width, b->FXctx->width); - b->height = MIN2((int)height, b->FXctx->height); - if (b->width & 1) - b->width--; /* prevent odd width */ - xmesa_alloc_back_buffer( b ); - } - - /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ - /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ - if (b->xm_visual->undithered_pf==PF_5R6G5B) { - /* Special case: 16bpp RGB */ - grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ - 0, b->FXctx->height - b->height, /*pos*/ - b->width, b->height, /* size */ - b->width * sizeof(GLushort), /* stride */ - b->backimage->data); /* dest buffer */ - } - else if (b->xm_visual->dithered_pf==PF_Dither - && GET_VISUAL_DEPTH(b->xm_visual)==8) { - /* Special case: 8bpp RGB */ - for (y=0;yheight;y++) { - GLubyte *ptr = (GLubyte*) b->backimage->data - + b->backimage->bytes_per_line * y; - XDITHER_SETUP(y); - - /* read row from 3Dfx frame buffer */ - grLfbReadRegion( GR_BUFFER_FRONTBUFFER, - 0, b->FXctx->height-(b->height-y), - b->width, 1, - 0, - pixbuf ); - - /* write to XImage back buffer */ - for (x=0;xwidth;x++) { - GLubyte r = (pixbuf[x] & 0xf800) >> 8; - GLubyte g = (pixbuf[x] & 0x07e0) >> 3; - GLubyte b = (pixbuf[x] & 0x001f) << 3; - *ptr++ = XDITHER( x, r, g, b); - } - } - } - else { - /* General case: slow! */ - for (y=0;yheight;y++) { - /* read row from 3Dfx frame buffer */ - grLfbReadRegion( GR_BUFFER_FRONTBUFFER, - 0, b->FXctx->height-(b->height-y), - b->width, 1, - 0, - pixbuf ); - - /* write to XImage back buffer */ - for (x=0;xwidth;x++) { - XMesaPutPixel(b->backimage,x,y, - xmesa_color_to_pixel(xmesa, - (pixbuf[x] & 0xf800) >> 8, - (pixbuf[x] & 0x07e0) >> 3, - (pixbuf[x] & 0x001f) << 3, - 0xff, - b->xm_visual->undithered_pf)); - } - } - } - /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ + (void) mode; + return GL_FALSE; } #endif + /* * Copy the back buffer to the front buffer. If there's no back buffer * this is a no-op. */ +PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { GET_CURRENT_CONTEXT(ctx); + if (!b->backxrb) { + /* single buffered */ + return; + } + /* If we're swapping the buffer associated with the current context * we have to flush any pending rendering commands first. */ if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) _mesa_notifySwapBuffers(ctx); - if (b->db_state) { + if (b->db_mode) { #ifdef FX - if (b->FXctx) { - fxMesaSwapBuffers(); - - if (b->FXwindowHack) - FXgetImage(b); - else - return; - } + if (FXswapBuffers(b)) + return; #endif - if (b->backimage) { - /* Copy Ximage from host's memory to server's window */ + if (b->backxrb->ximage) { + /* Copy Ximage (back buf) from client memory to server window */ #if defined(USE_XSHM) && !defined(XFree86Server) if (b->shm) { /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ - XShmPutImage( b->xm_visual->display, b->frontbuffer, + XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, - b->backimage, 0, 0, - 0, 0, b->width, b->height, False ); + b->backxrb->ximage, 0, 0, + 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, + False ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } else #endif { /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ - XMesaPutImage( b->xm_visual->display, b->frontbuffer, + XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, - b->backimage, 0, 0, - 0, 0, b->width, b->height ); + b->backxrb->ximage, 0, 0, + 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } } - else { - /* Copy pixmap to window on server */ + else if (b->backxrb->pixmap) { + /* Copy pixmap (back buf) to window (front buf) on server */ /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ XMesaCopyArea( b->xm_visual->display, - b->backpixmap, /* source drawable */ - b->frontbuffer, /* dest. drawable */ + b->backxrb->pixmap, /* source drawable */ + b->frontxrb->drawable, /* dest. drawable */ b->swapgc, - 0, 0, b->width, b->height, /* source region */ + 0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height, 0, 0 /* dest region */ ); /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ } + + if (b->swAlpha) + _mesa_copy_soft_alpha_renderbuffers(ctx, &b->mesa_buffer); } #if !defined(XFree86Server) XSync( b->xm_visual->display, False ); @@ -2423,25 +2066,25 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) _mesa_notifySwapBuffers(ctx); - if (b->db_state) { - int yTop = b->height - y - height; + if (!b->backxrb) { + /* single buffered */ + return; + } + + if (b->db_mode) { + int yTop = b->mesa_buffer.Height - y - height; #ifdef FX - if (b->FXctx) { - fxMesaSwapBuffers(); - if (b->FXwindowHack) - FXgetImage(b); - else - return; - } + if (FXswapBuffers(b)) + return; #endif - if (b->backimage) { + if (b->backxrb->ximage) { /* Copy Ximage from host's memory to server's window */ #if defined(USE_XSHM) && !defined(XFree86Server) if (b->shm) { /* XXX assuming width and height aren't too large! */ - XShmPutImage( b->xm_visual->display, b->frontbuffer, + XShmPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, - b->backimage, x, yTop, + b->backxrb->ximage, x, yTop, x, yTop, width, height, False ); /* wait for finished event??? */ } @@ -2449,17 +2092,17 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) #endif { /* XXX assuming width and height aren't too large! */ - XMesaPutImage( b->xm_visual->display, b->frontbuffer, + XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable, b->swapgc, - b->backimage, x, yTop, + b->backxrb->ximage, x, yTop, x, yTop, width, height ); } } else { /* Copy pixmap to window on server */ XMesaCopyArea( b->xm_visual->display, - b->backpixmap, /* source drawable */ - b->frontbuffer, /* dest. drawable */ + b->backxrb->pixmap, /* source drawable */ + b->frontxrb->drawable, /* dest. drawable */ b->swapgc, x, yTop, width, height, /* source region */ x, yTop /* dest region */ @@ -2478,13 +2121,16 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) * Return: GL_TRUE = context is double buffered * GL_FALSE = context is single buffered */ +#ifndef XFree86Server GLboolean XMesaGetBackBuffer( XMesaBuffer b, XMesaPixmap *pixmap, XMesaImage **ximage ) { - if (b->db_state) { - if (pixmap) *pixmap = b->backpixmap; - if (ximage) *ximage = b->backimage; + if (b->db_mode) { + if (pixmap) + *pixmap = b->backxrb->pixmap; + if (ximage) + *ximage = b->backxrb->ximage; return GL_TRUE; } else { @@ -2493,6 +2139,7 @@ GLboolean XMesaGetBackBuffer( XMesaBuffer b, return GL_FALSE; } } +#endif /* XFree86Server */ /* @@ -2506,7 +2153,9 @@ GLboolean XMesaGetBackBuffer( XMesaBuffer b, GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, GLint *bytesPerValue, void **buffer ) { - if (!b->mesa_buffer.DepthBuffer) { + struct gl_renderbuffer *rb + = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer; + if (!rb || !rb->Data) { *width = 0; *height = 0; *bytesPerValue = 0; @@ -2516,8 +2165,9 @@ GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, else { *width = b->mesa_buffer.Width; *height = b->mesa_buffer.Height; - *bytesPerValue = sizeof(GLdepth); - *buffer = b->mesa_buffer.DepthBuffer; + *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 + ? sizeof(GLushort) : sizeof(GLuint); + *buffer = rb->Data; return GL_TRUE; } } @@ -2556,7 +2206,7 @@ XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) { XMesaBuffer b; for (b=XMesaBufferList; b; b=b->Next) { - if (b->frontbuffer==d && b->display==dpy) { + if (b->frontxrb->drawable == d && b->display == dpy) { return b; } } @@ -2564,6 +2214,20 @@ XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) } +/** + * Free/destroy all XMesaBuffers associated with given display. + */ +void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy) +{ + XMesaBuffer b, next; + for (b = XMesaBufferList; b; b = next) { + next = b->Next; + if (b->display == dpy) { + xmesa_free_buffer(b); + } + } +} + /* * Look for XMesaBuffers whose X window has been destroyed. @@ -2574,12 +2238,12 @@ void XMesaGarbageCollect( void ) XMesaBuffer b, next; for (b=XMesaBufferList; b; b=next) { next = b->Next; - if (b->display && b->frontbuffer && b->type == WINDOW) { + if (b->display && b->frontxrb->drawable && b->type == WINDOW) { #ifdef XFree86Server /* NOT_NEEDED */ #else XSync(b->display, False); - if (!window_exists( b->display, b->frontbuffer )) { + if (!window_exists( b->display, b->frontxrb->drawable )) { /* found a dead window, free the ancillary info */ XMesaDestroyBuffer( b ); } @@ -2589,19 +2253,11 @@ void XMesaGarbageCollect( void ) } -void XMesaReset( void ) -{ - while (XMesaBufferList) - XMesaDestroyBuffer(XMesaBufferList); - - XMesaBufferList = NULL; -} - - unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) { + GLcontext *ctx = &xmesa->mesa; GLint r = (GLint) (red * 255.0F); GLint g = (GLint) (green * 255.0F); GLint b = (GLint) (blue * 255.0F); @@ -2618,6 +2274,8 @@ unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, } case PF_8A8B8G8R: return PACK_8A8B8G8R( r, g, b, a ); + case PF_8A8R8G8B: + return PACK_8A8R8G8B( r, g, b, a ); case PF_8R8G8B: return PACK_8R8G8B( r, g, b ); case PF_5R6G5B: @@ -2658,9 +2316,164 @@ unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, * This is typically called when the window size changes and we need * to reallocate the buffer's back/depth/stencil/accum buffers. */ -void XMesaResizeBuffers( XMesaBuffer b ) +PUBLIC void +XMesaResizeBuffers( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + XMesaContext xmctx = XMESA_CONTEXT(ctx); + if (!xmctx) + return; + xmesa_check_and_update_buffer_size(xmctx, b); +} + + +static GLint +xbuffer_to_renderbuffer(int buffer) +{ + assert(MAX_AUX_BUFFERS <= 4); + + switch (buffer) { + case GLX_FRONT_LEFT_EXT: + return BUFFER_FRONT_LEFT; + case GLX_FRONT_RIGHT_EXT: + return BUFFER_FRONT_RIGHT; + case GLX_BACK_LEFT_EXT: + return BUFFER_BACK_LEFT; + case GLX_BACK_RIGHT_EXT: + return BUFFER_BACK_RIGHT; + case GLX_AUX0_EXT: + return BUFFER_AUX0; + case GLX_AUX1_EXT: + return BUFFER_AUX1; + case GLX_AUX2_EXT: + return BUFFER_AUX2; + case GLX_AUX3_EXT: + return BUFFER_AUX3; + case GLX_AUX4_EXT: + case GLX_AUX5_EXT: + case GLX_AUX6_EXT: + case GLX_AUX7_EXT: + case GLX_AUX8_EXT: + case GLX_AUX9_EXT: + default: + /* BadValue error */ + return -1; + } +} + + +PUBLIC void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list) +{ +#if 0 + GET_CURRENT_CONTEXT(ctx); + const GLuint unit = ctx->Texture.CurrentUnit; + struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + struct gl_texture_object *texObj; +#endif + struct gl_renderbuffer *rb; + struct xmesa_renderbuffer *xrb; + GLint b; + XMesaImage *img; + GLboolean freeImg = GL_FALSE; + + b = xbuffer_to_renderbuffer(buffer); + if (b < 0) + return; + + if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT) + return; /* BadMatch error */ + + rb = drawable->mesa_buffer.Attachment[b].Renderbuffer; + if (!rb) { + /* invalid buffer */ + return; + } + xrb = xmesa_renderbuffer(rb); + +#if 0 + switch (drawable->TextureTarget) { + case GLX_TEXTURE_1D_EXT: + texObj = texUnit->Current1D; + break; + case GLX_TEXTURE_2D_EXT: + texObj = texUnit->Current2D; + break; + case GLX_TEXTURE_RECTANGLE_EXT: + texObj = texUnit->CurrentRect; + break; + default: + return; /* BadMatch error */ + } +#endif + + /* + * The following is a quick and simple way to implement + * BindTexImage. The better way is to write some new FetchTexel() + * functions which would extract texels from XImages. We'd still + * need to use XGetImage when texturing from a Pixmap (front buffer) + * but texturing from a back buffer (XImage) would avoid an image + * copy. + */ + + /* get XImage */ + if (xrb->pixmap) { + img = XGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, + AllPlanes, ZPixmap ); + freeImg = GL_TRUE; + } + else if (xrb->ximage) { + img = xrb->ximage; + } + + /* store the XImage as a new texture image */ + if (img) { + GLenum format, type, intFormat; + if (img->bits_per_pixel == 32) { + format = GL_BGRA; + type = GL_UNSIGNED_BYTE; + intFormat = GL_RGBA; + } + else if (img->bits_per_pixel == 24) { + format = GL_BGR; + type = GL_UNSIGNED_BYTE; + intFormat = GL_RGB; + } + else if (img->bits_per_pixel == 16) { + format = GL_BGR; + type = GL_UNSIGNED_SHORT_5_6_5; + intFormat = GL_RGB; + } + else { + _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage"); + return; + } + if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) { + intFormat = GL_RGBA; + } + else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) { + intFormat = GL_RGB; + } + + _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0, + format, type, img->data); + + if (freeImg) { + XMesaDestroyImage(img); + } + } +} + + + +PUBLIC void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) { - xmesa_resize_buffers( &(b->mesa_buffer) ); + const GLint b = xbuffer_to_renderbuffer(buffer); + if (b < 0) + return; + /* no-op for now */ }