xm_api.c revision 8570232b3b7930bd2ef58a337e9d57b12d3a8874
130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/*
230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Mesa 3-D graphics library
330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Version:  7.1
430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Permission is hereby granted, free of charge, to any person obtaining a
830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * copy of this software and associated documentation files (the "Software"),
930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * to deal in the Software without restriction, including without limitation
1030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * and/or sell copies of the Software, and to permit persons to whom the
1230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Software is furnished to do so, subject to the following conditions:
1330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
1430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * The above copyright notice and this permission notice shall be included
1530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * in all copies or substantial portions of the Software.
1630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
1730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
2430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
2530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/**
2630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * \file xm_api.c
2730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
2830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * All the XMesa* API functions.
2930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
3030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
3130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * NOTES:
3230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
3330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * The window coordinate system origin (0,0) is in the lower-left corner
3430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * of the window.  X11's window coordinate origin is in the upper-left
3530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * corner of the window.  Therefore, most drawing functions in this
3630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * file have to flip Y coordinates.
3730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
3830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
3930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Byte swapping:  If the Mesa host and the X display use a different
4030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * byte order then there's some trickiness to be aware of when using
4130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * XImages.  The byte ordering used for the XImage is that of the X
4230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * display, not the Mesa host.
4330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * The color-to-pixel encoding for True/DirectColor must be done
4430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * according to the display's visual red_mask, green_mask, and blue_mask.
4530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
4630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * do byte swapping if needed.  If one wants to directly "poke" the pixel
4730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * into the XImage's buffer then the pixel must be byte swapped first.
4830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *
4930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
5030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
5130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#ifdef __CYGWIN__
5230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#undef WIN32
5330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#undef __WIN32__
5430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#endif
5530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
5630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "xm_api.h"
5730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "xm_st.h"
5830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
5930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "main/context.h"
6030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "pipe/p_defines.h"
6130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "pipe/p_screen.h"
6230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "pipe/p_context.h"
6330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
6430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include "xm_public.h"
6530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#include <GL/glx.h>
6630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
6730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
6830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/* Driver interface routines, set up by xlib backend on library
6930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * _init().  These are global in the same way that function names are
7030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * global.
7130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
7230692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic struct xm_driver driver;
7330692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic struct st_api *stapi;
7430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
7530692c65c4174412c90e79489e98ab85c1a7412fBen Chengvoid xmesa_set_driver( const struct xm_driver *templ )
7630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng{
7730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   driver = *templ;
7830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   stapi = driver.create_st_api();
7930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng}
8030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
8130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
8230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/*
8330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * XXX replace this with a linked list, or better yet, try to attach the
8430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * gallium/mesa extra bits to the X Display object with XAddExtension().
8530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
8630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng#define MAX_DISPLAYS 10
8730692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic struct xmesa_display Displays[MAX_DISPLAYS];
8830692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic int NumDisplays = 0;
8930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
9030692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic int
9130692c65c4174412c90e79489e98ab85c1a7412fBen Chengxmesa_get_param(struct st_manager *smapi,
9230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng                enum st_manager_param param)
9330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng{
9430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   return 0;
9530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng}
9630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
9730692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic XMesaDisplay
9830692c65c4174412c90e79489e98ab85c1a7412fBen Chengxmesa_init_display( Display *display )
9930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng{
10030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   pipe_static_mutex(init_mutex);
10130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   XMesaDisplay xmdpy;
10230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   int i;
10330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
10430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   pipe_mutex_lock(init_mutex);
10530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
10630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   /* Look for XMesaDisplay which corresponds to 'display' */
10730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   for (i = 0; i < NumDisplays; i++) {
10830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      if (Displays[i].display == display) {
10930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         /* Found it */
11030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         pipe_mutex_unlock(init_mutex);
11130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         return &Displays[i];
11230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      }
11330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   }
11430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
11530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   /* Create new XMesaDisplay */
11630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
11730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   assert(NumDisplays < MAX_DISPLAYS);
11830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   xmdpy = &Displays[NumDisplays];
11930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   NumDisplays++;
12030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
12130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   if (!xmdpy->display && display) {
12230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      xmdpy->display = display;
12330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      xmdpy->screen = driver.create_pipe_screen(display);
12430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      xmdpy->smapi = CALLOC_STRUCT(st_manager);
12530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      if (xmdpy->smapi) {
12630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         xmdpy->smapi->screen = xmdpy->screen;
12730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         xmdpy->smapi->get_param = xmesa_get_param;
12830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      }
12930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
13030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      if (xmdpy->screen && xmdpy->smapi) {
13130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         pipe_mutex_init(xmdpy->mutex);
13230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      }
13330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      else {
13430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         if (xmdpy->screen) {
13530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng            xmdpy->screen->destroy(xmdpy->screen);
13630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng            xmdpy->screen = NULL;
13730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         }
13830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         if (xmdpy->smapi) {
13930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng            FREE(xmdpy->smapi);
14030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng            xmdpy->smapi = NULL;
14130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         }
14230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
14330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng         xmdpy->display = NULL;
14430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      }
14530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   }
14630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   if (!xmdpy->display || xmdpy->display != display)
14730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng      xmdpy = NULL;
14830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
14930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   pipe_mutex_unlock(init_mutex);
15030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
15130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   return xmdpy;
15230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng}
15330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
15430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/**********************************************************************/
15530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/*****                     X Utility Functions                    *****/
15630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/**********************************************************************/
15730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
15830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
15930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/**
16030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Return the host's byte order as LSBFirst or MSBFirst ala X.
16130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
16230692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic int host_byte_order( void )
16330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng{
16430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   int i = 1;
16530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   char *cptr = (char *) &i;
16630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   return (*cptr==1) ? LSBFirst : MSBFirst;
16730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng}
16830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
16930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
17030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
17130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
17230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/**
17330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Return the true number of bits per pixel for XImages.
17430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * For example, if we request a 24-bit deep visual we may actually need/get
17530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * 32bpp XImages.  This function returns the appropriate bpp.
17630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Input:  dpy - the X display
17730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *         visinfo - desribes the visual to be used for XImages
17830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Return:  true number of bits per pixel for XImages
17930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng */
18030692c65c4174412c90e79489e98ab85c1a7412fBen Chengstatic int
18130692c65c4174412c90e79489e98ab85c1a7412fBen Chengbits_per_pixel( XMesaVisual xmv )
18230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng{
18330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   Display *dpy = xmv->display;
18430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   XVisualInfo * visinfo = xmv->visinfo;
18530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   XImage *img;
18630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   int bitsPerPixel;
18730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   /* Create a temporary XImage */
18830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
18930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng		       ZPixmap, 0,           /*format, offset*/
19030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng		       (char*) MALLOC(8),    /*data*/
19130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng		       1, 1,                 /*width, height*/
19230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng		       32,                   /*bitmap_pad*/
19330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng		       0                     /*bytes_per_line*/
19430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng                     );
19530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   assert(img);
19630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   /* grab the bits/pixel value */
19730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   bitsPerPixel = img->bits_per_pixel;
19830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   /* free the XImage */
19930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   free( img->data );
20030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   img->data = NULL;
20130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   XDestroyImage( img );
20230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng   return bitsPerPixel;
20330692c65c4174412c90e79489e98ab85c1a7412fBen Cheng}
20430692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
20530692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
20630692c65c4174412c90e79489e98ab85c1a7412fBen Cheng
20730692c65c4174412c90e79489e98ab85c1a7412fBen Cheng/*
20830692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Determine if a given X window ID is valid (window exists).
20930692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Do this by calling XGetWindowAttributes() for the window and
21030692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * checking if we catch an X error.
21130692c65c4174412c90e79489e98ab85c1a7412fBen Cheng * Input:  dpy - the display
21230692c65c4174412c90e79489e98ab85c1a7412fBen Cheng *         win - the window to check for existance
213 * Return:  GL_TRUE - window exists
214 *          GL_FALSE - window doesn't exist
215 */
216static GLboolean WindowExistsFlag;
217
218static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
219{
220   (void) dpy;
221   if (xerr->error_code == BadWindow) {
222      WindowExistsFlag = GL_FALSE;
223   }
224   return 0;
225}
226
227static GLboolean window_exists( Display *dpy, Window win )
228{
229   XWindowAttributes wa;
230   int (*old_handler)( Display*, XErrorEvent* );
231   WindowExistsFlag = GL_TRUE;
232   old_handler = XSetErrorHandler(window_exists_err_handler);
233   XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
234   XSetErrorHandler(old_handler);
235   return WindowExistsFlag;
236}
237
238static Status
239get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
240{
241   Window root;
242   Status stat;
243   int xpos, ypos;
244   unsigned int w, h, bw, depth;
245   stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
246   *width = w;
247   *height = h;
248   return stat;
249}
250
251
252/**
253 * Return the size of the window (or pixmap) that corresponds to the
254 * given XMesaBuffer.
255 * \param width  returns width in pixels
256 * \param height  returns height in pixels
257 */
258void
259xmesa_get_window_size(Display *dpy, XMesaBuffer b,
260                      GLuint *width, GLuint *height)
261{
262   XMesaDisplay xmdpy = xmesa_init_display(dpy);
263   Status stat;
264
265   pipe_mutex_lock(xmdpy->mutex);
266   XSync(b->xm_visual->display, 0); /* added for Chromium */
267   stat = get_drawable_size(dpy, b->ws.drawable, width, height);
268   pipe_mutex_unlock(xmdpy->mutex);
269
270   if (!stat) {
271      /* probably querying a window that's recently been destroyed */
272      _mesa_warning(NULL, "XGetGeometry failed!\n");
273      *width = *height = 1;
274   }
275}
276
277#define GET_REDMASK(__v)        __v->mesa_visual.redMask
278#define GET_GREENMASK(__v)      __v->mesa_visual.greenMask
279#define GET_BLUEMASK(__v)       __v->mesa_visual.blueMask
280
281
282/**
283 * Choose the pixel format for the given visual.
284 * This will tell the gallium driver how to pack pixel data into
285 * drawing surfaces.
286 */
287static GLuint
288choose_pixel_format(XMesaVisual v)
289{
290   boolean native_byte_order = (host_byte_order() ==
291                                ImageByteOrder(v->display));
292
293   if (   GET_REDMASK(v)   == 0x0000ff
294       && GET_GREENMASK(v) == 0x00ff00
295       && GET_BLUEMASK(v)  == 0xff0000
296       && v->BitsPerPixel == 32) {
297      if (native_byte_order) {
298         /* no byteswapping needed */
299         return PIPE_FORMAT_R8G8B8A8_UNORM;
300      }
301      else {
302         return PIPE_FORMAT_A8B8G8R8_UNORM;
303      }
304   }
305   else if (   GET_REDMASK(v)   == 0xff0000
306            && GET_GREENMASK(v) == 0x00ff00
307            && GET_BLUEMASK(v)  == 0x0000ff
308            && v->BitsPerPixel == 32) {
309      if (native_byte_order) {
310         /* no byteswapping needed */
311         return PIPE_FORMAT_B8G8R8A8_UNORM;
312      }
313      else {
314         return PIPE_FORMAT_A8R8G8B8_UNORM;
315      }
316   }
317   else if (   GET_REDMASK(v)   == 0x0000ff00
318            && GET_GREENMASK(v) == 0x00ff0000
319            && GET_BLUEMASK(v)  == 0xff000000
320            && v->BitsPerPixel == 32) {
321      if (native_byte_order) {
322         /* no byteswapping needed */
323         return PIPE_FORMAT_A8R8G8B8_UNORM;
324      }
325      else {
326         return PIPE_FORMAT_B8G8R8A8_UNORM;
327      }
328   }
329   else if (   GET_REDMASK(v)   == 0xf800
330            && GET_GREENMASK(v) == 0x07e0
331            && GET_BLUEMASK(v)  == 0x001f
332            && native_byte_order
333            && v->BitsPerPixel == 16) {
334      /* 5-6-5 RGB */
335      return PIPE_FORMAT_B5G6R5_UNORM;
336   }
337
338   return PIPE_FORMAT_NONE;
339}
340
341
342/**
343 * Choose a depth/stencil format that satisfies the given depth and
344 * stencil sizes.
345 */
346static enum pipe_format
347choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil)
348{
349   const enum pipe_texture_target target = PIPE_TEXTURE_2D;
350   const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL;
351   const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE |
352                                PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO);
353   const unsigned sample_count = 0;
354   enum pipe_format formats[8], fmt;
355   int count, i;
356
357   count = 0;
358
359   if (depth <= 16 && stencil == 0) {
360      formats[count++] = PIPE_FORMAT_Z16_UNORM;
361   }
362   if (depth <= 24 && stencil == 0) {
363      formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
364      formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
365   }
366   if (depth <= 24 && stencil <= 8) {
367      formats[count++] = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
368      formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
369   }
370   if (depth <= 32 && stencil == 0) {
371      formats[count++] = PIPE_FORMAT_Z32_UNORM;
372   }
373
374   fmt = PIPE_FORMAT_NONE;
375   for (i = 0; i < count; i++) {
376      if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
377                                             target, sample_count,
378                                             tex_usage, geom_flags)) {
379         fmt = formats[i];
380         break;
381      }
382   }
383
384   return fmt;
385}
386
387
388
389/**********************************************************************/
390/*****                Linked list of XMesaBuffers                 *****/
391/**********************************************************************/
392
393static XMesaBuffer XMesaBufferList = NULL;
394
395
396/**
397 * Allocate a new XMesaBuffer object which corresponds to the given drawable.
398 * Note that XMesaBuffer is derived from GLframebuffer.
399 * The new XMesaBuffer will not have any size (Width=Height=0).
400 *
401 * \param d  the corresponding X drawable (window or pixmap)
402 * \param type  either WINDOW, PIXMAP or PBUFFER, describing d
403 * \param vis  the buffer's visual
404 * \param cmap  the window's colormap, if known.
405 * \return new XMesaBuffer or NULL if any problem
406 */
407static XMesaBuffer
408create_xmesa_buffer(Drawable d, BufferType type,
409                    XMesaVisual vis, Colormap cmap)
410{
411   XMesaDisplay xmdpy = xmesa_init_display(vis->display);
412   XMesaBuffer b;
413   uint width, height;
414
415   ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
416
417   if (!xmdpy)
418      return NULL;
419
420   b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
421   if (!b)
422      return NULL;
423
424   b->ws.drawable = d;
425   b->ws.visual = vis->visinfo->visual;
426   b->ws.depth = vis->visinfo->depth;
427
428   b->xm_visual = vis;
429   b->type = type;
430   b->cmap = cmap;
431
432   get_drawable_size(vis->display, d, &width, &height);
433
434   /*
435    * Create framebuffer, but we'll plug in our own renderbuffers below.
436    */
437   b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
438
439   /* GLX_EXT_texture_from_pixmap */
440   b->TextureTarget = 0;
441   b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
442   b->TextureMipmap = 0;
443
444   /* insert buffer into linked list */
445   b->Next = XMesaBufferList;
446   XMesaBufferList = b;
447
448   return b;
449}
450
451
452/**
453 * Find an XMesaBuffer by matching X display and colormap but NOT matching
454 * the notThis buffer.
455 */
456XMesaBuffer
457xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
458{
459   XMesaBuffer b;
460   for (b = XMesaBufferList; b; b = b->Next) {
461      if (b->xm_visual->display == dpy &&
462          b->cmap == cmap &&
463          b != notThis) {
464         return b;
465      }
466   }
467   return NULL;
468}
469
470
471/**
472 * Remove buffer from linked list, delete if no longer referenced.
473 */
474static void
475xmesa_free_buffer(XMesaBuffer buffer)
476{
477   XMesaBuffer prev = NULL, b;
478
479   for (b = XMesaBufferList; b; b = b->Next) {
480      if (b == buffer) {
481         /* unlink buffer from list */
482         if (prev)
483            prev->Next = buffer->Next;
484         else
485            XMesaBufferList = buffer->Next;
486
487         /* Since the X window for the XMesaBuffer is going away, we don't
488          * want to dereference this pointer in the future.
489          */
490         b->ws.drawable = 0;
491
492         /* XXX we should move the buffer to a delete-pending list and destroy
493          * the buffer until it is no longer current.
494          */
495         xmesa_destroy_st_framebuffer(buffer->stfb);
496
497         free(buffer);
498
499         return;
500      }
501      /* continue search */
502      prev = b;
503   }
504   /* buffer not found in XMesaBufferList */
505   _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
506}
507
508
509
510/**********************************************************************/
511/*****                   Misc Private Functions                   *****/
512/**********************************************************************/
513
514
515/**
516 * When a context is bound for the first time, we can finally finish
517 * initializing the context's visual and buffer information.
518 * \param v  the XMesaVisual to initialize
519 * \param b  the XMesaBuffer to initialize (may be NULL)
520 * \param rgb_flag  TRUE = RGBA mode, FALSE = color index mode
521 * \param window  the window/pixmap we're rendering into
522 * \param cmap  the colormap associated with the window/pixmap
523 * \return GL_TRUE=success, GL_FALSE=failure
524 */
525static GLboolean
526initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
527                             GLboolean rgb_flag, Drawable window,
528                             Colormap cmap)
529{
530   ASSERT(!b || b->xm_visual == v);
531
532   /* Save true bits/pixel */
533   v->BitsPerPixel = bits_per_pixel(v);
534   assert(v->BitsPerPixel > 0);
535
536   if (rgb_flag == GL_FALSE) {
537      /* COLOR-INDEXED WINDOW: not supported*/
538      return GL_FALSE;
539   }
540   else {
541      /* RGB WINDOW:
542       * We support RGB rendering into almost any kind of visual.
543       */
544      const int xclass = v->mesa_visual.visualType;
545      if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
546	 _mesa_warning(NULL,
547            "XMesa: RGB mode rendering not supported in given visual.\n");
548	 return GL_FALSE;
549      }
550      v->mesa_visual.indexBits = 0;
551
552      if (v->BitsPerPixel == 32) {
553         /* We use XImages for all front/back buffers.  If an X Window or
554          * X Pixmap is 32bpp, there's no guarantee that the alpha channel
555          * will be preserved.  For XImages we're in luck.
556          */
557         v->mesa_visual.alphaBits = 8;
558      }
559   }
560
561   /*
562    * If MESA_INFO env var is set print out some debugging info
563    * which can help Brian figure out what's going on when a user
564    * reports bugs.
565    */
566   if (_mesa_getenv("MESA_INFO")) {
567      printf("X/Mesa visual = %p\n", (void *) v);
568      printf("X/Mesa level = %d\n", v->mesa_visual.level);
569      printf("X/Mesa depth = %d\n", v->visinfo->depth);
570      printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
571   }
572
573   return GL_TRUE;
574}
575
576
577
578#define NUM_VISUAL_TYPES   6
579
580/**
581 * Convert an X visual type to a GLX visual type.
582 *
583 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
584 *        to be converted.
585 * \return If \c visualType is a valid X visual type, a GLX visual type will
586 *         be returned.  Otherwise \c GLX_NONE will be returned.
587 *
588 * \note
589 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
590 * DRI CVS tree.
591 */
592static GLint
593xmesa_convert_from_x_visual_type( int visualType )
594{
595    static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
596	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
597	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
598	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
599    };
600
601    return ( (unsigned) visualType < NUM_VISUAL_TYPES )
602	? glx_visual_types[ visualType ] : GLX_NONE;
603}
604
605
606/**********************************************************************/
607/*****                       Public Functions                     *****/
608/**********************************************************************/
609
610
611/*
612 * Create a new X/Mesa visual.
613 * Input:  display - X11 display
614 *         visinfo - an XVisualInfo pointer
615 *         rgb_flag - GL_TRUE = RGB mode,
616 *                    GL_FALSE = color index mode
617 *         alpha_flag - alpha buffer requested?
618 *         db_flag - GL_TRUE = double-buffered,
619 *                   GL_FALSE = single buffered
620 *         stereo_flag - stereo visual?
621 *         ximage_flag - GL_TRUE = use an XImage for back buffer,
622 *                       GL_FALSE = use an off-screen pixmap for back buffer
623 *         depth_size - requested bits/depth values, or zero
624 *         stencil_size - requested bits/stencil values, or zero
625 *         accum_red_size - requested bits/red accum values, or zero
626 *         accum_green_size - requested bits/green accum values, or zero
627 *         accum_blue_size - requested bits/blue accum values, or zero
628 *         accum_alpha_size - requested bits/alpha accum values, or zero
629 *         num_samples - number of samples/pixel if multisampling, or zero
630 *         level - visual level, usually 0
631 *         visualCaveat - ala the GLX extension, usually GLX_NONE
632 * Return;  a new XMesaVisual or 0 if error.
633 */
634PUBLIC
635XMesaVisual XMesaCreateVisual( Display *display,
636                               XVisualInfo * visinfo,
637                               GLboolean rgb_flag,
638                               GLboolean alpha_flag,
639                               GLboolean db_flag,
640                               GLboolean stereo_flag,
641                               GLboolean ximage_flag,
642                               GLint depth_size,
643                               GLint stencil_size,
644                               GLint accum_red_size,
645                               GLint accum_green_size,
646                               GLint accum_blue_size,
647                               GLint accum_alpha_size,
648                               GLint num_samples,
649                               GLint level,
650                               GLint visualCaveat )
651{
652   XMesaDisplay xmdpy = xmesa_init_display(display);
653   XMesaVisual v;
654   GLint red_bits, green_bits, blue_bits, alpha_bits;
655
656   if (!xmdpy)
657      return NULL;
658
659   /* For debugging only */
660   if (_mesa_getenv("MESA_XSYNC")) {
661      /* This makes debugging X easier.
662       * In your debugger, set a breakpoint on _XError to stop when an
663       * X protocol error is generated.
664       */
665      XSynchronize( display, 1 );
666   }
667
668   v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
669   if (!v) {
670      return NULL;
671   }
672
673   v->display = display;
674
675   /* Save a copy of the XVisualInfo struct because the user may Xfree()
676    * the struct but we may need some of the information contained in it
677    * at a later time.
678    */
679   v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
680   if (!v->visinfo) {
681      free(v);
682      return NULL;
683   }
684   memcpy(v->visinfo, visinfo, sizeof(*visinfo));
685
686   v->ximage_flag = ximage_flag;
687
688   v->mesa_visual.redMask = visinfo->red_mask;
689   v->mesa_visual.greenMask = visinfo->green_mask;
690   v->mesa_visual.blueMask = visinfo->blue_mask;
691   v->mesa_visual.visualID = visinfo->visualid;
692   v->mesa_visual.screen = visinfo->screen;
693
694#if !(defined(__cplusplus) || defined(c_plusplus))
695   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
696#else
697   v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
698#endif
699
700   v->mesa_visual.visualRating = visualCaveat;
701
702   if (alpha_flag)
703      v->mesa_visual.alphaBits = 8;
704
705   (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
706
707   {
708      const int xclass = v->mesa_visual.visualType;
709      if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
710         red_bits   = _mesa_bitcount(GET_REDMASK(v));
711         green_bits = _mesa_bitcount(GET_GREENMASK(v));
712         blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
713      }
714      else {
715         /* this is an approximation */
716         int depth;
717         depth = v->visinfo->depth;
718         red_bits = depth / 3;
719         depth -= red_bits;
720         green_bits = depth / 2;
721         depth -= green_bits;
722         blue_bits = depth;
723         alpha_bits = 0;
724         assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
725      }
726      alpha_bits = v->mesa_visual.alphaBits;
727   }
728
729   _mesa_initialize_visual( &v->mesa_visual,
730                            db_flag, stereo_flag,
731                            red_bits, green_bits,
732                            blue_bits, alpha_bits,
733                            depth_size,
734                            stencil_size,
735                            accum_red_size, accum_green_size,
736                            accum_blue_size, accum_alpha_size,
737                            0 );
738
739   v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
740   if (db_flag)
741      v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
742   if (stereo_flag) {
743      v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
744      if (db_flag)
745         v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
746   }
747
748   v->stvis.color_format = choose_pixel_format(v);
749   if (v->stvis.color_format == PIPE_FORMAT_NONE) {
750      FREE(v->visinfo);
751      FREE(v);
752      return NULL;
753   }
754
755   v->stvis.depth_stencil_format =
756      choose_depth_stencil_format(xmdpy, depth_size, stencil_size);
757
758   v->stvis.accum_format = (accum_red_size +
759         accum_green_size + accum_blue_size + accum_alpha_size) ?
760      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
761
762   v->stvis.samples = num_samples;
763   v->stvis.render_buffer = ST_ATTACHMENT_INVALID;
764
765   /* XXX minor hack */
766   v->mesa_visual.level = level;
767   return v;
768}
769
770
771PUBLIC
772void XMesaDestroyVisual( XMesaVisual v )
773{
774   free(v->visinfo);
775   free(v);
776}
777
778
779/**
780 * Do per-display initializations.
781 */
782void
783xmesa_init( Display *display )
784{
785   xmesa_init_display(display);
786}
787
788
789/**
790 * Create a new XMesaContext.
791 * \param v  the XMesaVisual
792 * \param share_list  another XMesaContext with which to share display
793 *                    lists or NULL if no sharing is wanted.
794 * \return an XMesaContext or NULL if error.
795 */
796PUBLIC
797XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
798{
799   XMesaDisplay xmdpy = xmesa_init_display(v->display);
800   XMesaContext c;
801
802   if (!xmdpy)
803      return NULL;
804
805   /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
806   c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
807   if (!c)
808      return NULL;
809
810   c->xm_visual = v;
811   c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
812   c->xm_read_buffer = NULL;
813
814   c->st = stapi->create_context(stapi, xmdpy->smapi,
815         &v->stvis, (share_list) ? share_list->st : NULL);
816   if (c->st == NULL)
817      goto fail;
818
819   c->st->st_manager_private = (void *) c;
820
821   return c;
822
823fail:
824   if (c->st)
825      c->st->destroy(c->st);
826
827   free(c);
828   return NULL;
829}
830
831
832
833PUBLIC
834void XMesaDestroyContext( XMesaContext c )
835{
836   c->st->destroy(c->st);
837
838   /* FIXME: We should destroy the screen here, but if we do so, surfaces may
839    * outlive it, causing segfaults
840   struct pipe_screen *screen = c->st->pipe->screen;
841   screen->destroy(screen);
842   */
843
844   free(c);
845}
846
847
848
849/**
850 * Private function for creating an XMesaBuffer which corresponds to an
851 * X window or pixmap.
852 * \param v  the window's XMesaVisual
853 * \param w  the window we're wrapping
854 * \return  new XMesaBuffer or NULL if error
855 */
856PUBLIC XMesaBuffer
857XMesaCreateWindowBuffer(XMesaVisual v, Window w)
858{
859   XWindowAttributes attr;
860   XMesaBuffer b;
861   Colormap cmap;
862   int depth;
863
864   assert(v);
865   assert(w);
866
867   /* Check that window depth matches visual depth */
868   XGetWindowAttributes( v->display, w, &attr );
869   depth = attr.depth;
870   if (v->visinfo->depth != depth) {
871      _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
872                    v->visinfo->depth, depth);
873      return NULL;
874   }
875
876   /* Find colormap */
877   if (attr.colormap) {
878      cmap = attr.colormap;
879   }
880   else {
881      _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
882      /* this is weird, a window w/out a colormap!? */
883      /* OK, let's just allocate a new one and hope for the best */
884      cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
885   }
886
887   b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
888   if (!b)
889      return NULL;
890
891   if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
892                                      (Drawable) w, cmap )) {
893      xmesa_free_buffer(b);
894      return NULL;
895   }
896
897   return b;
898}
899
900
901
902/**
903 * Create a new XMesaBuffer from an X pixmap.
904 *
905 * \param v    the XMesaVisual
906 * \param p    the pixmap
907 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
908 *             \c GLX_DIRECT_COLOR visual for the pixmap
909 * \returns new XMesaBuffer or NULL if error
910 */
911PUBLIC XMesaBuffer
912XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
913{
914   XMesaBuffer b;
915
916   assert(v);
917
918   b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
919   if (!b)
920      return NULL;
921
922   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
923				     (Drawable) p, cmap)) {
924      xmesa_free_buffer(b);
925      return NULL;
926   }
927
928   return b;
929}
930
931
932/**
933 * For GLX_EXT_texture_from_pixmap
934 */
935XMesaBuffer
936XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
937                               Colormap cmap,
938                               int format, int target, int mipmap)
939{
940   GET_CURRENT_CONTEXT(ctx);
941   XMesaBuffer b;
942
943   assert(v);
944
945   b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
946   if (!b)
947      return NULL;
948
949   /* get pixmap size */
950   xmesa_get_window_size(v->display, b, &b->width, &b->height);
951
952   if (target == 0) {
953      /* examine dims */
954      if (ctx->Extensions.ARB_texture_non_power_of_two) {
955         target = GLX_TEXTURE_2D_EXT;
956      }
957      else if (   _mesa_bitcount(b->width)  == 1
958               && _mesa_bitcount(b->height) == 1) {
959         /* power of two size */
960         if (b->height == 1) {
961            target = GLX_TEXTURE_1D_EXT;
962         }
963         else {
964            target = GLX_TEXTURE_2D_EXT;
965         }
966      }
967      else if (ctx->Extensions.NV_texture_rectangle) {
968         target = GLX_TEXTURE_RECTANGLE_EXT;
969      }
970      else {
971         /* non power of two textures not supported */
972         XMesaDestroyBuffer(b);
973         return 0;
974      }
975   }
976
977   b->TextureTarget = target;
978   b->TextureFormat = format;
979   b->TextureMipmap = mipmap;
980
981   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
982				     (Drawable) p, cmap)) {
983      xmesa_free_buffer(b);
984      return NULL;
985   }
986
987   return b;
988}
989
990
991
992XMesaBuffer
993XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
994                   unsigned int width, unsigned int height)
995{
996   Window root;
997   Drawable drawable;  /* X Pixmap Drawable */
998   XMesaBuffer b;
999
1000   /* allocate pixmap for front buffer */
1001   root = RootWindow( v->display, v->visinfo->screen );
1002   drawable = XCreatePixmap(v->display, root, width, height,
1003                            v->visinfo->depth);
1004   if (!drawable)
1005      return NULL;
1006
1007   b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1008   if (!b)
1009      return NULL;
1010
1011   if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1012				     drawable, cmap)) {
1013      xmesa_free_buffer(b);
1014      return NULL;
1015   }
1016
1017   return b;
1018}
1019
1020
1021
1022/*
1023 * Deallocate an XMesaBuffer structure and all related info.
1024 */
1025PUBLIC void
1026XMesaDestroyBuffer(XMesaBuffer b)
1027{
1028   xmesa_free_buffer(b);
1029}
1030
1031
1032/**
1033 * Query the current drawable size and notify the binding context.
1034 */
1035void
1036xmesa_check_buffer_size(XMesaBuffer b)
1037{
1038   XMesaContext xmctx = XMesaGetCurrentContext();
1039
1040   if (b->type == PBUFFER)
1041      return;
1042
1043   xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
1044   if (xmctx && xmctx->xm_buffer == b)
1045      xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb);
1046}
1047
1048
1049/*
1050 * Bind buffer b to context c and make c the current rendering context.
1051 */
1052PUBLIC
1053GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1054                             XMesaBuffer readBuffer )
1055{
1056   XMesaContext old_ctx = XMesaGetCurrentContext();
1057
1058   if (old_ctx && old_ctx != c) {
1059      XMesaFlush(old_ctx);
1060      old_ctx->xm_buffer = NULL;
1061      old_ctx->xm_read_buffer = NULL;
1062   }
1063
1064   if (c) {
1065      if (!drawBuffer || !readBuffer)
1066         return GL_FALSE;  /* must specify buffers! */
1067
1068      if (c == old_ctx &&
1069	  c->xm_buffer == drawBuffer &&
1070	  c->xm_read_buffer == readBuffer)
1071	 return GL_TRUE;
1072
1073      xmesa_check_buffer_size(drawBuffer);
1074      if (readBuffer != drawBuffer)
1075         xmesa_check_buffer_size(readBuffer);
1076
1077      c->xm_buffer = drawBuffer;
1078      c->xm_read_buffer = readBuffer;
1079
1080      stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb);
1081
1082      /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1083      drawBuffer->wasCurrent = GL_TRUE;
1084   }
1085   else {
1086      /* Detach */
1087      stapi->make_current(stapi, NULL, NULL, NULL);
1088
1089   }
1090   return GL_TRUE;
1091}
1092
1093
1094/*
1095 * Unbind the context c from its buffer.
1096 */
1097GLboolean XMesaUnbindContext( XMesaContext c )
1098{
1099   /* A no-op for XFree86 integration purposes */
1100   return GL_TRUE;
1101}
1102
1103
1104XMesaContext XMesaGetCurrentContext( void )
1105{
1106   struct st_context_iface *st = stapi->get_current(stapi);
1107   return (XMesaContext) (st) ? st->st_manager_private : NULL;
1108}
1109
1110
1111
1112/**
1113 * Swap front and back color buffers and have winsys display front buffer.
1114 * If there's no front color buffer no swap actually occurs.
1115 */
1116PUBLIC
1117void XMesaSwapBuffers( XMesaBuffer b )
1118{
1119   XMesaContext xmctx = XMesaGetCurrentContext();
1120
1121   if (xmctx && xmctx->xm_buffer == b) {
1122      xmctx->st->flush( xmctx->st,
1123            PIPE_FLUSH_RENDER_CACHE |
1124            PIPE_FLUSH_SWAPBUFFERS |
1125            PIPE_FLUSH_FRAME,
1126            NULL);
1127   }
1128
1129   xmesa_swap_st_framebuffer(b->stfb);
1130}
1131
1132
1133
1134/*
1135 * Copy sub-region of back buffer to front buffer
1136 */
1137void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1138{
1139   xmesa_copy_st_framebuffer(b->stfb,
1140         ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
1141         x, y, width, height);
1142}
1143
1144
1145
1146void XMesaFlush( XMesaContext c )
1147{
1148   if (c && c->xm_visual->display) {
1149      XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
1150      struct pipe_fence_handle *fence = NULL;
1151
1152      c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
1153      if (fence) {
1154         xmdpy->screen->fence_finish(xmdpy->screen, fence, 0);
1155         xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
1156      }
1157      XFlush( c->xm_visual->display );
1158   }
1159}
1160
1161
1162
1163
1164
1165XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
1166{
1167   XMesaBuffer b;
1168   for (b = XMesaBufferList; b; b = b->Next) {
1169      if (b->ws.drawable == d && b->xm_visual->display == dpy) {
1170         return b;
1171      }
1172   }
1173   return NULL;
1174}
1175
1176
1177/**
1178 * Free/destroy all XMesaBuffers associated with given display.
1179 */
1180void xmesa_destroy_buffers_on_display(Display *dpy)
1181{
1182   XMesaBuffer b, next;
1183   for (b = XMesaBufferList; b; b = next) {
1184      next = b->Next;
1185      if (b->xm_visual->display == dpy) {
1186         xmesa_free_buffer(b);
1187         /* delete head of list? */
1188         if (XMesaBufferList == b) {
1189            XMesaBufferList = next;
1190         }
1191      }
1192   }
1193}
1194
1195
1196/*
1197 * Look for XMesaBuffers whose X window has been destroyed.
1198 * Deallocate any such XMesaBuffers.
1199 */
1200void XMesaGarbageCollect( void )
1201{
1202   XMesaBuffer b, next;
1203   for (b=XMesaBufferList; b; b=next) {
1204      next = b->Next;
1205      if (b->xm_visual &&
1206          b->xm_visual->display &&
1207          b->ws.drawable &&
1208          b->type == WINDOW) {
1209         XSync(b->xm_visual->display, False);
1210         if (!window_exists( b->xm_visual->display, b->ws.drawable )) {
1211            /* found a dead window, free the ancillary info */
1212            XMesaDestroyBuffer( b );
1213         }
1214      }
1215   }
1216}
1217
1218
1219
1220
1221PUBLIC void
1222XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
1223                  const int *attrib_list)
1224{
1225}
1226
1227
1228
1229PUBLIC void
1230XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
1231{
1232}
1233
1234
1235void
1236XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
1237{
1238   if (dst->st->copy)
1239      dst->st->copy(dst->st, src->st, mask);
1240}
1241