Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1 | /* |
| 2 | * Mesa 3-D graphics library |
| 3 | * Version: 7.1 |
| 4 | * |
| 5 | * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
| 6 | * |
| 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 8 | * copy of this software and associated documentation files (the "Software"), |
| 9 | * to deal in the Software without restriction, including without limitation |
| 10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 11 | * and/or sell copies of the Software, and to permit persons to whom the |
| 12 | * Software is furnished to do so, subject to the following conditions: |
| 13 | * |
| 14 | * The above copyright notice and this permission notice shall be included |
| 15 | * in all copies or substantial portions of the Software. |
| 16 | * |
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 20 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| 21 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 23 | */ |
| 24 | |
| 25 | /** |
| 26 | * \file xm_api.c |
| 27 | * |
| 28 | * All the XMesa* API functions. |
| 29 | * |
| 30 | * |
| 31 | * NOTES: |
| 32 | * |
| 33 | * The window coordinate system origin (0,0) is in the lower-left corner |
| 34 | * of the window. X11's window coordinate origin is in the upper-left |
| 35 | * corner of the window. Therefore, most drawing functions in this |
| 36 | * file have to flip Y coordinates. |
| 37 | * |
| 38 | * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile |
| 39 | * in support for the MIT Shared Memory extension. If enabled, when you |
| 40 | * use an Ximage for the back buffer in double buffered mode, the "swap" |
| 41 | * operation will be faster. You must also link with -lXext. |
| 42 | * |
| 43 | * Byte swapping: If the Mesa host and the X display use a different |
| 44 | * byte order then there's some trickiness to be aware of when using |
| 45 | * XImages. The byte ordering used for the XImage is that of the X |
| 46 | * display, not the Mesa host. |
| 47 | * The color-to-pixel encoding for True/DirectColor must be done |
| 48 | * according to the display's visual red_mask, green_mask, and blue_mask. |
| 49 | * If XPutPixel is used to put a pixel into an XImage then XPutPixel will |
| 50 | * do byte swapping if needed. If one wants to directly "poke" the pixel |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 51 | * into the XImage's buffer then the pixel must be byte swapped first. |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 52 | * |
| 53 | */ |
| 54 | |
| 55 | #ifdef __CYGWIN__ |
| 56 | #undef WIN32 |
| 57 | #undef __WIN32__ |
| 58 | #endif |
| 59 | |
Keith Whitwell | 25deb85 | 2009-01-08 15:42:15 +0000 | [diff] [blame] | 60 | #include "xm_api.h" |
Brian | 6f467e5 | 2007-12-11 19:16:26 -0700 | [diff] [blame] | 61 | #include "main/context.h" |
| 62 | #include "main/framebuffer.h" |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 63 | |
| 64 | #include "state_tracker/st_public.h" |
| 65 | #include "state_tracker/st_context.h" |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 66 | #include "pipe/p_defines.h" |
José Fonseca | 969ff9e | 2008-08-14 10:47:39 +0100 | [diff] [blame] | 67 | #include "pipe/p_screen.h" |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 68 | #include "pipe/p_context.h" |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 69 | |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 70 | #include "trace/tr_screen.h" |
| 71 | #include "trace/tr_context.h" |
| 72 | #include "trace/tr_texture.h" |
| 73 | |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 74 | #include "xm_winsys.h" |
Keith Whitwell | 05f8e41 | 2009-01-09 10:40:47 +0000 | [diff] [blame] | 75 | #include <GL/glx.h> |
Zack Rusin | c474f1f | 2007-12-11 07:19:11 -0500 | [diff] [blame] | 76 | |
Keith Whitwell | 2f19fec | 2009-01-13 18:08:24 +0000 | [diff] [blame] | 77 | |
| 78 | /* Driver interface routines, set up by xlib backend on library |
| 79 | * _init(). These are global in the same way that function names are |
| 80 | * global. |
| 81 | */ |
| 82 | static struct xm_driver driver; |
| 83 | |
| 84 | void xmesa_set_driver( const struct xm_driver *templ ) |
| 85 | { |
| 86 | driver = *templ; |
| 87 | } |
| 88 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 89 | /** |
| 90 | * Global X driver lock |
| 91 | */ |
Brian Paul | 0bb852f | 2008-08-26 16:35:12 -0600 | [diff] [blame] | 92 | pipe_mutex _xmesa_lock; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 93 | |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 94 | static struct pipe_screen *_screen = NULL; |
| 95 | static struct pipe_screen *screen = NULL; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 96 | |
| 97 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 98 | /**********************************************************************/ |
| 99 | /***** X Utility Functions *****/ |
| 100 | /**********************************************************************/ |
| 101 | |
| 102 | |
| 103 | /** |
| 104 | * Return the host's byte order as LSBFirst or MSBFirst ala X. |
| 105 | */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 106 | static int host_byte_order( void ) |
| 107 | { |
| 108 | int i = 1; |
| 109 | char *cptr = (char *) &i; |
| 110 | return (*cptr==1) ? LSBFirst : MSBFirst; |
| 111 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 112 | |
| 113 | |
| 114 | /** |
| 115 | * Check if the X Shared Memory extension is available. |
| 116 | * Return: 0 = not available |
| 117 | * 1 = shared XImage support available |
| 118 | * 2 = shared Pixmap support available also |
| 119 | */ |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 120 | int xmesa_check_for_xshm( Display *display ) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 121 | { |
Keith Whitwell | 18ad0e3 | 2009-01-08 15:00:27 +0000 | [diff] [blame] | 122 | #if defined(USE_XSHM) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 123 | int major, minor, ignore; |
| 124 | Bool pixmaps; |
| 125 | |
Keith Whitwell | fec1d21 | 2008-05-08 22:10:15 +0100 | [diff] [blame] | 126 | if (getenv("SP_NO_RAST")) |
| 127 | return 0; |
| 128 | |
Ian Romanick | b09de96 | 2008-03-25 18:07:56 -0700 | [diff] [blame] | 129 | if (getenv("MESA_NOSHM")) { |
| 130 | return 0; |
| 131 | } |
| 132 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 133 | if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { |
| 134 | if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { |
| 135 | return (pixmaps==True) ? 2 : 1; |
| 136 | } |
| 137 | else { |
| 138 | return 0; |
| 139 | } |
| 140 | } |
| 141 | else { |
| 142 | return 0; |
| 143 | } |
| 144 | #else |
| 145 | /* No XSHM support */ |
| 146 | return 0; |
| 147 | #endif |
| 148 | } |
| 149 | |
| 150 | |
| 151 | /** |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 152 | * Return the true number of bits per pixel for XImages. |
| 153 | * For example, if we request a 24-bit deep visual we may actually need/get |
| 154 | * 32bpp XImages. This function returns the appropriate bpp. |
| 155 | * Input: dpy - the X display |
| 156 | * visinfo - desribes the visual to be used for XImages |
| 157 | * Return: true number of bits per pixel for XImages |
| 158 | */ |
| 159 | static int |
| 160 | bits_per_pixel( XMesaVisual xmv ) |
| 161 | { |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 162 | Display *dpy = xmv->display; |
| 163 | XVisualInfo * visinfo = xmv->visinfo; |
| 164 | XImage *img; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 165 | int bitsPerPixel; |
| 166 | /* Create a temporary XImage */ |
| 167 | img = XCreateImage( dpy, visinfo->visual, visinfo->depth, |
| 168 | ZPixmap, 0, /*format, offset*/ |
| 169 | (char*) MALLOC(8), /*data*/ |
| 170 | 1, 1, /*width, height*/ |
| 171 | 32, /*bitmap_pad*/ |
| 172 | 0 /*bytes_per_line*/ |
| 173 | ); |
| 174 | assert(img); |
| 175 | /* grab the bits/pixel value */ |
| 176 | bitsPerPixel = img->bits_per_pixel; |
| 177 | /* free the XImage */ |
| 178 | _mesa_free( img->data ); |
| 179 | img->data = NULL; |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 180 | XDestroyImage( img ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 181 | return bitsPerPixel; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | |
| 185 | |
| 186 | /* |
| 187 | * Determine if a given X window ID is valid (window exists). |
| 188 | * Do this by calling XGetWindowAttributes() for the window and |
| 189 | * checking if we catch an X error. |
| 190 | * Input: dpy - the display |
| 191 | * win - the window to check for existance |
| 192 | * Return: GL_TRUE - window exists |
| 193 | * GL_FALSE - window doesn't exist |
| 194 | */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 195 | static GLboolean WindowExistsFlag; |
| 196 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 197 | static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr ) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 198 | { |
| 199 | (void) dpy; |
| 200 | if (xerr->error_code == BadWindow) { |
| 201 | WindowExistsFlag = GL_FALSE; |
| 202 | } |
| 203 | return 0; |
| 204 | } |
| 205 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 206 | static GLboolean window_exists( Display *dpy, Window win ) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 207 | { |
| 208 | XWindowAttributes wa; |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 209 | int (*old_handler)( Display*, XErrorEvent* ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 210 | WindowExistsFlag = GL_TRUE; |
| 211 | old_handler = XSetErrorHandler(window_exists_err_handler); |
| 212 | XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ |
| 213 | XSetErrorHandler(old_handler); |
| 214 | return WindowExistsFlag; |
| 215 | } |
| 216 | |
| 217 | static Status |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 218 | get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height ) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 219 | { |
| 220 | Window root; |
| 221 | Status stat; |
| 222 | int xpos, ypos; |
| 223 | unsigned int w, h, bw, depth; |
| 224 | stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); |
| 225 | *width = w; |
| 226 | *height = h; |
| 227 | return stat; |
| 228 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 229 | |
| 230 | |
| 231 | /** |
| 232 | * Return the size of the window (or pixmap) that corresponds to the |
| 233 | * given XMesaBuffer. |
| 234 | * \param width returns width in pixels |
| 235 | * \param height returns height in pixels |
| 236 | */ |
Brian Paul | 0526100 | 2009-10-07 09:40:04 -0600 | [diff] [blame] | 237 | void |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 238 | xmesa_get_window_size(Display *dpy, XMesaBuffer b, |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 239 | GLuint *width, GLuint *height) |
| 240 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 241 | Status stat; |
| 242 | |
Brian Paul | 0bb852f | 2008-08-26 16:35:12 -0600 | [diff] [blame] | 243 | pipe_mutex_lock(_xmesa_lock); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 244 | XSync(b->xm_visual->display, 0); /* added for Chromium */ |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 245 | stat = get_drawable_size(dpy, b->drawable, width, height); |
Brian Paul | 0bb852f | 2008-08-26 16:35:12 -0600 | [diff] [blame] | 246 | pipe_mutex_unlock(_xmesa_lock); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 247 | |
| 248 | if (!stat) { |
| 249 | /* probably querying a window that's recently been destroyed */ |
| 250 | _mesa_warning(NULL, "XGetGeometry failed!\n"); |
| 251 | *width = *height = 1; |
| 252 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 253 | } |
| 254 | |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 255 | #define GET_REDMASK(__v) __v->mesa_visual.redMask |
| 256 | #define GET_GREENMASK(__v) __v->mesa_visual.greenMask |
| 257 | #define GET_BLUEMASK(__v) __v->mesa_visual.blueMask |
| 258 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 259 | |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 260 | /** |
| 261 | * Choose the pixel format for the given visual. |
| 262 | * This will tell the gallium driver how to pack pixel data into |
| 263 | * drawing surfaces. |
| 264 | */ |
| 265 | static GLuint |
| 266 | choose_pixel_format(XMesaVisual v) |
| 267 | { |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 268 | boolean native_byte_order = (host_byte_order() == |
| 269 | ImageByteOrder(v->display)); |
| 270 | |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 271 | if ( GET_REDMASK(v) == 0x0000ff |
| 272 | && GET_GREENMASK(v) == 0x00ff00 |
| 273 | && GET_BLUEMASK(v) == 0xff0000 |
| 274 | && v->BitsPerPixel == 32) { |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 275 | if (native_byte_order) { |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 276 | /* no byteswapping needed */ |
| 277 | return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */; |
| 278 | } |
| 279 | else { |
| 280 | return PIPE_FORMAT_R8G8B8A8_UNORM; |
| 281 | } |
| 282 | } |
| 283 | else if ( GET_REDMASK(v) == 0xff0000 |
| 284 | && GET_GREENMASK(v) == 0x00ff00 |
| 285 | && GET_BLUEMASK(v) == 0x0000ff |
| 286 | && v->BitsPerPixel == 32) { |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 287 | if (native_byte_order) { |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 288 | /* no byteswapping needed */ |
| 289 | return PIPE_FORMAT_A8R8G8B8_UNORM; |
| 290 | } |
| 291 | else { |
| 292 | return PIPE_FORMAT_B8G8R8A8_UNORM; |
| 293 | } |
| 294 | } |
Michel Dänzer | 9f0495a | 2009-08-31 10:22:19 +0200 | [diff] [blame] | 295 | else if ( GET_REDMASK(v) == 0x0000ff00 |
| 296 | && GET_GREENMASK(v) == 0x00ff0000 |
| 297 | && GET_BLUEMASK(v) == 0xff000000 |
| 298 | && v->BitsPerPixel == 32) { |
| 299 | if (native_byte_order) { |
| 300 | /* no byteswapping needed */ |
| 301 | return PIPE_FORMAT_B8G8R8A8_UNORM; |
| 302 | } |
| 303 | else { |
| 304 | return PIPE_FORMAT_A8R8G8B8_UNORM; |
| 305 | } |
| 306 | } |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 307 | else if ( GET_REDMASK(v) == 0xf800 |
| 308 | && GET_GREENMASK(v) == 0x07e0 |
| 309 | && GET_BLUEMASK(v) == 0x001f |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 310 | && native_byte_order |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 311 | && v->BitsPerPixel == 16) { |
| 312 | /* 5-6-5 RGB */ |
| 313 | return PIPE_FORMAT_R5G6B5_UNORM; |
| 314 | } |
| 315 | |
| 316 | assert(0); |
| 317 | return 0; |
| 318 | } |
| 319 | |
| 320 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 321 | |
| 322 | /**********************************************************************/ |
| 323 | /***** Linked list of XMesaBuffers *****/ |
| 324 | /**********************************************************************/ |
| 325 | |
| 326 | XMesaBuffer XMesaBufferList = NULL; |
| 327 | |
| 328 | |
| 329 | /** |
| 330 | * Allocate a new XMesaBuffer object which corresponds to the given drawable. |
| 331 | * Note that XMesaBuffer is derived from GLframebuffer. |
| 332 | * The new XMesaBuffer will not have any size (Width=Height=0). |
| 333 | * |
| 334 | * \param d the corresponding X drawable (window or pixmap) |
| 335 | * \param type either WINDOW, PIXMAP or PBUFFER, describing d |
| 336 | * \param vis the buffer's visual |
| 337 | * \param cmap the window's colormap, if known. |
| 338 | * \return new XMesaBuffer or NULL if any problem |
| 339 | */ |
| 340 | static XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 341 | create_xmesa_buffer(Drawable d, BufferType type, |
| 342 | XMesaVisual vis, Colormap cmap) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 343 | { |
| 344 | XMesaBuffer b; |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 345 | GLframebuffer *fb; |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 346 | enum pipe_format colorFormat, depthFormat, stencilFormat; |
Brian | c664302 | 2007-12-19 13:45:00 -0700 | [diff] [blame] | 347 | uint width, height; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 348 | |
| 349 | ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); |
| 350 | |
| 351 | b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); |
| 352 | if (!b) |
| 353 | return NULL; |
| 354 | |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 355 | b->drawable = d; |
| 356 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 357 | b->xm_visual = vis; |
| 358 | b->type = type; |
| 359 | b->cmap = cmap; |
| 360 | |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 361 | /* determine PIPE_FORMATs for buffers */ |
| 362 | colorFormat = choose_pixel_format(vis); |
| 363 | |
| 364 | if (vis->mesa_visual.depthBits == 0) |
| 365 | depthFormat = PIPE_FORMAT_NONE; |
Brian Paul | 284ab5a | 2008-09-10 18:22:00 -0600 | [diff] [blame] | 366 | #ifdef GALLIUM_CELL /* XXX temporary for Cell! */ |
| 367 | else |
| 368 | depthFormat = PIPE_FORMAT_S8Z24_UNORM; |
| 369 | #else |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 370 | else if (vis->mesa_visual.depthBits <= 16) |
Keith Whitwell | 536092f | 2008-09-11 18:35:19 +0100 | [diff] [blame] | 371 | depthFormat = PIPE_FORMAT_Z16_UNORM; |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 372 | else if (vis->mesa_visual.depthBits <= 24) |
| 373 | depthFormat = PIPE_FORMAT_S8Z24_UNORM; |
| 374 | else |
| 375 | depthFormat = PIPE_FORMAT_Z32_UNORM; |
Brian Paul | 284ab5a | 2008-09-10 18:22:00 -0600 | [diff] [blame] | 376 | #endif |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 377 | |
| 378 | if (vis->mesa_visual.stencilBits == 8) { |
| 379 | if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) |
| 380 | stencilFormat = depthFormat; |
| 381 | else |
| 382 | stencilFormat = PIPE_FORMAT_S8_UNORM; |
| 383 | } |
| 384 | else { |
Brian Paul | c1c4ff2 | 2008-08-07 15:11:54 -0600 | [diff] [blame] | 385 | /* no stencil */ |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 386 | stencilFormat = PIPE_FORMAT_NONE; |
Brian Paul | c1c4ff2 | 2008-08-07 15:11:54 -0600 | [diff] [blame] | 387 | if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) { |
| 388 | /* use 24-bit Z, undefined stencil channel */ |
| 389 | depthFormat = PIPE_FORMAT_X8Z24_UNORM; |
| 390 | } |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 391 | } |
| 392 | |
| 393 | |
Brian | c664302 | 2007-12-19 13:45:00 -0700 | [diff] [blame] | 394 | get_drawable_size(vis->display, d, &width, &height); |
| 395 | |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 396 | /* |
| 397 | * Create framebuffer, but we'll plug in our own renderbuffers below. |
| 398 | */ |
Brian | c664302 | 2007-12-19 13:45:00 -0700 | [diff] [blame] | 399 | b->stfb = st_create_framebuffer(&vis->mesa_visual, |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 400 | colorFormat, depthFormat, stencilFormat, |
Brian | c664302 | 2007-12-19 13:45:00 -0700 | [diff] [blame] | 401 | width, height, |
Brian | 20eae59 | 2007-12-12 14:55:57 -0700 | [diff] [blame] | 402 | (void *) b); |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 403 | fb = &b->stfb->Base; |
| 404 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 405 | /* |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 406 | * Create scratch XImage for xmesa_display_surface() |
Brian | b761177 | 2007-10-31 19:00:23 -0600 | [diff] [blame] | 407 | */ |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 408 | b->tempImage = XCreateImage(vis->display, |
| 409 | vis->visinfo->visual, |
| 410 | vis->visinfo->depth, |
| 411 | ZPixmap, 0, /* format, offset */ |
| 412 | NULL, /* data */ |
| 413 | 0, 0, /* size */ |
| 414 | 32, /* bitmap_pad */ |
| 415 | 0); /* bytes_per_line */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 416 | |
| 417 | /* GLX_EXT_texture_from_pixmap */ |
| 418 | b->TextureTarget = 0; |
| 419 | b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; |
| 420 | b->TextureMipmap = 0; |
| 421 | |
| 422 | /* insert buffer into linked list */ |
| 423 | b->Next = XMesaBufferList; |
| 424 | XMesaBufferList = b; |
| 425 | |
| 426 | return b; |
| 427 | } |
| 428 | |
| 429 | |
| 430 | /** |
| 431 | * Find an XMesaBuffer by matching X display and colormap but NOT matching |
| 432 | * the notThis buffer. |
| 433 | */ |
| 434 | XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 435 | xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 436 | { |
| 437 | XMesaBuffer b; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 438 | for (b = XMesaBufferList; b; b = b->Next) { |
| 439 | if (b->xm_visual->display == dpy && |
| 440 | b->cmap == cmap && |
| 441 | b != notThis) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 442 | return b; |
| 443 | } |
| 444 | } |
| 445 | return NULL; |
| 446 | } |
| 447 | |
| 448 | |
| 449 | /** |
| 450 | * Remove buffer from linked list, delete if no longer referenced. |
| 451 | */ |
| 452 | static void |
| 453 | xmesa_free_buffer(XMesaBuffer buffer) |
| 454 | { |
| 455 | XMesaBuffer prev = NULL, b; |
| 456 | |
| 457 | for (b = XMesaBufferList; b; b = b->Next) { |
| 458 | if (b == buffer) { |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 459 | struct gl_framebuffer *fb = &buffer->stfb->Base; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 460 | |
| 461 | /* unlink buffer from list */ |
| 462 | if (prev) |
| 463 | prev->Next = buffer->Next; |
| 464 | else |
| 465 | XMesaBufferList = buffer->Next; |
| 466 | |
| 467 | /* mark as delete pending */ |
| 468 | fb->DeletePending = GL_TRUE; |
| 469 | |
| 470 | /* Since the X window for the XMesaBuffer is going away, we don't |
| 471 | * want to dereference this pointer in the future. |
| 472 | */ |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 473 | b->drawable = 0; |
| 474 | |
| 475 | buffer->tempImage->data = NULL; |
| 476 | XDestroyImage(buffer->tempImage); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 477 | |
| 478 | /* Unreference. If count = zero we'll really delete the buffer */ |
Michel Dänzer | 317687c | 2009-03-09 13:27:54 +0100 | [diff] [blame] | 479 | _mesa_reference_framebuffer(&fb, NULL); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 480 | |
Brian | f44e2f1 | 2007-12-26 06:56:58 -0700 | [diff] [blame] | 481 | XFreeGC(b->xm_visual->display, b->gc); |
| 482 | |
| 483 | free(buffer); |
| 484 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 485 | return; |
| 486 | } |
| 487 | /* continue search */ |
| 488 | prev = b; |
| 489 | } |
| 490 | /* buffer not found in XMesaBufferList */ |
| 491 | _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); |
| 492 | } |
| 493 | |
| 494 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 495 | |
| 496 | /**********************************************************************/ |
| 497 | /***** Misc Private Functions *****/ |
| 498 | /**********************************************************************/ |
| 499 | |
| 500 | |
| 501 | /** |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 502 | * When a context is bound for the first time, we can finally finish |
| 503 | * initializing the context's visual and buffer information. |
| 504 | * \param v the XMesaVisual to initialize |
| 505 | * \param b the XMesaBuffer to initialize (may be NULL) |
| 506 | * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode |
| 507 | * \param window the window/pixmap we're rendering into |
| 508 | * \param cmap the colormap associated with the window/pixmap |
| 509 | * \return GL_TRUE=success, GL_FALSE=failure |
| 510 | */ |
| 511 | static GLboolean |
| 512 | initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 513 | GLboolean rgb_flag, Drawable window, |
| 514 | Colormap cmap) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 515 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 516 | ASSERT(!b || b->xm_visual == v); |
| 517 | |
| 518 | /* Save true bits/pixel */ |
| 519 | v->BitsPerPixel = bits_per_pixel(v); |
| 520 | assert(v->BitsPerPixel > 0); |
| 521 | |
| 522 | if (rgb_flag == GL_FALSE) { |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 523 | /* COLOR-INDEXED WINDOW: not supported*/ |
| 524 | return GL_FALSE; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 525 | } |
| 526 | else { |
| 527 | /* RGB WINDOW: |
| 528 | * We support RGB rendering into almost any kind of visual. |
| 529 | */ |
| 530 | const int xclass = v->mesa_visual.visualType; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 531 | if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) { |
| 532 | _mesa_warning(NULL, |
| 533 | "XMesa: RGB mode rendering not supported in given visual.\n"); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 534 | return GL_FALSE; |
| 535 | } |
| 536 | v->mesa_visual.indexBits = 0; |
Brian | 5935b16 | 2008-03-27 21:11:45 -0600 | [diff] [blame] | 537 | |
| 538 | if (v->BitsPerPixel == 32) { |
| 539 | /* We use XImages for all front/back buffers. If an X Window or |
| 540 | * X Pixmap is 32bpp, there's no guarantee that the alpha channel |
| 541 | * will be preserved. For XImages we're in luck. |
| 542 | */ |
| 543 | v->mesa_visual.alphaBits = 8; |
| 544 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 545 | } |
| 546 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 547 | /* |
| 548 | * If MESA_INFO env var is set print out some debugging info |
| 549 | * which can help Brian figure out what's going on when a user |
| 550 | * reports bugs. |
| 551 | */ |
| 552 | if (_mesa_getenv("MESA_INFO")) { |
| 553 | _mesa_printf("X/Mesa visual = %p\n", (void *) v); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 554 | _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level); |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 555 | _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 556 | _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); |
| 557 | } |
| 558 | |
| 559 | if (b && window) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 560 | /* these should have been set in create_xmesa_buffer */ |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 561 | ASSERT(b->drawable == window); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 562 | |
| 563 | /* Setup for single/double buffering */ |
| 564 | if (v->mesa_visual.doubleBufferMode) { |
| 565 | /* Double buffered */ |
Ian Romanick | b09de96 | 2008-03-25 18:07:56 -0700 | [diff] [blame] | 566 | b->shm = xmesa_check_for_xshm( v->display ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 567 | } |
| 568 | |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 569 | /* X11 graphics context */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 570 | b->gc = XCreateGC( v->display, window, 0, NULL ); |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 571 | XSetFunction( v->display, b->gc, GXcopy ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 572 | } |
| 573 | |
| 574 | return GL_TRUE; |
| 575 | } |
| 576 | |
| 577 | |
| 578 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 579 | #define NUM_VISUAL_TYPES 6 |
| 580 | |
| 581 | /** |
| 582 | * Convert an X visual type to a GLX visual type. |
| 583 | * |
| 584 | * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) |
| 585 | * to be converted. |
| 586 | * \return If \c visualType is a valid X visual type, a GLX visual type will |
| 587 | * be returned. Otherwise \c GLX_NONE will be returned. |
| 588 | * |
| 589 | * \note |
| 590 | * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the |
| 591 | * DRI CVS tree. |
| 592 | */ |
| 593 | static GLint |
| 594 | xmesa_convert_from_x_visual_type( int visualType ) |
| 595 | { |
| 596 | static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { |
| 597 | GLX_STATIC_GRAY, GLX_GRAY_SCALE, |
| 598 | GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, |
| 599 | GLX_TRUE_COLOR, GLX_DIRECT_COLOR |
| 600 | }; |
| 601 | |
| 602 | return ( (unsigned) visualType < NUM_VISUAL_TYPES ) |
| 603 | ? glx_visual_types[ visualType ] : GLX_NONE; |
| 604 | } |
| 605 | |
| 606 | |
| 607 | /**********************************************************************/ |
| 608 | /***** Public Functions *****/ |
| 609 | /**********************************************************************/ |
| 610 | |
| 611 | |
| 612 | /* |
| 613 | * Create a new X/Mesa visual. |
| 614 | * Input: display - X11 display |
| 615 | * visinfo - an XVisualInfo pointer |
| 616 | * rgb_flag - GL_TRUE = RGB mode, |
| 617 | * GL_FALSE = color index mode |
| 618 | * alpha_flag - alpha buffer requested? |
| 619 | * db_flag - GL_TRUE = double-buffered, |
| 620 | * GL_FALSE = single buffered |
| 621 | * stereo_flag - stereo visual? |
| 622 | * ximage_flag - GL_TRUE = use an XImage for back buffer, |
| 623 | * GL_FALSE = use an off-screen pixmap for back buffer |
| 624 | * depth_size - requested bits/depth values, or zero |
| 625 | * stencil_size - requested bits/stencil values, or zero |
| 626 | * accum_red_size - requested bits/red accum values, or zero |
| 627 | * accum_green_size - requested bits/green accum values, or zero |
| 628 | * accum_blue_size - requested bits/blue accum values, or zero |
| 629 | * accum_alpha_size - requested bits/alpha accum values, or zero |
| 630 | * num_samples - number of samples/pixel if multisampling, or zero |
| 631 | * level - visual level, usually 0 |
| 632 | * visualCaveat - ala the GLX extension, usually GLX_NONE |
| 633 | * Return; a new XMesaVisual or 0 if error. |
| 634 | */ |
| 635 | PUBLIC |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 636 | XMesaVisual XMesaCreateVisual( Display *display, |
| 637 | XVisualInfo * visinfo, |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 638 | GLboolean rgb_flag, |
| 639 | GLboolean alpha_flag, |
| 640 | GLboolean db_flag, |
| 641 | GLboolean stereo_flag, |
| 642 | GLboolean ximage_flag, |
| 643 | GLint depth_size, |
| 644 | GLint stencil_size, |
| 645 | GLint accum_red_size, |
| 646 | GLint accum_green_size, |
| 647 | GLint accum_blue_size, |
| 648 | GLint accum_alpha_size, |
| 649 | GLint num_samples, |
| 650 | GLint level, |
| 651 | GLint visualCaveat ) |
| 652 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 653 | XMesaVisual v; |
| 654 | GLint red_bits, green_bits, blue_bits, alpha_bits; |
| 655 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 656 | /* For debugging only */ |
| 657 | if (_mesa_getenv("MESA_XSYNC")) { |
| 658 | /* This makes debugging X easier. |
| 659 | * In your debugger, set a breakpoint on _XError to stop when an |
| 660 | * X protocol error is generated. |
| 661 | */ |
| 662 | XSynchronize( display, 1 ); |
| 663 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 664 | |
| 665 | v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); |
| 666 | if (!v) { |
| 667 | return NULL; |
| 668 | } |
| 669 | |
| 670 | v->display = display; |
| 671 | |
| 672 | /* Save a copy of the XVisualInfo struct because the user may X_mesa_free() |
| 673 | * the struct but we may need some of the information contained in it |
| 674 | * at a later time. |
| 675 | */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 676 | v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); |
Brian Paul | 40636fe | 2009-09-03 17:16:19 -0600 | [diff] [blame] | 677 | if (!v->visinfo) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 678 | _mesa_free(v); |
| 679 | return NULL; |
| 680 | } |
| 681 | MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 682 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 683 | v->ximage_flag = ximage_flag; |
| 684 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 685 | v->mesa_visual.redMask = visinfo->red_mask; |
| 686 | v->mesa_visual.greenMask = visinfo->green_mask; |
| 687 | v->mesa_visual.blueMask = visinfo->blue_mask; |
| 688 | v->mesa_visual.visualID = visinfo->visualid; |
| 689 | v->mesa_visual.screen = visinfo->screen; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 690 | |
Keith Whitwell | 18ad0e3 | 2009-01-08 15:00:27 +0000 | [diff] [blame] | 691 | #if !(defined(__cplusplus) || defined(c_plusplus)) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 692 | v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); |
| 693 | #else |
| 694 | v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); |
| 695 | #endif |
| 696 | |
| 697 | v->mesa_visual.visualRating = visualCaveat; |
| 698 | |
| 699 | if (alpha_flag) |
| 700 | v->mesa_visual.alphaBits = 8; |
| 701 | |
| 702 | (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 ); |
| 703 | |
| 704 | { |
| 705 | const int xclass = v->mesa_visual.visualType; |
| 706 | if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { |
| 707 | red_bits = _mesa_bitcount(GET_REDMASK(v)); |
| 708 | green_bits = _mesa_bitcount(GET_GREENMASK(v)); |
| 709 | blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); |
| 710 | } |
| 711 | else { |
| 712 | /* this is an approximation */ |
| 713 | int depth; |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 714 | depth = v->visinfo->depth; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 715 | red_bits = depth / 3; |
| 716 | depth -= red_bits; |
| 717 | green_bits = depth / 2; |
| 718 | depth -= green_bits; |
| 719 | blue_bits = depth; |
| 720 | alpha_bits = 0; |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 721 | assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 722 | } |
| 723 | alpha_bits = v->mesa_visual.alphaBits; |
| 724 | } |
| 725 | |
| 726 | _mesa_initialize_visual( &v->mesa_visual, |
| 727 | rgb_flag, db_flag, stereo_flag, |
| 728 | red_bits, green_bits, |
| 729 | blue_bits, alpha_bits, |
| 730 | v->mesa_visual.indexBits, |
| 731 | depth_size, |
| 732 | stencil_size, |
| 733 | accum_red_size, accum_green_size, |
| 734 | accum_blue_size, accum_alpha_size, |
| 735 | 0 ); |
| 736 | |
| 737 | /* XXX minor hack */ |
| 738 | v->mesa_visual.level = level; |
| 739 | return v; |
| 740 | } |
| 741 | |
| 742 | |
| 743 | PUBLIC |
| 744 | void XMesaDestroyVisual( XMesaVisual v ) |
| 745 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 746 | _mesa_free(v->visinfo); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 747 | _mesa_free(v); |
| 748 | } |
| 749 | |
| 750 | |
| 751 | |
| 752 | /** |
| 753 | * Create a new XMesaContext. |
| 754 | * \param v the XMesaVisual |
| 755 | * \param share_list another XMesaContext with which to share display |
| 756 | * lists or NULL if no sharing is wanted. |
| 757 | * \return an XMesaContext or NULL if error. |
| 758 | */ |
| 759 | PUBLIC |
| 760 | XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) |
| 761 | { |
| 762 | static GLboolean firstTime = GL_TRUE; |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 763 | struct pipe_context *_pipe = NULL; |
Brian Paul | 7ec8652 | 2009-09-03 15:44:22 -0600 | [diff] [blame] | 764 | struct pipe_context *pipe = NULL; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 765 | XMesaContext c; |
| 766 | GLcontext *mesaCtx; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 767 | uint pf; |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 768 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 769 | if (firstTime) { |
Brian Paul | 0bb852f | 2008-08-26 16:35:12 -0600 | [diff] [blame] | 770 | pipe_mutex_init(_xmesa_lock); |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 771 | _screen = driver.create_pipe_screen(); |
| 772 | screen = trace_screen_create( _screen ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 773 | firstTime = GL_FALSE; |
| 774 | } |
| 775 | |
| 776 | /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ |
| 777 | c = (XMesaContext) CALLOC_STRUCT(xmesa_context); |
| 778 | if (!c) |
| 779 | return NULL; |
| 780 | |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 781 | pf = choose_pixel_format(v); |
Brian | 0d1669f | 2007-12-07 08:24:56 -0700 | [diff] [blame] | 782 | assert(pf); |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 783 | |
Ian Romanick | b09de96 | 2008-03-25 18:07:56 -0700 | [diff] [blame] | 784 | c->xm_visual = v; |
| 785 | c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ |
Thomas Hellstrom | d405ba3 | 2009-03-18 11:52:24 +0100 | [diff] [blame] | 786 | c->xm_read_buffer = NULL; |
| 787 | |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 788 | if (screen == NULL) |
| 789 | goto fail; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 790 | |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 791 | _pipe = driver.create_pipe_context(_screen, (void *) c); |
| 792 | if (_pipe == NULL) |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 793 | goto fail; |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 794 | pipe = trace_context_create(screen, _pipe); |
| 795 | pipe->priv = c; |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 796 | |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 797 | c->st = st_create_context(pipe, |
| 798 | &v->mesa_visual, |
Brian | 91564ee | 2007-11-05 16:15:43 -0700 | [diff] [blame] | 799 | share_list ? share_list->st : NULL); |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 800 | if (c->st == NULL) |
| 801 | goto fail; |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 802 | |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 803 | mesaCtx = c->st->ctx; |
| 804 | c->st->ctx->DriverCtx = c; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 805 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 806 | return c; |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 807 | |
Brian Paul | 40636fe | 2009-09-03 17:16:19 -0600 | [diff] [blame] | 808 | fail: |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 809 | if (c->st) |
| 810 | st_destroy_context(c->st); |
José Fonseca | 969ff9e | 2008-08-14 10:47:39 +0100 | [diff] [blame] | 811 | else if (pipe) |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 812 | pipe->destroy(pipe); |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 813 | |
Brian Paul | 40636fe | 2009-09-03 17:16:19 -0600 | [diff] [blame] | 814 | _mesa_free(c); |
Keith Whitwell | 2258f6b | 2008-05-12 14:09:50 +0100 | [diff] [blame] | 815 | return NULL; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 816 | } |
| 817 | |
| 818 | |
| 819 | |
| 820 | PUBLIC |
| 821 | void XMesaDestroyContext( XMesaContext c ) |
| 822 | { |
Brian | 91564ee | 2007-11-05 16:15:43 -0700 | [diff] [blame] | 823 | st_destroy_context(c->st); |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 824 | |
José Fonseca | f9e14e0 | 2008-08-19 00:18:19 +0100 | [diff] [blame] | 825 | /* FIXME: We should destroy the screen here, but if we do so, surfaces may |
| 826 | * outlive it, causing segfaults |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 827 | struct pipe_screen *screen = c->st->pipe->screen; |
José Fonseca | 969ff9e | 2008-08-14 10:47:39 +0100 | [diff] [blame] | 828 | screen->destroy(screen); |
José Fonseca | f9e14e0 | 2008-08-19 00:18:19 +0100 | [diff] [blame] | 829 | */ |
Keith Whitwell | 002dfb1 | 2009-01-08 14:10:56 +0000 | [diff] [blame] | 830 | |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 831 | _mesa_free(c); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 832 | } |
| 833 | |
| 834 | |
| 835 | |
| 836 | /** |
| 837 | * Private function for creating an XMesaBuffer which corresponds to an |
| 838 | * X window or pixmap. |
| 839 | * \param v the window's XMesaVisual |
| 840 | * \param w the window we're wrapping |
| 841 | * \return new XMesaBuffer or NULL if error |
| 842 | */ |
| 843 | PUBLIC XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 844 | XMesaCreateWindowBuffer(XMesaVisual v, Window w) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 845 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 846 | XWindowAttributes attr; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 847 | XMesaBuffer b; |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 848 | Colormap cmap; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 849 | int depth; |
| 850 | |
| 851 | assert(v); |
| 852 | assert(w); |
| 853 | |
| 854 | /* Check that window depth matches visual depth */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 855 | XGetWindowAttributes( v->display, w, &attr ); |
| 856 | depth = attr.depth; |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 857 | if (v->visinfo->depth != depth) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 858 | _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", |
Keith Whitwell | 2b96012 | 2009-01-08 15:33:32 +0000 | [diff] [blame] | 859 | v->visinfo->depth, depth); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 860 | return NULL; |
| 861 | } |
| 862 | |
| 863 | /* Find colormap */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 864 | if (attr.colormap) { |
| 865 | cmap = attr.colormap; |
| 866 | } |
| 867 | else { |
| 868 | _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); |
| 869 | /* this is weird, a window w/out a colormap!? */ |
| 870 | /* OK, let's just allocate a new one and hope for the best */ |
| 871 | cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); |
| 872 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 873 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 874 | b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 875 | if (!b) |
| 876 | return NULL; |
| 877 | |
| 878 | if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode, |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 879 | (Drawable) w, cmap )) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 880 | xmesa_free_buffer(b); |
| 881 | return NULL; |
| 882 | } |
| 883 | |
| 884 | return b; |
| 885 | } |
| 886 | |
| 887 | |
| 888 | |
| 889 | /** |
| 890 | * Create a new XMesaBuffer from an X pixmap. |
| 891 | * |
| 892 | * \param v the XMesaVisual |
| 893 | * \param p the pixmap |
| 894 | * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or |
| 895 | * \c GLX_DIRECT_COLOR visual for the pixmap |
| 896 | * \returns new XMesaBuffer or NULL if error |
| 897 | */ |
| 898 | PUBLIC XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 899 | XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 900 | { |
| 901 | XMesaBuffer b; |
| 902 | |
| 903 | assert(v); |
| 904 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 905 | b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 906 | if (!b) |
| 907 | return NULL; |
| 908 | |
| 909 | if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 910 | (Drawable) p, cmap)) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 911 | xmesa_free_buffer(b); |
| 912 | return NULL; |
| 913 | } |
| 914 | |
| 915 | return b; |
| 916 | } |
| 917 | |
| 918 | |
| 919 | /** |
| 920 | * For GLX_EXT_texture_from_pixmap |
| 921 | */ |
| 922 | XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 923 | XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, |
| 924 | Colormap cmap, |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 925 | int format, int target, int mipmap) |
| 926 | { |
| 927 | GET_CURRENT_CONTEXT(ctx); |
| 928 | XMesaBuffer b; |
| 929 | GLuint width, height; |
| 930 | |
| 931 | assert(v); |
| 932 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 933 | b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 934 | if (!b) |
| 935 | return NULL; |
| 936 | |
| 937 | /* get pixmap size, update framebuffer/renderbuffer dims */ |
| 938 | xmesa_get_window_size(v->display, b, &width, &height); |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 939 | _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 940 | |
| 941 | if (target == 0) { |
| 942 | /* examine dims */ |
| 943 | if (ctx->Extensions.ARB_texture_non_power_of_two) { |
| 944 | target = GLX_TEXTURE_2D_EXT; |
| 945 | } |
| 946 | else if ( _mesa_bitcount(width) == 1 |
| 947 | && _mesa_bitcount(height) == 1) { |
| 948 | /* power of two size */ |
| 949 | if (height == 1) { |
| 950 | target = GLX_TEXTURE_1D_EXT; |
| 951 | } |
| 952 | else { |
| 953 | target = GLX_TEXTURE_2D_EXT; |
| 954 | } |
| 955 | } |
| 956 | else if (ctx->Extensions.NV_texture_rectangle) { |
| 957 | target = GLX_TEXTURE_RECTANGLE_EXT; |
| 958 | } |
| 959 | else { |
| 960 | /* non power of two textures not supported */ |
| 961 | XMesaDestroyBuffer(b); |
| 962 | return 0; |
| 963 | } |
| 964 | } |
| 965 | |
| 966 | b->TextureTarget = target; |
| 967 | b->TextureFormat = format; |
| 968 | b->TextureMipmap = mipmap; |
| 969 | |
| 970 | if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 971 | (Drawable) p, cmap)) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 972 | xmesa_free_buffer(b); |
| 973 | return NULL; |
| 974 | } |
| 975 | |
| 976 | return b; |
| 977 | } |
| 978 | |
| 979 | |
| 980 | |
| 981 | XMesaBuffer |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 982 | XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 983 | unsigned int width, unsigned int height) |
| 984 | { |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 985 | Window root; |
| 986 | Drawable drawable; /* X Pixmap Drawable */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 987 | XMesaBuffer b; |
| 988 | |
| 989 | /* allocate pixmap for front buffer */ |
| 990 | root = RootWindow( v->display, v->visinfo->screen ); |
| 991 | drawable = XCreatePixmap(v->display, root, width, height, |
| 992 | v->visinfo->depth); |
| 993 | if (!drawable) |
| 994 | return NULL; |
| 995 | |
| 996 | b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); |
| 997 | if (!b) |
| 998 | return NULL; |
| 999 | |
| 1000 | if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, |
| 1001 | drawable, cmap)) { |
| 1002 | xmesa_free_buffer(b); |
| 1003 | return NULL; |
| 1004 | } |
| 1005 | |
| 1006 | return b; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1007 | } |
| 1008 | |
| 1009 | |
| 1010 | |
| 1011 | /* |
| 1012 | * Deallocate an XMesaBuffer structure and all related info. |
| 1013 | */ |
| 1014 | PUBLIC void |
| 1015 | XMesaDestroyBuffer(XMesaBuffer b) |
| 1016 | { |
| 1017 | xmesa_free_buffer(b); |
| 1018 | } |
| 1019 | |
| 1020 | |
| 1021 | /** |
| 1022 | * Query the current window size and update the corresponding GLframebuffer |
| 1023 | * and all attached renderbuffers. |
| 1024 | * Called when: |
| 1025 | * 1. the first time a buffer is bound to a context. |
Keith Whitwell | ee28763 | 2009-01-08 16:05:45 +0000 | [diff] [blame] | 1026 | * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1027 | * Note: it's possible (and legal) for xmctx to be NULL. That can happen |
| 1028 | * when resizing a buffer when no rendering context is bound. |
| 1029 | */ |
| 1030 | void |
| 1031 | xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) |
| 1032 | { |
| 1033 | GLuint width, height; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1034 | xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 1035 | st_resize_framebuffer(drawBuffer->stfb, width, height); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1036 | } |
| 1037 | |
| 1038 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1039 | |
| 1040 | |
| 1041 | /* |
| 1042 | * Bind buffer b to context c and make c the current rendering context. |
| 1043 | */ |
| 1044 | PUBLIC |
| 1045 | GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, |
| 1046 | XMesaBuffer readBuffer ) |
| 1047 | { |
Thomas Hellstrom | d405ba3 | 2009-03-18 11:52:24 +0100 | [diff] [blame] | 1048 | XMesaContext old_ctx = XMesaGetCurrentContext(); |
| 1049 | |
| 1050 | if (old_ctx && old_ctx != c) { |
| 1051 | XMesaFlush(old_ctx); |
| 1052 | old_ctx->xm_buffer = NULL; |
| 1053 | old_ctx->xm_read_buffer = NULL; |
| 1054 | } |
| 1055 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1056 | if (c) { |
| 1057 | if (!drawBuffer || !readBuffer) |
| 1058 | return GL_FALSE; /* must specify buffers! */ |
| 1059 | |
Thomas Hellstrom | d405ba3 | 2009-03-18 11:52:24 +0100 | [diff] [blame] | 1060 | if (c == old_ctx && |
| 1061 | c->xm_buffer == drawBuffer && |
| 1062 | c->xm_read_buffer == readBuffer) |
| 1063 | return GL_TRUE; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1064 | |
| 1065 | c->xm_buffer = drawBuffer; |
Thomas Hellstrom | d405ba3 | 2009-03-18 11:52:24 +0100 | [diff] [blame] | 1066 | c->xm_read_buffer = readBuffer; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1067 | |
Brian | dbf6ece | 2007-12-19 08:50:35 -0700 | [diff] [blame] | 1068 | st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb); |
| 1069 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1070 | xmesa_check_and_update_buffer_size(c, drawBuffer); |
| 1071 | if (readBuffer != drawBuffer) |
| 1072 | xmesa_check_and_update_buffer_size(c, readBuffer); |
| 1073 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1074 | /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ |
| 1075 | drawBuffer->wasCurrent = GL_TRUE; |
| 1076 | } |
| 1077 | else { |
| 1078 | /* Detach */ |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 1079 | st_make_current( NULL, NULL, NULL ); |
Thomas Hellstrom | d405ba3 | 2009-03-18 11:52:24 +0100 | [diff] [blame] | 1080 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1081 | } |
| 1082 | return GL_TRUE; |
| 1083 | } |
| 1084 | |
| 1085 | |
| 1086 | /* |
| 1087 | * Unbind the context c from its buffer. |
| 1088 | */ |
| 1089 | GLboolean XMesaUnbindContext( XMesaContext c ) |
| 1090 | { |
| 1091 | /* A no-op for XFree86 integration purposes */ |
| 1092 | return GL_TRUE; |
| 1093 | } |
| 1094 | |
| 1095 | |
| 1096 | XMesaContext XMesaGetCurrentContext( void ) |
| 1097 | { |
| 1098 | GET_CURRENT_CONTEXT(ctx); |
| 1099 | if (ctx) { |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1100 | XMesaContext xmesa = xmesa_context(ctx); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1101 | return xmesa; |
| 1102 | } |
| 1103 | else { |
| 1104 | return 0; |
| 1105 | } |
| 1106 | } |
| 1107 | |
| 1108 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1109 | |
Brian Paul | b57b6c2 | 2009-05-01 12:28:57 -0600 | [diff] [blame] | 1110 | /** |
| 1111 | * Swap front and back color buffers and have winsys display front buffer. |
| 1112 | * If there's no front color buffer no swap actually occurs. |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1113 | */ |
| 1114 | PUBLIC |
| 1115 | void XMesaSwapBuffers( XMesaBuffer b ) |
| 1116 | { |
Brian Paul | b57b6c2 | 2009-05-01 12:28:57 -0600 | [diff] [blame] | 1117 | struct pipe_surface *frontLeftSurf; |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1118 | |
Brian Paul | b57b6c2 | 2009-05-01 12:28:57 -0600 | [diff] [blame] | 1119 | st_swapbuffers(b->stfb, &frontLeftSurf, NULL); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1120 | |
Brian Paul | b57b6c2 | 2009-05-01 12:28:57 -0600 | [diff] [blame] | 1121 | if (frontLeftSurf) { |
José Fonseca | 67171ed | 2009-12-28 16:25:48 +0000 | [diff] [blame] | 1122 | if (_screen != screen) { |
| 1123 | struct trace_surface *tr_surf = trace_surface( frontLeftSurf ); |
| 1124 | struct pipe_surface *surf = tr_surf->surface; |
| 1125 | frontLeftSurf = surf; |
| 1126 | } |
| 1127 | |
Brian Paul | b57b6c2 | 2009-05-01 12:28:57 -0600 | [diff] [blame] | 1128 | driver.display_surface(b, frontLeftSurf); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1129 | } |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1130 | |
| 1131 | xmesa_check_and_update_buffer_size(NULL, b); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1132 | } |
| 1133 | |
| 1134 | |
| 1135 | |
| 1136 | /* |
| 1137 | * Copy sub-region of back buffer to front buffer |
| 1138 | */ |
| 1139 | void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) |
| 1140 | { |
Alan Hourihane | b0d0e53 | 2009-01-23 16:04:57 +0000 | [diff] [blame] | 1141 | struct pipe_surface *surf_front; |
| 1142 | struct pipe_surface *surf_back; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1143 | struct pipe_context *pipe = NULL; /* XXX fix */ |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1144 | |
Alan Hourihane | b0d0e53 | 2009-01-23 16:04:57 +0000 | [diff] [blame] | 1145 | st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); |
| 1146 | st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); |
| 1147 | |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1148 | if (!surf_front || !surf_back) |
| 1149 | return; |
Brian | e39f1b4 | 2007-11-05 15:59:55 -0700 | [diff] [blame] | 1150 | |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1151 | pipe->surface_copy(pipe, |
| 1152 | surf_front, x, y, /* dest */ |
| 1153 | surf_back, x, y, /* src */ |
| 1154 | width, height); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1155 | } |
| 1156 | |
| 1157 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1158 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1159 | void XMesaFlush( XMesaContext c ) |
| 1160 | { |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1161 | if (c && c->xm_visual->display) { |
Brian Paul | 6f33b77 | 2008-08-27 11:29:26 -0600 | [diff] [blame] | 1162 | st_finish(c->st); |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1163 | XSync( c->xm_visual->display, False ); |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1164 | } |
| 1165 | } |
| 1166 | |
| 1167 | |
| 1168 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1169 | |
| 1170 | |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 1171 | XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1172 | { |
| 1173 | XMesaBuffer b; |
Brian Paul | 40636fe | 2009-09-03 17:16:19 -0600 | [diff] [blame] | 1174 | for (b = XMesaBufferList; b; b = b->Next) { |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1175 | if (b->drawable == d && b->xm_visual->display == dpy) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1176 | return b; |
| 1177 | } |
| 1178 | } |
| 1179 | return NULL; |
| 1180 | } |
| 1181 | |
| 1182 | |
| 1183 | /** |
| 1184 | * Free/destroy all XMesaBuffers associated with given display. |
| 1185 | */ |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 1186 | void xmesa_destroy_buffers_on_display(Display *dpy) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1187 | { |
| 1188 | XMesaBuffer b, next; |
| 1189 | for (b = XMesaBufferList; b; b = next) { |
| 1190 | next = b->Next; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1191 | if (b->xm_visual->display == dpy) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1192 | xmesa_free_buffer(b); |
| 1193 | } |
| 1194 | } |
| 1195 | } |
| 1196 | |
| 1197 | |
| 1198 | /* |
| 1199 | * Look for XMesaBuffers whose X window has been destroyed. |
| 1200 | * Deallocate any such XMesaBuffers. |
| 1201 | */ |
| 1202 | void XMesaGarbageCollect( void ) |
| 1203 | { |
| 1204 | XMesaBuffer b, next; |
| 1205 | for (b=XMesaBufferList; b; b=next) { |
| 1206 | next = b->Next; |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1207 | if (b->xm_visual && |
| 1208 | b->xm_visual->display && |
| 1209 | b->drawable && |
| 1210 | b->type == WINDOW) { |
Brian | 749d723 | 2007-12-07 07:57:54 -0700 | [diff] [blame] | 1211 | XSync(b->xm_visual->display, False); |
| 1212 | if (!window_exists( b->xm_visual->display, b->drawable )) { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1213 | /* found a dead window, free the ancillary info */ |
| 1214 | XMesaDestroyBuffer( b ); |
| 1215 | } |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1216 | } |
| 1217 | } |
| 1218 | } |
| 1219 | |
| 1220 | |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1221 | |
| 1222 | |
| 1223 | PUBLIC void |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 1224 | XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1225 | const int *attrib_list) |
| 1226 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1227 | } |
| 1228 | |
| 1229 | |
| 1230 | |
| 1231 | PUBLIC void |
Keith Whitwell | 153b4d5 | 2009-01-08 15:23:51 +0000 | [diff] [blame] | 1232 | XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1233 | { |
Brian | ef25c49 | 2007-10-31 14:19:09 -0600 | [diff] [blame] | 1234 | } |
| 1235 | |