blob: 67a9a1ec8c84329944c7d8db524937fee7146417 [file] [log] [blame]
Brianef25c492007-10-31 14:19:09 -06001/*
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
Brian749d7232007-12-07 07:57:54 -070051 * into the XImage's buffer then the pixel must be byte swapped first.
Brianef25c492007-10-31 14:19:09 -060052 *
53 */
54
55#ifdef __CYGWIN__
56#undef WIN32
57#undef __WIN32__
58#endif
59
60#include "glxheader.h"
Keith Whitwell25deb852009-01-08 15:42:15 +000061#include "xm_api.h"
Brian6f467e52007-12-11 19:16:26 -070062#include "main/context.h"
63#include "main/framebuffer.h"
Brianef25c492007-10-31 14:19:09 -060064
65#include "state_tracker/st_public.h"
66#include "state_tracker/st_context.h"
Brianef25c492007-10-31 14:19:09 -060067#include "pipe/p_defines.h"
José Fonseca969ff9e2008-08-14 10:47:39 +010068#include "pipe/p_screen.h"
Keith Whitwell002dfb12009-01-08 14:10:56 +000069#include "pipe/p_winsys.h"
Brian749d7232007-12-07 07:57:54 -070070#include "pipe/p_context.h"
Brianef25c492007-10-31 14:19:09 -060071
Keith Whitwell002dfb12009-01-08 14:10:56 +000072#include "xm_winsys.h"
Zack Rusinc474f1f2007-12-11 07:19:11 -050073
Brianef25c492007-10-31 14:19:09 -060074/**
75 * Global X driver lock
76 */
Brian Paul0bb852f2008-08-26 16:35:12 -060077pipe_mutex _xmesa_lock;
Brianef25c492007-10-31 14:19:09 -060078
79
80
Brianef25c492007-10-31 14:19:09 -060081/**********************************************************************/
82/***** X Utility Functions *****/
83/**********************************************************************/
84
85
86/**
87 * Return the host's byte order as LSBFirst or MSBFirst ala X.
88 */
Brianef25c492007-10-31 14:19:09 -060089static int host_byte_order( void )
90{
91 int i = 1;
92 char *cptr = (char *) &i;
93 return (*cptr==1) ? LSBFirst : MSBFirst;
94}
Brianef25c492007-10-31 14:19:09 -060095
96
97/**
98 * Check if the X Shared Memory extension is available.
99 * Return: 0 = not available
100 * 1 = shared XImage support available
101 * 2 = shared Pixmap support available also
102 */
Keith Whitwell153b4d52009-01-08 15:23:51 +0000103int xmesa_check_for_xshm( Display *display )
Brianef25c492007-10-31 14:19:09 -0600104{
Keith Whitwell18ad0e32009-01-08 15:00:27 +0000105#if defined(USE_XSHM)
Brianef25c492007-10-31 14:19:09 -0600106 int major, minor, ignore;
107 Bool pixmaps;
108
Keith Whitwellfec1d212008-05-08 22:10:15 +0100109 if (getenv("SP_NO_RAST"))
110 return 0;
111
Ian Romanickb09de962008-03-25 18:07:56 -0700112 if (getenv("MESA_NOSHM")) {
113 return 0;
114 }
115
Brianef25c492007-10-31 14:19:09 -0600116 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
117 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
118 return (pixmaps==True) ? 2 : 1;
119 }
120 else {
121 return 0;
122 }
123 }
124 else {
125 return 0;
126 }
127#else
128 /* No XSHM support */
129 return 0;
130#endif
131}
132
133
134/**
Brianef25c492007-10-31 14:19:09 -0600135 * Return the true number of bits per pixel for XImages.
136 * For example, if we request a 24-bit deep visual we may actually need/get
137 * 32bpp XImages. This function returns the appropriate bpp.
138 * Input: dpy - the X display
139 * visinfo - desribes the visual to be used for XImages
140 * Return: true number of bits per pixel for XImages
141 */
142static int
143bits_per_pixel( XMesaVisual xmv )
144{
Keith Whitwell153b4d52009-01-08 15:23:51 +0000145 Display *dpy = xmv->display;
146 XVisualInfo * visinfo = xmv->visinfo;
147 XImage *img;
Brianef25c492007-10-31 14:19:09 -0600148 int bitsPerPixel;
149 /* Create a temporary XImage */
150 img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
151 ZPixmap, 0, /*format, offset*/
152 (char*) MALLOC(8), /*data*/
153 1, 1, /*width, height*/
154 32, /*bitmap_pad*/
155 0 /*bytes_per_line*/
156 );
157 assert(img);
158 /* grab the bits/pixel value */
159 bitsPerPixel = img->bits_per_pixel;
160 /* free the XImage */
161 _mesa_free( img->data );
162 img->data = NULL;
Keith Whitwell2b960122009-01-08 15:33:32 +0000163 XDestroyImage( img );
Brianef25c492007-10-31 14:19:09 -0600164 return bitsPerPixel;
Brianef25c492007-10-31 14:19:09 -0600165}
166
167
168
169/*
170 * Determine if a given X window ID is valid (window exists).
171 * Do this by calling XGetWindowAttributes() for the window and
172 * checking if we catch an X error.
173 * Input: dpy - the display
174 * win - the window to check for existance
175 * Return: GL_TRUE - window exists
176 * GL_FALSE - window doesn't exist
177 */
Brianef25c492007-10-31 14:19:09 -0600178static GLboolean WindowExistsFlag;
179
Keith Whitwell153b4d52009-01-08 15:23:51 +0000180static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
Brianef25c492007-10-31 14:19:09 -0600181{
182 (void) dpy;
183 if (xerr->error_code == BadWindow) {
184 WindowExistsFlag = GL_FALSE;
185 }
186 return 0;
187}
188
Keith Whitwell153b4d52009-01-08 15:23:51 +0000189static GLboolean window_exists( Display *dpy, Window win )
Brianef25c492007-10-31 14:19:09 -0600190{
191 XWindowAttributes wa;
Keith Whitwell153b4d52009-01-08 15:23:51 +0000192 int (*old_handler)( Display*, XErrorEvent* );
Brianef25c492007-10-31 14:19:09 -0600193 WindowExistsFlag = GL_TRUE;
194 old_handler = XSetErrorHandler(window_exists_err_handler);
195 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
196 XSetErrorHandler(old_handler);
197 return WindowExistsFlag;
198}
199
200static Status
Keith Whitwell153b4d52009-01-08 15:23:51 +0000201get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
Brianef25c492007-10-31 14:19:09 -0600202{
203 Window root;
204 Status stat;
205 int xpos, ypos;
206 unsigned int w, h, bw, depth;
207 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
208 *width = w;
209 *height = h;
210 return stat;
211}
Brianef25c492007-10-31 14:19:09 -0600212
213
214/**
215 * Return the size of the window (or pixmap) that corresponds to the
216 * given XMesaBuffer.
217 * \param width returns width in pixels
218 * \param height returns height in pixels
219 */
Brian749d7232007-12-07 07:57:54 -0700220static void
Keith Whitwell153b4d52009-01-08 15:23:51 +0000221xmesa_get_window_size(Display *dpy, XMesaBuffer b,
Brianef25c492007-10-31 14:19:09 -0600222 GLuint *width, GLuint *height)
223{
Brianef25c492007-10-31 14:19:09 -0600224 Status stat;
225
Brian Paul0bb852f2008-08-26 16:35:12 -0600226 pipe_mutex_lock(_xmesa_lock);
Brianef25c492007-10-31 14:19:09 -0600227 XSync(b->xm_visual->display, 0); /* added for Chromium */
Brian749d7232007-12-07 07:57:54 -0700228 stat = get_drawable_size(dpy, b->drawable, width, height);
Brian Paul0bb852f2008-08-26 16:35:12 -0600229 pipe_mutex_unlock(_xmesa_lock);
Brianef25c492007-10-31 14:19:09 -0600230
231 if (!stat) {
232 /* probably querying a window that's recently been destroyed */
233 _mesa_warning(NULL, "XGetGeometry failed!\n");
234 *width = *height = 1;
235 }
Brianef25c492007-10-31 14:19:09 -0600236}
237
Keith Whitwell2b960122009-01-08 15:33:32 +0000238#define GET_REDMASK(__v) __v->mesa_visual.redMask
239#define GET_GREENMASK(__v) __v->mesa_visual.greenMask
240#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask
241
Brianef25c492007-10-31 14:19:09 -0600242
Brian20eae592007-12-12 14:55:57 -0700243/**
244 * Choose the pixel format for the given visual.
245 * This will tell the gallium driver how to pack pixel data into
246 * drawing surfaces.
247 */
248static GLuint
249choose_pixel_format(XMesaVisual v)
250{
Keith Whitwell2b960122009-01-08 15:33:32 +0000251 boolean native_byte_order = (host_byte_order() ==
252 ImageByteOrder(v->display));
253
Brian20eae592007-12-12 14:55:57 -0700254 if ( GET_REDMASK(v) == 0x0000ff
255 && GET_GREENMASK(v) == 0x00ff00
256 && GET_BLUEMASK(v) == 0xff0000
257 && v->BitsPerPixel == 32) {
Keith Whitwell2b960122009-01-08 15:33:32 +0000258 if (native_byte_order) {
Brian20eae592007-12-12 14:55:57 -0700259 /* no byteswapping needed */
260 return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */;
261 }
262 else {
263 return PIPE_FORMAT_R8G8B8A8_UNORM;
264 }
265 }
266 else if ( GET_REDMASK(v) == 0xff0000
267 && GET_GREENMASK(v) == 0x00ff00
268 && GET_BLUEMASK(v) == 0x0000ff
269 && v->BitsPerPixel == 32) {
Keith Whitwell2b960122009-01-08 15:33:32 +0000270 if (native_byte_order) {
Brian20eae592007-12-12 14:55:57 -0700271 /* no byteswapping needed */
272 return PIPE_FORMAT_A8R8G8B8_UNORM;
273 }
274 else {
275 return PIPE_FORMAT_B8G8R8A8_UNORM;
276 }
277 }
278 else if ( GET_REDMASK(v) == 0xf800
279 && GET_GREENMASK(v) == 0x07e0
280 && GET_BLUEMASK(v) == 0x001f
Keith Whitwell2b960122009-01-08 15:33:32 +0000281 && native_byte_order
Brian20eae592007-12-12 14:55:57 -0700282 && v->BitsPerPixel == 16) {
283 /* 5-6-5 RGB */
284 return PIPE_FORMAT_R5G6B5_UNORM;
285 }
286
287 assert(0);
288 return 0;
289}
290
291
Brianef25c492007-10-31 14:19:09 -0600292
293/**********************************************************************/
294/***** Linked list of XMesaBuffers *****/
295/**********************************************************************/
296
297XMesaBuffer XMesaBufferList = NULL;
298
299
300/**
301 * Allocate a new XMesaBuffer object which corresponds to the given drawable.
302 * Note that XMesaBuffer is derived from GLframebuffer.
303 * The new XMesaBuffer will not have any size (Width=Height=0).
304 *
305 * \param d the corresponding X drawable (window or pixmap)
306 * \param type either WINDOW, PIXMAP or PBUFFER, describing d
307 * \param vis the buffer's visual
308 * \param cmap the window's colormap, if known.
309 * \return new XMesaBuffer or NULL if any problem
310 */
311static XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000312create_xmesa_buffer(Drawable d, BufferType type,
313 XMesaVisual vis, Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600314{
315 XMesaBuffer b;
Briane39f1b42007-11-05 15:59:55 -0700316 GLframebuffer *fb;
Brian20eae592007-12-12 14:55:57 -0700317 enum pipe_format colorFormat, depthFormat, stencilFormat;
Brianc6643022007-12-19 13:45:00 -0700318 uint width, height;
Brianef25c492007-10-31 14:19:09 -0600319
320 ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
321
322 b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
323 if (!b)
324 return NULL;
325
Brian749d7232007-12-07 07:57:54 -0700326 b->drawable = d;
327
Brianef25c492007-10-31 14:19:09 -0600328 b->xm_visual = vis;
329 b->type = type;
330 b->cmap = cmap;
331
Brian20eae592007-12-12 14:55:57 -0700332 /* determine PIPE_FORMATs for buffers */
333 colorFormat = choose_pixel_format(vis);
334
335 if (vis->mesa_visual.depthBits == 0)
336 depthFormat = PIPE_FORMAT_NONE;
Brian Paul284ab5a2008-09-10 18:22:00 -0600337#ifdef GALLIUM_CELL /* XXX temporary for Cell! */
338 else
339 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
340#else
Brian20eae592007-12-12 14:55:57 -0700341 else if (vis->mesa_visual.depthBits <= 16)
Keith Whitwell536092f2008-09-11 18:35:19 +0100342 depthFormat = PIPE_FORMAT_Z16_UNORM;
Brian20eae592007-12-12 14:55:57 -0700343 else if (vis->mesa_visual.depthBits <= 24)
344 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
345 else
346 depthFormat = PIPE_FORMAT_Z32_UNORM;
Brian Paul284ab5a2008-09-10 18:22:00 -0600347#endif
Brian20eae592007-12-12 14:55:57 -0700348
349 if (vis->mesa_visual.stencilBits == 8) {
350 if (depthFormat == PIPE_FORMAT_S8Z24_UNORM)
351 stencilFormat = depthFormat;
352 else
353 stencilFormat = PIPE_FORMAT_S8_UNORM;
354 }
355 else {
Brian Paulc1c4ff22008-08-07 15:11:54 -0600356 /* no stencil */
Brian20eae592007-12-12 14:55:57 -0700357 stencilFormat = PIPE_FORMAT_NONE;
Brian Paulc1c4ff22008-08-07 15:11:54 -0600358 if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) {
359 /* use 24-bit Z, undefined stencil channel */
360 depthFormat = PIPE_FORMAT_X8Z24_UNORM;
361 }
Brian20eae592007-12-12 14:55:57 -0700362 }
363
364
Brianc6643022007-12-19 13:45:00 -0700365 get_drawable_size(vis->display, d, &width, &height);
366
Briane39f1b42007-11-05 15:59:55 -0700367 /*
368 * Create framebuffer, but we'll plug in our own renderbuffers below.
369 */
Brianc6643022007-12-19 13:45:00 -0700370 b->stfb = st_create_framebuffer(&vis->mesa_visual,
Brian20eae592007-12-12 14:55:57 -0700371 colorFormat, depthFormat, stencilFormat,
Brianc6643022007-12-19 13:45:00 -0700372 width, height,
Brian20eae592007-12-12 14:55:57 -0700373 (void *) b);
Briane39f1b42007-11-05 15:59:55 -0700374 fb = &b->stfb->Base;
375
Brianef25c492007-10-31 14:19:09 -0600376 /*
Brian749d7232007-12-07 07:57:54 -0700377 * Create scratch XImage for xmesa_display_surface()
Brianb7611772007-10-31 19:00:23 -0600378 */
Brian749d7232007-12-07 07:57:54 -0700379 b->tempImage = XCreateImage(vis->display,
380 vis->visinfo->visual,
381 vis->visinfo->depth,
382 ZPixmap, 0, /* format, offset */
383 NULL, /* data */
384 0, 0, /* size */
385 32, /* bitmap_pad */
386 0); /* bytes_per_line */
Brianef25c492007-10-31 14:19:09 -0600387
388 /* GLX_EXT_texture_from_pixmap */
389 b->TextureTarget = 0;
390 b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
391 b->TextureMipmap = 0;
392
393 /* insert buffer into linked list */
394 b->Next = XMesaBufferList;
395 XMesaBufferList = b;
396
397 return b;
398}
399
400
401/**
402 * Find an XMesaBuffer by matching X display and colormap but NOT matching
403 * the notThis buffer.
404 */
405XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000406xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
Brianef25c492007-10-31 14:19:09 -0600407{
408 XMesaBuffer b;
Brian749d7232007-12-07 07:57:54 -0700409 for (b = XMesaBufferList; b; b = b->Next) {
410 if (b->xm_visual->display == dpy &&
411 b->cmap == cmap &&
412 b != notThis) {
Brianef25c492007-10-31 14:19:09 -0600413 return b;
414 }
415 }
416 return NULL;
417}
418
419
420/**
421 * Remove buffer from linked list, delete if no longer referenced.
422 */
423static void
424xmesa_free_buffer(XMesaBuffer buffer)
425{
426 XMesaBuffer prev = NULL, b;
427
428 for (b = XMesaBufferList; b; b = b->Next) {
429 if (b == buffer) {
Briane39f1b42007-11-05 15:59:55 -0700430 struct gl_framebuffer *fb = &buffer->stfb->Base;
Brianef25c492007-10-31 14:19:09 -0600431
432 /* unlink buffer from list */
433 if (prev)
434 prev->Next = buffer->Next;
435 else
436 XMesaBufferList = buffer->Next;
437
438 /* mark as delete pending */
439 fb->DeletePending = GL_TRUE;
440
441 /* Since the X window for the XMesaBuffer is going away, we don't
442 * want to dereference this pointer in the future.
443 */
Brian749d7232007-12-07 07:57:54 -0700444 b->drawable = 0;
445
446 buffer->tempImage->data = NULL;
447 XDestroyImage(buffer->tempImage);
Brianef25c492007-10-31 14:19:09 -0600448
449 /* Unreference. If count = zero we'll really delete the buffer */
450 _mesa_unreference_framebuffer(&fb);
451
Brianf44e2f12007-12-26 06:56:58 -0700452 XFreeGC(b->xm_visual->display, b->gc);
453
454 free(buffer);
455
Brianef25c492007-10-31 14:19:09 -0600456 return;
457 }
458 /* continue search */
459 prev = b;
460 }
461 /* buffer not found in XMesaBufferList */
462 _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
463}
464
465
Brianef25c492007-10-31 14:19:09 -0600466
467/**********************************************************************/
468/***** Misc Private Functions *****/
469/**********************************************************************/
470
471
472/**
Brianef25c492007-10-31 14:19:09 -0600473 * When a context is bound for the first time, we can finally finish
474 * initializing the context's visual and buffer information.
475 * \param v the XMesaVisual to initialize
476 * \param b the XMesaBuffer to initialize (may be NULL)
477 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode
478 * \param window the window/pixmap we're rendering into
479 * \param cmap the colormap associated with the window/pixmap
480 * \return GL_TRUE=success, GL_FALSE=failure
481 */
482static GLboolean
483initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000484 GLboolean rgb_flag, Drawable window,
485 Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600486{
Brianef25c492007-10-31 14:19:09 -0600487 ASSERT(!b || b->xm_visual == v);
488
489 /* Save true bits/pixel */
490 v->BitsPerPixel = bits_per_pixel(v);
491 assert(v->BitsPerPixel > 0);
492
493 if (rgb_flag == GL_FALSE) {
Brian749d7232007-12-07 07:57:54 -0700494 /* COLOR-INDEXED WINDOW: not supported*/
495 return GL_FALSE;
Brianef25c492007-10-31 14:19:09 -0600496 }
497 else {
498 /* RGB WINDOW:
499 * We support RGB rendering into almost any kind of visual.
500 */
501 const int xclass = v->mesa_visual.visualType;
Brian749d7232007-12-07 07:57:54 -0700502 if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
503 _mesa_warning(NULL,
504 "XMesa: RGB mode rendering not supported in given visual.\n");
Brianef25c492007-10-31 14:19:09 -0600505 return GL_FALSE;
506 }
507 v->mesa_visual.indexBits = 0;
Brian5935b162008-03-27 21:11:45 -0600508
509 if (v->BitsPerPixel == 32) {
510 /* We use XImages for all front/back buffers. If an X Window or
511 * X Pixmap is 32bpp, there's no guarantee that the alpha channel
512 * will be preserved. For XImages we're in luck.
513 */
514 v->mesa_visual.alphaBits = 8;
515 }
Brianef25c492007-10-31 14:19:09 -0600516 }
517
Brianef25c492007-10-31 14:19:09 -0600518 /*
519 * If MESA_INFO env var is set print out some debugging info
520 * which can help Brian figure out what's going on when a user
521 * reports bugs.
522 */
523 if (_mesa_getenv("MESA_INFO")) {
524 _mesa_printf("X/Mesa visual = %p\n", (void *) v);
Brianef25c492007-10-31 14:19:09 -0600525 _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
Keith Whitwell2b960122009-01-08 15:33:32 +0000526 _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth);
Brianef25c492007-10-31 14:19:09 -0600527 _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
528 }
529
530 if (b && window) {
Brianef25c492007-10-31 14:19:09 -0600531 /* these should have been set in create_xmesa_buffer */
Brian749d7232007-12-07 07:57:54 -0700532 ASSERT(b->drawable == window);
Brianef25c492007-10-31 14:19:09 -0600533
534 /* Setup for single/double buffering */
535 if (v->mesa_visual.doubleBufferMode) {
536 /* Double buffered */
Ian Romanickb09de962008-03-25 18:07:56 -0700537 b->shm = xmesa_check_for_xshm( v->display );
Brianef25c492007-10-31 14:19:09 -0600538 }
539
Brian749d7232007-12-07 07:57:54 -0700540 /* X11 graphics context */
Brianef25c492007-10-31 14:19:09 -0600541 b->gc = XCreateGC( v->display, window, 0, NULL );
Keith Whitwell2b960122009-01-08 15:33:32 +0000542 XSetFunction( v->display, b->gc, GXcopy );
Brianef25c492007-10-31 14:19:09 -0600543 }
544
545 return GL_TRUE;
546}
547
548
549
Brianef25c492007-10-31 14:19:09 -0600550#define NUM_VISUAL_TYPES 6
551
552/**
553 * Convert an X visual type to a GLX visual type.
554 *
555 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
556 * to be converted.
557 * \return If \c visualType is a valid X visual type, a GLX visual type will
558 * be returned. Otherwise \c GLX_NONE will be returned.
559 *
560 * \note
561 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
562 * DRI CVS tree.
563 */
564static GLint
565xmesa_convert_from_x_visual_type( int visualType )
566{
567 static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
568 GLX_STATIC_GRAY, GLX_GRAY_SCALE,
569 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
570 GLX_TRUE_COLOR, GLX_DIRECT_COLOR
571 };
572
573 return ( (unsigned) visualType < NUM_VISUAL_TYPES )
574 ? glx_visual_types[ visualType ] : GLX_NONE;
575}
576
577
578/**********************************************************************/
579/***** Public Functions *****/
580/**********************************************************************/
581
582
583/*
584 * Create a new X/Mesa visual.
585 * Input: display - X11 display
586 * visinfo - an XVisualInfo pointer
587 * rgb_flag - GL_TRUE = RGB mode,
588 * GL_FALSE = color index mode
589 * alpha_flag - alpha buffer requested?
590 * db_flag - GL_TRUE = double-buffered,
591 * GL_FALSE = single buffered
592 * stereo_flag - stereo visual?
593 * ximage_flag - GL_TRUE = use an XImage for back buffer,
594 * GL_FALSE = use an off-screen pixmap for back buffer
595 * depth_size - requested bits/depth values, or zero
596 * stencil_size - requested bits/stencil values, or zero
597 * accum_red_size - requested bits/red accum values, or zero
598 * accum_green_size - requested bits/green accum values, or zero
599 * accum_blue_size - requested bits/blue accum values, or zero
600 * accum_alpha_size - requested bits/alpha accum values, or zero
601 * num_samples - number of samples/pixel if multisampling, or zero
602 * level - visual level, usually 0
603 * visualCaveat - ala the GLX extension, usually GLX_NONE
604 * Return; a new XMesaVisual or 0 if error.
605 */
606PUBLIC
Keith Whitwell153b4d52009-01-08 15:23:51 +0000607XMesaVisual XMesaCreateVisual( Display *display,
608 XVisualInfo * visinfo,
Brianef25c492007-10-31 14:19:09 -0600609 GLboolean rgb_flag,
610 GLboolean alpha_flag,
611 GLboolean db_flag,
612 GLboolean stereo_flag,
613 GLboolean ximage_flag,
614 GLint depth_size,
615 GLint stencil_size,
616 GLint accum_red_size,
617 GLint accum_green_size,
618 GLint accum_blue_size,
619 GLint accum_alpha_size,
620 GLint num_samples,
621 GLint level,
622 GLint visualCaveat )
623{
Brianef25c492007-10-31 14:19:09 -0600624 XMesaVisual v;
625 GLint red_bits, green_bits, blue_bits, alpha_bits;
626
Brianef25c492007-10-31 14:19:09 -0600627 /* For debugging only */
628 if (_mesa_getenv("MESA_XSYNC")) {
629 /* This makes debugging X easier.
630 * In your debugger, set a breakpoint on _XError to stop when an
631 * X protocol error is generated.
632 */
633 XSynchronize( display, 1 );
634 }
Brianef25c492007-10-31 14:19:09 -0600635
636 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
637 if (!v) {
638 return NULL;
639 }
640
641 v->display = display;
642
643 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
644 * the struct but we may need some of the information contained in it
645 * at a later time.
646 */
Brianef25c492007-10-31 14:19:09 -0600647 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
648 if(!v->visinfo) {
649 _mesa_free(v);
650 return NULL;
651 }
652 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
Brianef25c492007-10-31 14:19:09 -0600653
Brianef25c492007-10-31 14:19:09 -0600654 v->ximage_flag = ximage_flag;
655
Brianef25c492007-10-31 14:19:09 -0600656 v->mesa_visual.redMask = visinfo->red_mask;
657 v->mesa_visual.greenMask = visinfo->green_mask;
658 v->mesa_visual.blueMask = visinfo->blue_mask;
659 v->mesa_visual.visualID = visinfo->visualid;
660 v->mesa_visual.screen = visinfo->screen;
Brianef25c492007-10-31 14:19:09 -0600661
Keith Whitwell18ad0e32009-01-08 15:00:27 +0000662#if !(defined(__cplusplus) || defined(c_plusplus))
Brianef25c492007-10-31 14:19:09 -0600663 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
664#else
665 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
666#endif
667
668 v->mesa_visual.visualRating = visualCaveat;
669
670 if (alpha_flag)
671 v->mesa_visual.alphaBits = 8;
672
673 (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
674
675 {
676 const int xclass = v->mesa_visual.visualType;
677 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
678 red_bits = _mesa_bitcount(GET_REDMASK(v));
679 green_bits = _mesa_bitcount(GET_GREENMASK(v));
680 blue_bits = _mesa_bitcount(GET_BLUEMASK(v));
681 }
682 else {
683 /* this is an approximation */
684 int depth;
Keith Whitwell2b960122009-01-08 15:33:32 +0000685 depth = v->visinfo->depth;
Brianef25c492007-10-31 14:19:09 -0600686 red_bits = depth / 3;
687 depth -= red_bits;
688 green_bits = depth / 2;
689 depth -= green_bits;
690 blue_bits = depth;
691 alpha_bits = 0;
Keith Whitwell2b960122009-01-08 15:33:32 +0000692 assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
Brianef25c492007-10-31 14:19:09 -0600693 }
694 alpha_bits = v->mesa_visual.alphaBits;
695 }
696
697 _mesa_initialize_visual( &v->mesa_visual,
698 rgb_flag, db_flag, stereo_flag,
699 red_bits, green_bits,
700 blue_bits, alpha_bits,
701 v->mesa_visual.indexBits,
702 depth_size,
703 stencil_size,
704 accum_red_size, accum_green_size,
705 accum_blue_size, accum_alpha_size,
706 0 );
707
708 /* XXX minor hack */
709 v->mesa_visual.level = level;
710 return v;
711}
712
713
714PUBLIC
715void XMesaDestroyVisual( XMesaVisual v )
716{
Brianef25c492007-10-31 14:19:09 -0600717 _mesa_free(v->visinfo);
Brianef25c492007-10-31 14:19:09 -0600718 _mesa_free(v);
719}
720
721
722
723/**
724 * Create a new XMesaContext.
725 * \param v the XMesaVisual
726 * \param share_list another XMesaContext with which to share display
727 * lists or NULL if no sharing is wanted.
728 * \return an XMesaContext or NULL if error.
729 */
730PUBLIC
731XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
732{
733 static GLboolean firstTime = GL_TRUE;
Keith Whitwell002dfb12009-01-08 14:10:56 +0000734 struct pipe_winsys *winsys;
735 struct pipe_screen *screen;
Briane39f1b42007-11-05 15:59:55 -0700736 struct pipe_context *pipe;
Brianef25c492007-10-31 14:19:09 -0600737 XMesaContext c;
738 GLcontext *mesaCtx;
Brian749d7232007-12-07 07:57:54 -0700739 uint pf;
Briane39f1b42007-11-05 15:59:55 -0700740
Brianef25c492007-10-31 14:19:09 -0600741 if (firstTime) {
Brian Paul0bb852f2008-08-26 16:35:12 -0600742 pipe_mutex_init(_xmesa_lock);
Brianef25c492007-10-31 14:19:09 -0600743 firstTime = GL_FALSE;
744 }
745
746 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
747 c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
748 if (!c)
749 return NULL;
750
Brian749d7232007-12-07 07:57:54 -0700751 pf = choose_pixel_format(v);
Brian0d1669f2007-12-07 08:24:56 -0700752 assert(pf);
Brian749d7232007-12-07 07:57:54 -0700753
Ian Romanickb09de962008-03-25 18:07:56 -0700754 c->xm_visual = v;
755 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
Keith Whitwell002dfb12009-01-08 14:10:56 +0000756
757 /* XXX: create once per Xlib Display.
758 */
759 winsys = xmesa_create_pipe_winsys();
760 if (winsys == NULL)
761 goto fail;
Ian Romanickb09de962008-03-25 18:07:56 -0700762
Keith Whitwell002dfb12009-01-08 14:10:56 +0000763 /* XXX: create once per Xlib Display.
764 */
765 screen = xmesa_create_pipe_screen( winsys );
766 if (screen == NULL)
767 goto fail;
Brianef25c492007-10-31 14:19:09 -0600768
Keith Whitwell002dfb12009-01-08 14:10:56 +0000769 pipe = xmesa_create_pipe_context( screen,
770 (void *)c );
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100771 if (pipe == NULL)
772 goto fail;
773
Keith Whitwell002dfb12009-01-08 14:10:56 +0000774 c->st = st_create_context(pipe,
775 &v->mesa_visual,
Brian91564ee2007-11-05 16:15:43 -0700776 share_list ? share_list->st : NULL);
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100777 if (c->st == NULL)
778 goto fail;
Keith Whitwell002dfb12009-01-08 14:10:56 +0000779
Briane39f1b42007-11-05 15:59:55 -0700780 mesaCtx = c->st->ctx;
781 c->st->ctx->DriverCtx = c;
Brianef25c492007-10-31 14:19:09 -0600782
Briane39f1b42007-11-05 15:59:55 -0700783#if 00
Brianef25c492007-10-31 14:19:09 -0600784 _mesa_enable_sw_extensions(mesaCtx);
785 _mesa_enable_1_3_extensions(mesaCtx);
786 _mesa_enable_1_4_extensions(mesaCtx);
787 _mesa_enable_1_5_extensions(mesaCtx);
788 _mesa_enable_2_0_extensions(mesaCtx);
Briane39f1b42007-11-05 15:59:55 -0700789#endif
Brianef25c492007-10-31 14:19:09 -0600790
Brianef25c492007-10-31 14:19:09 -0600791 return c;
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100792
793 fail:
794 if (c->st)
795 st_destroy_context(c->st);
José Fonseca969ff9e2008-08-14 10:47:39 +0100796 else if (pipe)
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100797 pipe->destroy(pipe);
Keith Whitwell002dfb12009-01-08 14:10:56 +0000798
799 if (screen)
800 screen->destroy( screen );
801
802 if (winsys)
803 winsys->destroy( winsys );
804
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100805 FREE(c);
806 return NULL;
Brianef25c492007-10-31 14:19:09 -0600807}
808
809
810
811PUBLIC
812void XMesaDestroyContext( XMesaContext c )
813{
Brian91564ee2007-11-05 16:15:43 -0700814 st_destroy_context(c->st);
Keith Whitwell002dfb12009-01-08 14:10:56 +0000815
José Fonsecaf9e14e02008-08-19 00:18:19 +0100816 /* FIXME: We should destroy the screen here, but if we do so, surfaces may
817 * outlive it, causing segfaults
Keith Whitwell002dfb12009-01-08 14:10:56 +0000818 struct pipe_screen *screen = c->st->pipe->screen;
José Fonseca969ff9e2008-08-14 10:47:39 +0100819 screen->destroy(screen);
José Fonsecaf9e14e02008-08-19 00:18:19 +0100820 */
Keith Whitwell002dfb12009-01-08 14:10:56 +0000821
Briane39f1b42007-11-05 15:59:55 -0700822 _mesa_free(c);
Brianef25c492007-10-31 14:19:09 -0600823}
824
825
826
827/**
828 * Private function for creating an XMesaBuffer which corresponds to an
829 * X window or pixmap.
830 * \param v the window's XMesaVisual
831 * \param w the window we're wrapping
832 * \return new XMesaBuffer or NULL if error
833 */
834PUBLIC XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000835XMesaCreateWindowBuffer(XMesaVisual v, Window w)
Brianef25c492007-10-31 14:19:09 -0600836{
Brianef25c492007-10-31 14:19:09 -0600837 XWindowAttributes attr;
Brianef25c492007-10-31 14:19:09 -0600838 XMesaBuffer b;
Keith Whitwell153b4d52009-01-08 15:23:51 +0000839 Colormap cmap;
Brianef25c492007-10-31 14:19:09 -0600840 int depth;
841
842 assert(v);
843 assert(w);
844
845 /* Check that window depth matches visual depth */
Brianef25c492007-10-31 14:19:09 -0600846 XGetWindowAttributes( v->display, w, &attr );
847 depth = attr.depth;
Keith Whitwell2b960122009-01-08 15:33:32 +0000848 if (v->visinfo->depth != depth) {
Brianef25c492007-10-31 14:19:09 -0600849 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
Keith Whitwell2b960122009-01-08 15:33:32 +0000850 v->visinfo->depth, depth);
Brianef25c492007-10-31 14:19:09 -0600851 return NULL;
852 }
853
854 /* Find colormap */
Brianef25c492007-10-31 14:19:09 -0600855 if (attr.colormap) {
856 cmap = attr.colormap;
857 }
858 else {
859 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
860 /* this is weird, a window w/out a colormap!? */
861 /* OK, let's just allocate a new one and hope for the best */
862 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
863 }
Brianef25c492007-10-31 14:19:09 -0600864
Keith Whitwell153b4d52009-01-08 15:23:51 +0000865 b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600866 if (!b)
867 return NULL;
868
869 if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000870 (Drawable) w, cmap )) {
Brianef25c492007-10-31 14:19:09 -0600871 xmesa_free_buffer(b);
872 return NULL;
873 }
874
875 return b;
876}
877
878
879
880/**
881 * Create a new XMesaBuffer from an X pixmap.
882 *
883 * \param v the XMesaVisual
884 * \param p the pixmap
885 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
886 * \c GLX_DIRECT_COLOR visual for the pixmap
887 * \returns new XMesaBuffer or NULL if error
888 */
889PUBLIC XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000890XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600891{
892 XMesaBuffer b;
893
894 assert(v);
895
Keith Whitwell153b4d52009-01-08 15:23:51 +0000896 b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600897 if (!b)
898 return NULL;
899
900 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000901 (Drawable) p, cmap)) {
Brianef25c492007-10-31 14:19:09 -0600902 xmesa_free_buffer(b);
903 return NULL;
904 }
905
906 return b;
907}
908
909
910/**
911 * For GLX_EXT_texture_from_pixmap
912 */
913XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000914XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
915 Colormap cmap,
Brianef25c492007-10-31 14:19:09 -0600916 int format, int target, int mipmap)
917{
918 GET_CURRENT_CONTEXT(ctx);
919 XMesaBuffer b;
920 GLuint width, height;
921
922 assert(v);
923
Keith Whitwell153b4d52009-01-08 15:23:51 +0000924 b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600925 if (!b)
926 return NULL;
927
928 /* get pixmap size, update framebuffer/renderbuffer dims */
929 xmesa_get_window_size(v->display, b, &width, &height);
Briane39f1b42007-11-05 15:59:55 -0700930 _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
Brianef25c492007-10-31 14:19:09 -0600931
932 if (target == 0) {
933 /* examine dims */
934 if (ctx->Extensions.ARB_texture_non_power_of_two) {
935 target = GLX_TEXTURE_2D_EXT;
936 }
937 else if ( _mesa_bitcount(width) == 1
938 && _mesa_bitcount(height) == 1) {
939 /* power of two size */
940 if (height == 1) {
941 target = GLX_TEXTURE_1D_EXT;
942 }
943 else {
944 target = GLX_TEXTURE_2D_EXT;
945 }
946 }
947 else if (ctx->Extensions.NV_texture_rectangle) {
948 target = GLX_TEXTURE_RECTANGLE_EXT;
949 }
950 else {
951 /* non power of two textures not supported */
952 XMesaDestroyBuffer(b);
953 return 0;
954 }
955 }
956
957 b->TextureTarget = target;
958 b->TextureFormat = format;
959 b->TextureMipmap = mipmap;
960
961 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000962 (Drawable) p, cmap)) {
Brianef25c492007-10-31 14:19:09 -0600963 xmesa_free_buffer(b);
964 return NULL;
965 }
966
967 return b;
968}
969
970
971
972XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000973XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
Brianef25c492007-10-31 14:19:09 -0600974 unsigned int width, unsigned int height)
975{
Keith Whitwell153b4d52009-01-08 15:23:51 +0000976 Window root;
977 Drawable drawable; /* X Pixmap Drawable */
Brianef25c492007-10-31 14:19:09 -0600978 XMesaBuffer b;
979
980 /* allocate pixmap for front buffer */
981 root = RootWindow( v->display, v->visinfo->screen );
982 drawable = XCreatePixmap(v->display, root, width, height,
983 v->visinfo->depth);
984 if (!drawable)
985 return NULL;
986
987 b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
988 if (!b)
989 return NULL;
990
991 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
992 drawable, cmap)) {
993 xmesa_free_buffer(b);
994 return NULL;
995 }
996
997 return b;
Brianef25c492007-10-31 14:19:09 -0600998}
999
1000
1001
1002/*
1003 * Deallocate an XMesaBuffer structure and all related info.
1004 */
1005PUBLIC void
1006XMesaDestroyBuffer(XMesaBuffer b)
1007{
1008 xmesa_free_buffer(b);
1009}
1010
1011
1012/**
1013 * Query the current window size and update the corresponding GLframebuffer
1014 * and all attached renderbuffers.
1015 * Called when:
1016 * 1. the first time a buffer is bound to a context.
Keith Whitwellee287632009-01-08 16:05:45 +00001017 * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
Brianef25c492007-10-31 14:19:09 -06001018 * Note: it's possible (and legal) for xmctx to be NULL. That can happen
1019 * when resizing a buffer when no rendering context is bound.
1020 */
1021void
1022xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1023{
1024 GLuint width, height;
Brian749d7232007-12-07 07:57:54 -07001025 xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
Briane39f1b42007-11-05 15:59:55 -07001026 st_resize_framebuffer(drawBuffer->stfb, width, height);
Brianef25c492007-10-31 14:19:09 -06001027}
1028
1029
Brianef25c492007-10-31 14:19:09 -06001030
1031
1032/*
1033 * Bind buffer b to context c and make c the current rendering context.
1034 */
1035PUBLIC
1036GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1037 XMesaBuffer readBuffer )
1038{
1039 if (c) {
1040 if (!drawBuffer || !readBuffer)
1041 return GL_FALSE; /* must specify buffers! */
1042
Briane39f1b42007-11-05 15:59:55 -07001043#if 0
1044 /* XXX restore this optimization */
Brianef25c492007-10-31 14:19:09 -06001045 if (&(c->mesa) == _mesa_get_current_context()
1046 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1047 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
Brian749d7232007-12-07 07:57:54 -07001048 && xmesa_buffer(c->mesa.DrawBuffer)->wasCurrent) {
Brianef25c492007-10-31 14:19:09 -06001049 /* same context and buffer, do nothing */
1050 return GL_TRUE;
1051 }
Briane39f1b42007-11-05 15:59:55 -07001052#endif
Brianef25c492007-10-31 14:19:09 -06001053
1054 c->xm_buffer = drawBuffer;
1055
Brianef25c492007-10-31 14:19:09 -06001056 /* Call this periodically to detect when the user has begun using
1057 * GL rendering from multiple threads.
1058 */
1059 _glapi_check_multithread();
1060
Briandbf6ece2007-12-19 08:50:35 -07001061 st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
1062
Brianef25c492007-10-31 14:19:09 -06001063 xmesa_check_and_update_buffer_size(c, drawBuffer);
1064 if (readBuffer != drawBuffer)
1065 xmesa_check_and_update_buffer_size(c, readBuffer);
1066
Brianef25c492007-10-31 14:19:09 -06001067 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1068 drawBuffer->wasCurrent = GL_TRUE;
1069 }
1070 else {
1071 /* Detach */
Briane39f1b42007-11-05 15:59:55 -07001072 st_make_current( NULL, NULL, NULL );
Brianef25c492007-10-31 14:19:09 -06001073 }
1074 return GL_TRUE;
1075}
1076
1077
1078/*
1079 * Unbind the context c from its buffer.
1080 */
1081GLboolean XMesaUnbindContext( XMesaContext c )
1082{
1083 /* A no-op for XFree86 integration purposes */
1084 return GL_TRUE;
1085}
1086
1087
1088XMesaContext XMesaGetCurrentContext( void )
1089{
1090 GET_CURRENT_CONTEXT(ctx);
1091 if (ctx) {
Brian749d7232007-12-07 07:57:54 -07001092 XMesaContext xmesa = xmesa_context(ctx);
Brianef25c492007-10-31 14:19:09 -06001093 return xmesa;
1094 }
1095 else {
1096 return 0;
1097 }
1098}
1099
1100
Brianef25c492007-10-31 14:19:09 -06001101
1102
Brianef25c492007-10-31 14:19:09 -06001103
1104
1105/*
1106 * Copy the back buffer to the front buffer. If there's no back buffer
1107 * this is a no-op.
1108 */
1109PUBLIC
1110void XMesaSwapBuffers( XMesaBuffer b )
1111{
Brian749d7232007-12-07 07:57:54 -07001112 struct pipe_surface *surf;
Brianef25c492007-10-31 14:19:09 -06001113
1114 /* If we're swapping the buffer associated with the current context
1115 * we have to flush any pending rendering commands first.
1116 */
Briane39f1b42007-11-05 15:59:55 -07001117 st_notify_swapbuffers(b->stfb);
Brianef25c492007-10-31 14:19:09 -06001118
Brian749d7232007-12-07 07:57:54 -07001119 surf = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
1120 if (surf) {
Keith Whitwell002dfb12009-01-08 14:10:56 +00001121 xmesa_display_surface(b, surf);
1122// xmesa_display_surface(b, surf);
Brianef25c492007-10-31 14:19:09 -06001123 }
Brian749d7232007-12-07 07:57:54 -07001124
1125 xmesa_check_and_update_buffer_size(NULL, b);
Brianef25c492007-10-31 14:19:09 -06001126}
1127
1128
1129
1130/*
1131 * Copy sub-region of back buffer to front buffer
1132 */
1133void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1134{
Brian749d7232007-12-07 07:57:54 -07001135 struct pipe_surface *surf_front
1136 = st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT);
1137 struct pipe_surface *surf_back
1138 = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
1139 struct pipe_context *pipe = NULL; /* XXX fix */
Brianef25c492007-10-31 14:19:09 -06001140
Brian749d7232007-12-07 07:57:54 -07001141 if (!surf_front || !surf_back)
1142 return;
Briane39f1b42007-11-05 15:59:55 -07001143
Brian749d7232007-12-07 07:57:54 -07001144 pipe->surface_copy(pipe,
Michel Dänzere922adb2008-02-13 11:39:58 +00001145 FALSE,
Brian749d7232007-12-07 07:57:54 -07001146 surf_front, x, y, /* dest */
1147 surf_back, x, y, /* src */
1148 width, height);
Brianef25c492007-10-31 14:19:09 -06001149}
1150
1151
Brianef25c492007-10-31 14:19:09 -06001152
Brianef25c492007-10-31 14:19:09 -06001153void XMesaFlush( XMesaContext c )
1154{
Brian749d7232007-12-07 07:57:54 -07001155 if (c && c->xm_visual->display) {
Brian Paul6f33b772008-08-27 11:29:26 -06001156 st_finish(c->st);
Brian749d7232007-12-07 07:57:54 -07001157 XSync( c->xm_visual->display, False );
Brianef25c492007-10-31 14:19:09 -06001158 }
1159}
1160
1161
1162
Brianef25c492007-10-31 14:19:09 -06001163
1164
Keith Whitwell153b4d52009-01-08 15:23:51 +00001165XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
Brianef25c492007-10-31 14:19:09 -06001166{
1167 XMesaBuffer b;
1168 for (b=XMesaBufferList; b; b=b->Next) {
Brian749d7232007-12-07 07:57:54 -07001169 if (b->drawable == d && b->xm_visual->display == dpy) {
Brianef25c492007-10-31 14:19:09 -06001170 return b;
1171 }
1172 }
1173 return NULL;
1174}
1175
1176
1177/**
1178 * Free/destroy all XMesaBuffers associated with given display.
1179 */
Keith Whitwell153b4d52009-01-08 15:23:51 +00001180void xmesa_destroy_buffers_on_display(Display *dpy)
Brianef25c492007-10-31 14:19:09 -06001181{
1182 XMesaBuffer b, next;
1183 for (b = XMesaBufferList; b; b = next) {
1184 next = b->Next;
Brian749d7232007-12-07 07:57:54 -07001185 if (b->xm_visual->display == dpy) {
Brianef25c492007-10-31 14:19:09 -06001186 xmesa_free_buffer(b);
1187 }
1188 }
1189}
1190
1191
1192/*
1193 * Look for XMesaBuffers whose X window has been destroyed.
1194 * Deallocate any such XMesaBuffers.
1195 */
1196void XMesaGarbageCollect( void )
1197{
1198 XMesaBuffer b, next;
1199 for (b=XMesaBufferList; b; b=next) {
1200 next = b->Next;
Brian749d7232007-12-07 07:57:54 -07001201 if (b->xm_visual &&
1202 b->xm_visual->display &&
1203 b->drawable &&
1204 b->type == WINDOW) {
Brian749d7232007-12-07 07:57:54 -07001205 XSync(b->xm_visual->display, False);
1206 if (!window_exists( b->xm_visual->display, b->drawable )) {
Brianef25c492007-10-31 14:19:09 -06001207 /* found a dead window, free the ancillary info */
1208 XMesaDestroyBuffer( b );
1209 }
Brianef25c492007-10-31 14:19:09 -06001210 }
1211 }
1212}
1213
1214
Brianef25c492007-10-31 14:19:09 -06001215
1216
1217PUBLIC void
Keith Whitwell153b4d52009-01-08 15:23:51 +00001218XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
Brianef25c492007-10-31 14:19:09 -06001219 const int *attrib_list)
1220{
Brianef25c492007-10-31 14:19:09 -06001221}
1222
1223
1224
1225PUBLIC void
Keith Whitwell153b4d52009-01-08 15:23:51 +00001226XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
Brianef25c492007-10-31 14:19:09 -06001227{
Brianef25c492007-10-31 14:19:09 -06001228}
1229