blob: 1783bc504d91bec3b87668b0c1bedd39276efbe9 [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
Keith Whitwell25deb852009-01-08 15:42:15 +000060#include "xm_api.h"
Brian6f467e52007-12-11 19:16:26 -070061#include "main/context.h"
62#include "main/framebuffer.h"
Brianef25c492007-10-31 14:19:09 -060063
64#include "state_tracker/st_public.h"
65#include "state_tracker/st_context.h"
Brianef25c492007-10-31 14:19:09 -060066#include "pipe/p_defines.h"
José Fonseca969ff9e2008-08-14 10:47:39 +010067#include "pipe/p_screen.h"
Brian749d7232007-12-07 07:57:54 -070068#include "pipe/p_context.h"
Brianef25c492007-10-31 14:19:09 -060069
José Fonseca67171ed2009-12-28 16:25:48 +000070#include "trace/tr_screen.h"
71#include "trace/tr_context.h"
72#include "trace/tr_texture.h"
73
Keith Whitwell002dfb12009-01-08 14:10:56 +000074#include "xm_winsys.h"
Keith Whitwell05f8e412009-01-09 10:40:47 +000075#include <GL/glx.h>
Zack Rusinc474f1f2007-12-11 07:19:11 -050076
Keith Whitwell2f19fec2009-01-13 18:08:24 +000077
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 */
82static struct xm_driver driver;
83
84void xmesa_set_driver( const struct xm_driver *templ )
85{
86 driver = *templ;
87}
88
Brianef25c492007-10-31 14:19:09 -060089/**
90 * Global X driver lock
91 */
Brian Paul0bb852f2008-08-26 16:35:12 -060092pipe_mutex _xmesa_lock;
Brianef25c492007-10-31 14:19:09 -060093
José Fonseca67171ed2009-12-28 16:25:48 +000094static struct pipe_screen *_screen = NULL;
95static struct pipe_screen *screen = NULL;
Brianef25c492007-10-31 14:19:09 -060096
97
Brianef25c492007-10-31 14:19:09 -060098/**********************************************************************/
99/***** X Utility Functions *****/
100/**********************************************************************/
101
102
103/**
104 * Return the host's byte order as LSBFirst or MSBFirst ala X.
105 */
Brianef25c492007-10-31 14:19:09 -0600106static int host_byte_order( void )
107{
108 int i = 1;
109 char *cptr = (char *) &i;
110 return (*cptr==1) ? LSBFirst : MSBFirst;
111}
Brianef25c492007-10-31 14:19:09 -0600112
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 Whitwell153b4d52009-01-08 15:23:51 +0000120int xmesa_check_for_xshm( Display *display )
Brianef25c492007-10-31 14:19:09 -0600121{
Keith Whitwell18ad0e32009-01-08 15:00:27 +0000122#if defined(USE_XSHM)
Brianef25c492007-10-31 14:19:09 -0600123 int major, minor, ignore;
124 Bool pixmaps;
125
Keith Whitwellfec1d212008-05-08 22:10:15 +0100126 if (getenv("SP_NO_RAST"))
127 return 0;
128
Ian Romanickb09de962008-03-25 18:07:56 -0700129 if (getenv("MESA_NOSHM")) {
130 return 0;
131 }
132
Brianef25c492007-10-31 14:19:09 -0600133 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/**
Brianef25c492007-10-31 14:19:09 -0600152 * 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 */
159static int
160bits_per_pixel( XMesaVisual xmv )
161{
Keith Whitwell153b4d52009-01-08 15:23:51 +0000162 Display *dpy = xmv->display;
163 XVisualInfo * visinfo = xmv->visinfo;
164 XImage *img;
Brianef25c492007-10-31 14:19:09 -0600165 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 Whitwell2b960122009-01-08 15:33:32 +0000180 XDestroyImage( img );
Brianef25c492007-10-31 14:19:09 -0600181 return bitsPerPixel;
Brianef25c492007-10-31 14:19:09 -0600182}
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 */
Brianef25c492007-10-31 14:19:09 -0600195static GLboolean WindowExistsFlag;
196
Keith Whitwell153b4d52009-01-08 15:23:51 +0000197static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
Brianef25c492007-10-31 14:19:09 -0600198{
199 (void) dpy;
200 if (xerr->error_code == BadWindow) {
201 WindowExistsFlag = GL_FALSE;
202 }
203 return 0;
204}
205
Keith Whitwell153b4d52009-01-08 15:23:51 +0000206static GLboolean window_exists( Display *dpy, Window win )
Brianef25c492007-10-31 14:19:09 -0600207{
208 XWindowAttributes wa;
Keith Whitwell153b4d52009-01-08 15:23:51 +0000209 int (*old_handler)( Display*, XErrorEvent* );
Brianef25c492007-10-31 14:19:09 -0600210 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
217static Status
Keith Whitwell153b4d52009-01-08 15:23:51 +0000218get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
Brianef25c492007-10-31 14:19:09 -0600219{
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}
Brianef25c492007-10-31 14:19:09 -0600229
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 Paul05261002009-10-07 09:40:04 -0600237void
Keith Whitwell153b4d52009-01-08 15:23:51 +0000238xmesa_get_window_size(Display *dpy, XMesaBuffer b,
Brianef25c492007-10-31 14:19:09 -0600239 GLuint *width, GLuint *height)
240{
Brianef25c492007-10-31 14:19:09 -0600241 Status stat;
242
Brian Paul0bb852f2008-08-26 16:35:12 -0600243 pipe_mutex_lock(_xmesa_lock);
Brianef25c492007-10-31 14:19:09 -0600244 XSync(b->xm_visual->display, 0); /* added for Chromium */
Brian749d7232007-12-07 07:57:54 -0700245 stat = get_drawable_size(dpy, b->drawable, width, height);
Brian Paul0bb852f2008-08-26 16:35:12 -0600246 pipe_mutex_unlock(_xmesa_lock);
Brianef25c492007-10-31 14:19:09 -0600247
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 }
Brianef25c492007-10-31 14:19:09 -0600253}
254
Keith Whitwell2b960122009-01-08 15:33:32 +0000255#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
Brianef25c492007-10-31 14:19:09 -0600259
Brian20eae592007-12-12 14:55:57 -0700260/**
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 */
265static GLuint
266choose_pixel_format(XMesaVisual v)
267{
Keith Whitwell2b960122009-01-08 15:33:32 +0000268 boolean native_byte_order = (host_byte_order() ==
269 ImageByteOrder(v->display));
270
Brian20eae592007-12-12 14:55:57 -0700271 if ( GET_REDMASK(v) == 0x0000ff
272 && GET_GREENMASK(v) == 0x00ff00
273 && GET_BLUEMASK(v) == 0xff0000
274 && v->BitsPerPixel == 32) {
Keith Whitwell2b960122009-01-08 15:33:32 +0000275 if (native_byte_order) {
Brian20eae592007-12-12 14:55:57 -0700276 /* 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 Whitwell2b960122009-01-08 15:33:32 +0000287 if (native_byte_order) {
Brian20eae592007-12-12 14:55:57 -0700288 /* no byteswapping needed */
289 return PIPE_FORMAT_A8R8G8B8_UNORM;
290 }
291 else {
292 return PIPE_FORMAT_B8G8R8A8_UNORM;
293 }
294 }
Michel Dänzer9f0495a2009-08-31 10:22:19 +0200295 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 }
Brian20eae592007-12-12 14:55:57 -0700307 else if ( GET_REDMASK(v) == 0xf800
308 && GET_GREENMASK(v) == 0x07e0
309 && GET_BLUEMASK(v) == 0x001f
Keith Whitwell2b960122009-01-08 15:33:32 +0000310 && native_byte_order
Brian20eae592007-12-12 14:55:57 -0700311 && 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
Brianef25c492007-10-31 14:19:09 -0600321
322/**********************************************************************/
323/***** Linked list of XMesaBuffers *****/
324/**********************************************************************/
325
326XMesaBuffer 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 */
340static XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000341create_xmesa_buffer(Drawable d, BufferType type,
342 XMesaVisual vis, Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600343{
344 XMesaBuffer b;
Briane39f1b42007-11-05 15:59:55 -0700345 GLframebuffer *fb;
Brian20eae592007-12-12 14:55:57 -0700346 enum pipe_format colorFormat, depthFormat, stencilFormat;
Brianc6643022007-12-19 13:45:00 -0700347 uint width, height;
Brianef25c492007-10-31 14:19:09 -0600348
349 ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
350
351 b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
352 if (!b)
353 return NULL;
354
Brian749d7232007-12-07 07:57:54 -0700355 b->drawable = d;
356
Brianef25c492007-10-31 14:19:09 -0600357 b->xm_visual = vis;
358 b->type = type;
359 b->cmap = cmap;
360
Brian20eae592007-12-12 14:55:57 -0700361 /* 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 Paul284ab5a2008-09-10 18:22:00 -0600366#ifdef GALLIUM_CELL /* XXX temporary for Cell! */
367 else
368 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
369#else
Brian20eae592007-12-12 14:55:57 -0700370 else if (vis->mesa_visual.depthBits <= 16)
Keith Whitwell536092f2008-09-11 18:35:19 +0100371 depthFormat = PIPE_FORMAT_Z16_UNORM;
Brian20eae592007-12-12 14:55:57 -0700372 else if (vis->mesa_visual.depthBits <= 24)
373 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
374 else
375 depthFormat = PIPE_FORMAT_Z32_UNORM;
Brian Paul284ab5a2008-09-10 18:22:00 -0600376#endif
Brian20eae592007-12-12 14:55:57 -0700377
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 Paulc1c4ff22008-08-07 15:11:54 -0600385 /* no stencil */
Brian20eae592007-12-12 14:55:57 -0700386 stencilFormat = PIPE_FORMAT_NONE;
Brian Paulc1c4ff22008-08-07 15:11:54 -0600387 if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) {
388 /* use 24-bit Z, undefined stencil channel */
389 depthFormat = PIPE_FORMAT_X8Z24_UNORM;
390 }
Brian20eae592007-12-12 14:55:57 -0700391 }
392
393
Brianc6643022007-12-19 13:45:00 -0700394 get_drawable_size(vis->display, d, &width, &height);
395
Briane39f1b42007-11-05 15:59:55 -0700396 /*
397 * Create framebuffer, but we'll plug in our own renderbuffers below.
398 */
Brianc6643022007-12-19 13:45:00 -0700399 b->stfb = st_create_framebuffer(&vis->mesa_visual,
Brian20eae592007-12-12 14:55:57 -0700400 colorFormat, depthFormat, stencilFormat,
Brianc6643022007-12-19 13:45:00 -0700401 width, height,
Brian20eae592007-12-12 14:55:57 -0700402 (void *) b);
Briane39f1b42007-11-05 15:59:55 -0700403 fb = &b->stfb->Base;
404
Brianef25c492007-10-31 14:19:09 -0600405 /*
Brian749d7232007-12-07 07:57:54 -0700406 * Create scratch XImage for xmesa_display_surface()
Brianb7611772007-10-31 19:00:23 -0600407 */
Brian749d7232007-12-07 07:57:54 -0700408 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 */
Brianef25c492007-10-31 14:19:09 -0600416
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 */
434XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000435xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
Brianef25c492007-10-31 14:19:09 -0600436{
437 XMesaBuffer b;
Brian749d7232007-12-07 07:57:54 -0700438 for (b = XMesaBufferList; b; b = b->Next) {
439 if (b->xm_visual->display == dpy &&
440 b->cmap == cmap &&
441 b != notThis) {
Brianef25c492007-10-31 14:19:09 -0600442 return b;
443 }
444 }
445 return NULL;
446}
447
448
449/**
450 * Remove buffer from linked list, delete if no longer referenced.
451 */
452static void
453xmesa_free_buffer(XMesaBuffer buffer)
454{
455 XMesaBuffer prev = NULL, b;
456
457 for (b = XMesaBufferList; b; b = b->Next) {
458 if (b == buffer) {
Briane39f1b42007-11-05 15:59:55 -0700459 struct gl_framebuffer *fb = &buffer->stfb->Base;
Brianef25c492007-10-31 14:19:09 -0600460
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 */
Brian749d7232007-12-07 07:57:54 -0700473 b->drawable = 0;
474
475 buffer->tempImage->data = NULL;
476 XDestroyImage(buffer->tempImage);
Brianef25c492007-10-31 14:19:09 -0600477
478 /* Unreference. If count = zero we'll really delete the buffer */
Michel Dänzer317687c2009-03-09 13:27:54 +0100479 _mesa_reference_framebuffer(&fb, NULL);
Brianef25c492007-10-31 14:19:09 -0600480
Brianf44e2f12007-12-26 06:56:58 -0700481 XFreeGC(b->xm_visual->display, b->gc);
482
483 free(buffer);
484
Brianef25c492007-10-31 14:19:09 -0600485 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
Brianef25c492007-10-31 14:19:09 -0600495
496/**********************************************************************/
497/***** Misc Private Functions *****/
498/**********************************************************************/
499
500
501/**
Brianef25c492007-10-31 14:19:09 -0600502 * 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 */
511static GLboolean
512initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000513 GLboolean rgb_flag, Drawable window,
514 Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600515{
Brianef25c492007-10-31 14:19:09 -0600516 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) {
Brian749d7232007-12-07 07:57:54 -0700523 /* COLOR-INDEXED WINDOW: not supported*/
524 return GL_FALSE;
Brianef25c492007-10-31 14:19:09 -0600525 }
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;
Brian749d7232007-12-07 07:57:54 -0700531 if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
532 _mesa_warning(NULL,
533 "XMesa: RGB mode rendering not supported in given visual.\n");
Brianef25c492007-10-31 14:19:09 -0600534 return GL_FALSE;
535 }
536 v->mesa_visual.indexBits = 0;
Brian5935b162008-03-27 21:11:45 -0600537
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 }
Brianef25c492007-10-31 14:19:09 -0600545 }
546
Brianef25c492007-10-31 14:19:09 -0600547 /*
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);
Brianef25c492007-10-31 14:19:09 -0600554 _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
Keith Whitwell2b960122009-01-08 15:33:32 +0000555 _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth);
Brianef25c492007-10-31 14:19:09 -0600556 _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
557 }
558
559 if (b && window) {
Brianef25c492007-10-31 14:19:09 -0600560 /* these should have been set in create_xmesa_buffer */
Brian749d7232007-12-07 07:57:54 -0700561 ASSERT(b->drawable == window);
Brianef25c492007-10-31 14:19:09 -0600562
563 /* Setup for single/double buffering */
564 if (v->mesa_visual.doubleBufferMode) {
565 /* Double buffered */
Ian Romanickb09de962008-03-25 18:07:56 -0700566 b->shm = xmesa_check_for_xshm( v->display );
Brianef25c492007-10-31 14:19:09 -0600567 }
568
Brian749d7232007-12-07 07:57:54 -0700569 /* X11 graphics context */
Brianef25c492007-10-31 14:19:09 -0600570 b->gc = XCreateGC( v->display, window, 0, NULL );
Keith Whitwell2b960122009-01-08 15:33:32 +0000571 XSetFunction( v->display, b->gc, GXcopy );
Brianef25c492007-10-31 14:19:09 -0600572 }
573
574 return GL_TRUE;
575}
576
577
578
Brianef25c492007-10-31 14:19:09 -0600579#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 */
593static GLint
594xmesa_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 */
635PUBLIC
Keith Whitwell153b4d52009-01-08 15:23:51 +0000636XMesaVisual XMesaCreateVisual( Display *display,
637 XVisualInfo * visinfo,
Brianef25c492007-10-31 14:19:09 -0600638 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{
Brianef25c492007-10-31 14:19:09 -0600653 XMesaVisual v;
654 GLint red_bits, green_bits, blue_bits, alpha_bits;
655
Brianef25c492007-10-31 14:19:09 -0600656 /* 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 }
Brianef25c492007-10-31 14:19:09 -0600664
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 */
Brianef25c492007-10-31 14:19:09 -0600676 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
Brian Paul40636fe2009-09-03 17:16:19 -0600677 if (!v->visinfo) {
Brianef25c492007-10-31 14:19:09 -0600678 _mesa_free(v);
679 return NULL;
680 }
681 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
Brianef25c492007-10-31 14:19:09 -0600682
Brianef25c492007-10-31 14:19:09 -0600683 v->ximage_flag = ximage_flag;
684
Brianef25c492007-10-31 14:19:09 -0600685 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;
Brianef25c492007-10-31 14:19:09 -0600690
Keith Whitwell18ad0e32009-01-08 15:00:27 +0000691#if !(defined(__cplusplus) || defined(c_plusplus))
Brianef25c492007-10-31 14:19:09 -0600692 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 Whitwell2b960122009-01-08 15:33:32 +0000714 depth = v->visinfo->depth;
Brianef25c492007-10-31 14:19:09 -0600715 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 Whitwell2b960122009-01-08 15:33:32 +0000721 assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
Brianef25c492007-10-31 14:19:09 -0600722 }
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
743PUBLIC
744void XMesaDestroyVisual( XMesaVisual v )
745{
Brianef25c492007-10-31 14:19:09 -0600746 _mesa_free(v->visinfo);
Brianef25c492007-10-31 14:19:09 -0600747 _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 */
759PUBLIC
760XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
761{
762 static GLboolean firstTime = GL_TRUE;
José Fonseca67171ed2009-12-28 16:25:48 +0000763 struct pipe_context *_pipe = NULL;
Brian Paul7ec86522009-09-03 15:44:22 -0600764 struct pipe_context *pipe = NULL;
Brianef25c492007-10-31 14:19:09 -0600765 XMesaContext c;
766 GLcontext *mesaCtx;
Brian749d7232007-12-07 07:57:54 -0700767 uint pf;
Briane39f1b42007-11-05 15:59:55 -0700768
Brianef25c492007-10-31 14:19:09 -0600769 if (firstTime) {
Brian Paul0bb852f2008-08-26 16:35:12 -0600770 pipe_mutex_init(_xmesa_lock);
José Fonseca67171ed2009-12-28 16:25:48 +0000771 _screen = driver.create_pipe_screen();
772 screen = trace_screen_create( _screen );
Brianef25c492007-10-31 14:19:09 -0600773 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
Brian749d7232007-12-07 07:57:54 -0700781 pf = choose_pixel_format(v);
Brian0d1669f2007-12-07 08:24:56 -0700782 assert(pf);
Brian749d7232007-12-07 07:57:54 -0700783
Ian Romanickb09de962008-03-25 18:07:56 -0700784 c->xm_visual = v;
785 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
Thomas Hellstromd405ba32009-03-18 11:52:24 +0100786 c->xm_read_buffer = NULL;
787
Keith Whitwell002dfb12009-01-08 14:10:56 +0000788 if (screen == NULL)
789 goto fail;
Brianef25c492007-10-31 14:19:09 -0600790
José Fonseca67171ed2009-12-28 16:25:48 +0000791 _pipe = driver.create_pipe_context(_screen, (void *) c);
792 if (_pipe == NULL)
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100793 goto fail;
José Fonseca67171ed2009-12-28 16:25:48 +0000794 pipe = trace_context_create(screen, _pipe);
795 pipe->priv = c;
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100796
Keith Whitwell002dfb12009-01-08 14:10:56 +0000797 c->st = st_create_context(pipe,
798 &v->mesa_visual,
Brian91564ee2007-11-05 16:15:43 -0700799 share_list ? share_list->st : NULL);
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100800 if (c->st == NULL)
801 goto fail;
Keith Whitwell002dfb12009-01-08 14:10:56 +0000802
Briane39f1b42007-11-05 15:59:55 -0700803 mesaCtx = c->st->ctx;
804 c->st->ctx->DriverCtx = c;
Brianef25c492007-10-31 14:19:09 -0600805
Brianef25c492007-10-31 14:19:09 -0600806 return c;
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100807
Brian Paul40636fe2009-09-03 17:16:19 -0600808fail:
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100809 if (c->st)
810 st_destroy_context(c->st);
José Fonseca969ff9e2008-08-14 10:47:39 +0100811 else if (pipe)
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100812 pipe->destroy(pipe);
Keith Whitwell002dfb12009-01-08 14:10:56 +0000813
Brian Paul40636fe2009-09-03 17:16:19 -0600814 _mesa_free(c);
Keith Whitwell2258f6b2008-05-12 14:09:50 +0100815 return NULL;
Brianef25c492007-10-31 14:19:09 -0600816}
817
818
819
820PUBLIC
821void XMesaDestroyContext( XMesaContext c )
822{
Brian91564ee2007-11-05 16:15:43 -0700823 st_destroy_context(c->st);
Keith Whitwell002dfb12009-01-08 14:10:56 +0000824
José Fonsecaf9e14e02008-08-19 00:18:19 +0100825 /* FIXME: We should destroy the screen here, but if we do so, surfaces may
826 * outlive it, causing segfaults
Keith Whitwell002dfb12009-01-08 14:10:56 +0000827 struct pipe_screen *screen = c->st->pipe->screen;
José Fonseca969ff9e2008-08-14 10:47:39 +0100828 screen->destroy(screen);
José Fonsecaf9e14e02008-08-19 00:18:19 +0100829 */
Keith Whitwell002dfb12009-01-08 14:10:56 +0000830
Briane39f1b42007-11-05 15:59:55 -0700831 _mesa_free(c);
Brianef25c492007-10-31 14:19:09 -0600832}
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 */
843PUBLIC XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000844XMesaCreateWindowBuffer(XMesaVisual v, Window w)
Brianef25c492007-10-31 14:19:09 -0600845{
Brianef25c492007-10-31 14:19:09 -0600846 XWindowAttributes attr;
Brianef25c492007-10-31 14:19:09 -0600847 XMesaBuffer b;
Keith Whitwell153b4d52009-01-08 15:23:51 +0000848 Colormap cmap;
Brianef25c492007-10-31 14:19:09 -0600849 int depth;
850
851 assert(v);
852 assert(w);
853
854 /* Check that window depth matches visual depth */
Brianef25c492007-10-31 14:19:09 -0600855 XGetWindowAttributes( v->display, w, &attr );
856 depth = attr.depth;
Keith Whitwell2b960122009-01-08 15:33:32 +0000857 if (v->visinfo->depth != depth) {
Brianef25c492007-10-31 14:19:09 -0600858 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
Keith Whitwell2b960122009-01-08 15:33:32 +0000859 v->visinfo->depth, depth);
Brianef25c492007-10-31 14:19:09 -0600860 return NULL;
861 }
862
863 /* Find colormap */
Brianef25c492007-10-31 14:19:09 -0600864 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 }
Brianef25c492007-10-31 14:19:09 -0600873
Keith Whitwell153b4d52009-01-08 15:23:51 +0000874 b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600875 if (!b)
876 return NULL;
877
878 if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000879 (Drawable) w, cmap )) {
Brianef25c492007-10-31 14:19:09 -0600880 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 */
898PUBLIC XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000899XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
Brianef25c492007-10-31 14:19:09 -0600900{
901 XMesaBuffer b;
902
903 assert(v);
904
Keith Whitwell153b4d52009-01-08 15:23:51 +0000905 b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600906 if (!b)
907 return NULL;
908
909 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
Keith Whitwell153b4d52009-01-08 15:23:51 +0000910 (Drawable) p, cmap)) {
Brianef25c492007-10-31 14:19:09 -0600911 xmesa_free_buffer(b);
912 return NULL;
913 }
914
915 return b;
916}
917
918
919/**
920 * For GLX_EXT_texture_from_pixmap
921 */
922XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000923XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
924 Colormap cmap,
Brianef25c492007-10-31 14:19:09 -0600925 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 Whitwell153b4d52009-01-08 15:23:51 +0000933 b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
Brianef25c492007-10-31 14:19:09 -0600934 if (!b)
935 return NULL;
936
937 /* get pixmap size, update framebuffer/renderbuffer dims */
938 xmesa_get_window_size(v->display, b, &width, &height);
Briane39f1b42007-11-05 15:59:55 -0700939 _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
Brianef25c492007-10-31 14:19:09 -0600940
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 Whitwell153b4d52009-01-08 15:23:51 +0000971 (Drawable) p, cmap)) {
Brianef25c492007-10-31 14:19:09 -0600972 xmesa_free_buffer(b);
973 return NULL;
974 }
975
976 return b;
977}
978
979
980
981XMesaBuffer
Keith Whitwell153b4d52009-01-08 15:23:51 +0000982XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
Brianef25c492007-10-31 14:19:09 -0600983 unsigned int width, unsigned int height)
984{
Keith Whitwell153b4d52009-01-08 15:23:51 +0000985 Window root;
986 Drawable drawable; /* X Pixmap Drawable */
Brianef25c492007-10-31 14:19:09 -0600987 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;
Brianef25c492007-10-31 14:19:09 -06001007}
1008
1009
1010
1011/*
1012 * Deallocate an XMesaBuffer structure and all related info.
1013 */
1014PUBLIC void
1015XMesaDestroyBuffer(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 Whitwellee287632009-01-08 16:05:45 +00001026 * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
Brianef25c492007-10-31 14:19:09 -06001027 * 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 */
1030void
1031xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1032{
1033 GLuint width, height;
Brian749d7232007-12-07 07:57:54 -07001034 xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
Briane39f1b42007-11-05 15:59:55 -07001035 st_resize_framebuffer(drawBuffer->stfb, width, height);
Brianef25c492007-10-31 14:19:09 -06001036}
1037
1038
Brianef25c492007-10-31 14:19:09 -06001039
1040
1041/*
1042 * Bind buffer b to context c and make c the current rendering context.
1043 */
1044PUBLIC
1045GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1046 XMesaBuffer readBuffer )
1047{
Thomas Hellstromd405ba32009-03-18 11:52:24 +01001048 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
Brianef25c492007-10-31 14:19:09 -06001056 if (c) {
1057 if (!drawBuffer || !readBuffer)
1058 return GL_FALSE; /* must specify buffers! */
1059
Thomas Hellstromd405ba32009-03-18 11:52:24 +01001060 if (c == old_ctx &&
1061 c->xm_buffer == drawBuffer &&
1062 c->xm_read_buffer == readBuffer)
1063 return GL_TRUE;
Brianef25c492007-10-31 14:19:09 -06001064
1065 c->xm_buffer = drawBuffer;
Thomas Hellstromd405ba32009-03-18 11:52:24 +01001066 c->xm_read_buffer = readBuffer;
Brianef25c492007-10-31 14:19:09 -06001067
Briandbf6ece2007-12-19 08:50:35 -07001068 st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
1069
Brianef25c492007-10-31 14:19:09 -06001070 xmesa_check_and_update_buffer_size(c, drawBuffer);
1071 if (readBuffer != drawBuffer)
1072 xmesa_check_and_update_buffer_size(c, readBuffer);
1073
Brianef25c492007-10-31 14:19:09 -06001074 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1075 drawBuffer->wasCurrent = GL_TRUE;
1076 }
1077 else {
1078 /* Detach */
Briane39f1b42007-11-05 15:59:55 -07001079 st_make_current( NULL, NULL, NULL );
Thomas Hellstromd405ba32009-03-18 11:52:24 +01001080
Brianef25c492007-10-31 14:19:09 -06001081 }
1082 return GL_TRUE;
1083}
1084
1085
1086/*
1087 * Unbind the context c from its buffer.
1088 */
1089GLboolean XMesaUnbindContext( XMesaContext c )
1090{
1091 /* A no-op for XFree86 integration purposes */
1092 return GL_TRUE;
1093}
1094
1095
1096XMesaContext XMesaGetCurrentContext( void )
1097{
1098 GET_CURRENT_CONTEXT(ctx);
1099 if (ctx) {
Brian749d7232007-12-07 07:57:54 -07001100 XMesaContext xmesa = xmesa_context(ctx);
Brianef25c492007-10-31 14:19:09 -06001101 return xmesa;
1102 }
1103 else {
1104 return 0;
1105 }
1106}
1107
1108
Brianef25c492007-10-31 14:19:09 -06001109
Brian Paulb57b6c22009-05-01 12:28:57 -06001110/**
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.
Brianef25c492007-10-31 14:19:09 -06001113 */
1114PUBLIC
1115void XMesaSwapBuffers( XMesaBuffer b )
1116{
Brian Paulb57b6c22009-05-01 12:28:57 -06001117 struct pipe_surface *frontLeftSurf;
Brianef25c492007-10-31 14:19:09 -06001118
Brian Paulb57b6c22009-05-01 12:28:57 -06001119 st_swapbuffers(b->stfb, &frontLeftSurf, NULL);
Brianef25c492007-10-31 14:19:09 -06001120
Brian Paulb57b6c22009-05-01 12:28:57 -06001121 if (frontLeftSurf) {
José Fonseca67171ed2009-12-28 16:25:48 +00001122 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 Paulb57b6c22009-05-01 12:28:57 -06001128 driver.display_surface(b, frontLeftSurf);
Brianef25c492007-10-31 14:19:09 -06001129 }
Brian749d7232007-12-07 07:57:54 -07001130
1131 xmesa_check_and_update_buffer_size(NULL, b);
Brianef25c492007-10-31 14:19:09 -06001132}
1133
1134
1135
1136/*
1137 * Copy sub-region of back buffer to front buffer
1138 */
1139void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1140{
Alan Hourihaneb0d0e532009-01-23 16:04:57 +00001141 struct pipe_surface *surf_front;
1142 struct pipe_surface *surf_back;
Brian749d7232007-12-07 07:57:54 -07001143 struct pipe_context *pipe = NULL; /* XXX fix */
Brianef25c492007-10-31 14:19:09 -06001144
Alan Hourihaneb0d0e532009-01-23 16:04:57 +00001145 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
Brian749d7232007-12-07 07:57:54 -07001148 if (!surf_front || !surf_back)
1149 return;
Briane39f1b42007-11-05 15:59:55 -07001150
Brian749d7232007-12-07 07:57:54 -07001151 pipe->surface_copy(pipe,
1152 surf_front, x, y, /* dest */
1153 surf_back, x, y, /* src */
1154 width, height);
Brianef25c492007-10-31 14:19:09 -06001155}
1156
1157
Brianef25c492007-10-31 14:19:09 -06001158
Brianef25c492007-10-31 14:19:09 -06001159void XMesaFlush( XMesaContext c )
1160{
Brian749d7232007-12-07 07:57:54 -07001161 if (c && c->xm_visual->display) {
Brian Paul6f33b772008-08-27 11:29:26 -06001162 st_finish(c->st);
Brian749d7232007-12-07 07:57:54 -07001163 XSync( c->xm_visual->display, False );
Brianef25c492007-10-31 14:19:09 -06001164 }
1165}
1166
1167
1168
Brianef25c492007-10-31 14:19:09 -06001169
1170
Keith Whitwell153b4d52009-01-08 15:23:51 +00001171XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
Brianef25c492007-10-31 14:19:09 -06001172{
1173 XMesaBuffer b;
Brian Paul40636fe2009-09-03 17:16:19 -06001174 for (b = XMesaBufferList; b; b = b->Next) {
Brian749d7232007-12-07 07:57:54 -07001175 if (b->drawable == d && b->xm_visual->display == dpy) {
Brianef25c492007-10-31 14:19:09 -06001176 return b;
1177 }
1178 }
1179 return NULL;
1180}
1181
1182
1183/**
1184 * Free/destroy all XMesaBuffers associated with given display.
1185 */
Keith Whitwell153b4d52009-01-08 15:23:51 +00001186void xmesa_destroy_buffers_on_display(Display *dpy)
Brianef25c492007-10-31 14:19:09 -06001187{
1188 XMesaBuffer b, next;
1189 for (b = XMesaBufferList; b; b = next) {
1190 next = b->Next;
Brian749d7232007-12-07 07:57:54 -07001191 if (b->xm_visual->display == dpy) {
Brianef25c492007-10-31 14:19:09 -06001192 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 */
1202void XMesaGarbageCollect( void )
1203{
1204 XMesaBuffer b, next;
1205 for (b=XMesaBufferList; b; b=next) {
1206 next = b->Next;
Brian749d7232007-12-07 07:57:54 -07001207 if (b->xm_visual &&
1208 b->xm_visual->display &&
1209 b->drawable &&
1210 b->type == WINDOW) {
Brian749d7232007-12-07 07:57:54 -07001211 XSync(b->xm_visual->display, False);
1212 if (!window_exists( b->xm_visual->display, b->drawable )) {
Brianef25c492007-10-31 14:19:09 -06001213 /* found a dead window, free the ancillary info */
1214 XMesaDestroyBuffer( b );
1215 }
Brianef25c492007-10-31 14:19:09 -06001216 }
1217 }
1218}
1219
1220
Brianef25c492007-10-31 14:19:09 -06001221
1222
1223PUBLIC void
Keith Whitwell153b4d52009-01-08 15:23:51 +00001224XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
Brianef25c492007-10-31 14:19:09 -06001225 const int *attrib_list)
1226{
Brianef25c492007-10-31 14:19:09 -06001227}
1228
1229
1230
1231PUBLIC void
Keith Whitwell153b4d52009-01-08 15:23:51 +00001232XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
Brianef25c492007-10-31 14:19:09 -06001233{
Brianef25c492007-10-31 14:19:09 -06001234}
1235