gallium: remove unneeded st->haveFramebufferSurfaces field.
[mesa.git] / src / gallium / winsys / xlib / xm_api.c
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
51 * into the XImage's buffer then the pixel must be byte swapped first.
52 *
53 */
54
55 #ifdef __CYGWIN__
56 #undef WIN32
57 #undef __WIN32__
58 #endif
59
60 #include "glxheader.h"
61 #include "GL/xmesa.h"
62 #include "xmesaP.h"
63 #include "main/context.h"
64 #include "main/framebuffer.h"
65 #include "glapi/glthread.h"
66
67 #include "state_tracker/st_public.h"
68 #include "state_tracker/st_context.h"
69 #include "pipe/p_defines.h"
70 #include "pipe/p_context.h"
71
72 #include "xm_winsys_aub.h"
73
74 /**
75 * Global X driver lock
76 */
77 _glthread_Mutex _xmesa_lock;
78
79
80 int xmesa_mode;
81
82
83 /**********************************************************************/
84 /***** X Utility Functions *****/
85 /**********************************************************************/
86
87
88 /**
89 * Return the host's byte order as LSBFirst or MSBFirst ala X.
90 */
91 #ifndef XFree86Server
92 static int host_byte_order( void )
93 {
94 int i = 1;
95 char *cptr = (char *) &i;
96 return (*cptr==1) ? LSBFirst : MSBFirst;
97 }
98 #endif
99
100
101 /**
102 * Check if the X Shared Memory extension is available.
103 * Return: 0 = not available
104 * 1 = shared XImage support available
105 * 2 = shared Pixmap support available also
106 */
107 int xmesa_check_for_xshm( XMesaDisplay *display )
108 {
109 #if defined(USE_XSHM) && !defined(XFree86Server)
110 int major, minor, ignore;
111 Bool pixmaps;
112
113 if (getenv("MESA_NOSHM")) {
114 return 0;
115 }
116
117 if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
118 if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
119 return (pixmaps==True) ? 2 : 1;
120 }
121 else {
122 return 0;
123 }
124 }
125 else {
126 return 0;
127 }
128 #else
129 /* No XSHM support */
130 return 0;
131 #endif
132 }
133
134
135 /**
136 * Return the true number of bits per pixel for XImages.
137 * For example, if we request a 24-bit deep visual we may actually need/get
138 * 32bpp XImages. This function returns the appropriate bpp.
139 * Input: dpy - the X display
140 * visinfo - desribes the visual to be used for XImages
141 * Return: true number of bits per pixel for XImages
142 */
143 static int
144 bits_per_pixel( XMesaVisual xmv )
145 {
146 #ifdef XFree86Server
147 const int depth = xmv->nplanes;
148 int i;
149 assert(depth > 0);
150 for (i = 0; i < screenInfo.numPixmapFormats; i++) {
151 if (screenInfo.formats[i].depth == depth)
152 return screenInfo.formats[i].bitsPerPixel;
153 }
154 return depth; /* should never get here, but this should be safe */
155 #else
156 XMesaDisplay *dpy = xmv->display;
157 XMesaVisualInfo visinfo = xmv->visinfo;
158 XMesaImage *img;
159 int bitsPerPixel;
160 /* Create a temporary XImage */
161 img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
162 ZPixmap, 0, /*format, offset*/
163 (char*) MALLOC(8), /*data*/
164 1, 1, /*width, height*/
165 32, /*bitmap_pad*/
166 0 /*bytes_per_line*/
167 );
168 assert(img);
169 /* grab the bits/pixel value */
170 bitsPerPixel = img->bits_per_pixel;
171 /* free the XImage */
172 _mesa_free( img->data );
173 img->data = NULL;
174 XMesaDestroyImage( img );
175 return bitsPerPixel;
176 #endif
177 }
178
179
180
181 /*
182 * Determine if a given X window ID is valid (window exists).
183 * Do this by calling XGetWindowAttributes() for the window and
184 * checking if we catch an X error.
185 * Input: dpy - the display
186 * win - the window to check for existance
187 * Return: GL_TRUE - window exists
188 * GL_FALSE - window doesn't exist
189 */
190 #ifndef XFree86Server
191 static GLboolean WindowExistsFlag;
192
193 static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
194 {
195 (void) dpy;
196 if (xerr->error_code == BadWindow) {
197 WindowExistsFlag = GL_FALSE;
198 }
199 return 0;
200 }
201
202 static GLboolean window_exists( XMesaDisplay *dpy, Window win )
203 {
204 XWindowAttributes wa;
205 int (*old_handler)( XMesaDisplay*, XErrorEvent* );
206 WindowExistsFlag = GL_TRUE;
207 old_handler = XSetErrorHandler(window_exists_err_handler);
208 XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
209 XSetErrorHandler(old_handler);
210 return WindowExistsFlag;
211 }
212
213 static Status
214 get_drawable_size( XMesaDisplay *dpy, Drawable d, uint *width, uint *height )
215 {
216 Window root;
217 Status stat;
218 int xpos, ypos;
219 unsigned int w, h, bw, depth;
220 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
221 *width = w;
222 *height = h;
223 return stat;
224 }
225 #endif
226
227
228 /**
229 * Return the size of the window (or pixmap) that corresponds to the
230 * given XMesaBuffer.
231 * \param width returns width in pixels
232 * \param height returns height in pixels
233 */
234 static void
235 xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
236 GLuint *width, GLuint *height)
237 {
238 #ifdef XFree86Server
239 *width = MIN2(b->drawable->width, MAX_WIDTH);
240 *height = MIN2(b->drawable->height, MAX_HEIGHT);
241 #else
242 Status stat;
243
244 _glthread_LOCK_MUTEX(_xmesa_lock);
245 XSync(b->xm_visual->display, 0); /* added for Chromium */
246 stat = get_drawable_size(dpy, b->drawable, width, height);
247 _glthread_UNLOCK_MUTEX(_xmesa_lock);
248
249 if (!stat) {
250 /* probably querying a window that's recently been destroyed */
251 _mesa_warning(NULL, "XGetGeometry failed!\n");
252 *width = *height = 1;
253 }
254 #endif
255 }
256
257
258 /**
259 * Choose the pixel format for the given visual.
260 * This will tell the gallium driver how to pack pixel data into
261 * drawing surfaces.
262 */
263 static GLuint
264 choose_pixel_format(XMesaVisual v)
265 {
266 if ( GET_REDMASK(v) == 0x0000ff
267 && GET_GREENMASK(v) == 0x00ff00
268 && GET_BLUEMASK(v) == 0xff0000
269 && v->BitsPerPixel == 32) {
270 if (CHECK_BYTE_ORDER(v)) {
271 /* no byteswapping needed */
272 return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */;
273 }
274 else {
275 return PIPE_FORMAT_R8G8B8A8_UNORM;
276 }
277 }
278 else if ( GET_REDMASK(v) == 0xff0000
279 && GET_GREENMASK(v) == 0x00ff00
280 && GET_BLUEMASK(v) == 0x0000ff
281 && v->BitsPerPixel == 32) {
282 if (CHECK_BYTE_ORDER(v)) {
283 /* no byteswapping needed */
284 return PIPE_FORMAT_A8R8G8B8_UNORM;
285 }
286 else {
287 return PIPE_FORMAT_B8G8R8A8_UNORM;
288 }
289 }
290 else if ( GET_REDMASK(v) == 0xf800
291 && GET_GREENMASK(v) == 0x07e0
292 && GET_BLUEMASK(v) == 0x001f
293 && CHECK_BYTE_ORDER(v)
294 && v->BitsPerPixel == 16) {
295 /* 5-6-5 RGB */
296 return PIPE_FORMAT_R5G6B5_UNORM;
297 }
298
299 assert(0);
300 return 0;
301 }
302
303
304
305 /**********************************************************************/
306 /***** Linked list of XMesaBuffers *****/
307 /**********************************************************************/
308
309 XMesaBuffer XMesaBufferList = NULL;
310
311
312 /**
313 * Allocate a new XMesaBuffer object which corresponds to the given drawable.
314 * Note that XMesaBuffer is derived from GLframebuffer.
315 * The new XMesaBuffer will not have any size (Width=Height=0).
316 *
317 * \param d the corresponding X drawable (window or pixmap)
318 * \param type either WINDOW, PIXMAP or PBUFFER, describing d
319 * \param vis the buffer's visual
320 * \param cmap the window's colormap, if known.
321 * \return new XMesaBuffer or NULL if any problem
322 */
323 static XMesaBuffer
324 create_xmesa_buffer(XMesaDrawable d, BufferType type,
325 XMesaVisual vis, XMesaColormap cmap)
326 {
327 XMesaBuffer b;
328 GLframebuffer *fb;
329 enum pipe_format colorFormat, depthFormat, stencilFormat;
330 uint width, height;
331
332 ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
333
334 b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
335 if (!b)
336 return NULL;
337
338 b->drawable = d;
339
340 b->xm_visual = vis;
341 b->type = type;
342 b->cmap = cmap;
343
344 /* determine PIPE_FORMATs for buffers */
345 colorFormat = choose_pixel_format(vis);
346
347 if (vis->mesa_visual.depthBits == 0)
348 depthFormat = PIPE_FORMAT_NONE;
349 else if (vis->mesa_visual.depthBits <= 16)
350 depthFormat = PIPE_FORMAT_Z16_UNORM;
351 else if (vis->mesa_visual.depthBits <= 24)
352 depthFormat = PIPE_FORMAT_S8Z24_UNORM;
353 else
354 depthFormat = PIPE_FORMAT_Z32_UNORM;
355
356 if (vis->mesa_visual.stencilBits == 8) {
357 if (depthFormat == PIPE_FORMAT_S8Z24_UNORM)
358 stencilFormat = depthFormat;
359 else
360 stencilFormat = PIPE_FORMAT_S8_UNORM;
361 }
362 else {
363 stencilFormat = PIPE_FORMAT_NONE;
364 }
365
366
367 get_drawable_size(vis->display, d, &width, &height);
368
369 /*
370 * Create framebuffer, but we'll plug in our own renderbuffers below.
371 */
372 b->stfb = st_create_framebuffer(&vis->mesa_visual,
373 colorFormat, depthFormat, stencilFormat,
374 width, height,
375 (void *) b);
376 fb = &b->stfb->Base;
377
378 /*
379 * Create scratch XImage for xmesa_display_surface()
380 */
381 b->tempImage = XCreateImage(vis->display,
382 vis->visinfo->visual,
383 vis->visinfo->depth,
384 ZPixmap, 0, /* format, offset */
385 NULL, /* data */
386 0, 0, /* size */
387 32, /* bitmap_pad */
388 0); /* bytes_per_line */
389
390 /* GLX_EXT_texture_from_pixmap */
391 b->TextureTarget = 0;
392 b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
393 b->TextureMipmap = 0;
394
395 /* insert buffer into linked list */
396 b->Next = XMesaBufferList;
397 XMesaBufferList = b;
398
399 return b;
400 }
401
402
403 /**
404 * Find an XMesaBuffer by matching X display and colormap but NOT matching
405 * the notThis buffer.
406 */
407 XMesaBuffer
408 xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
409 {
410 XMesaBuffer b;
411 for (b = XMesaBufferList; b; b = b->Next) {
412 if (b->xm_visual->display == dpy &&
413 b->cmap == cmap &&
414 b != notThis) {
415 return b;
416 }
417 }
418 return NULL;
419 }
420
421
422 /**
423 * Remove buffer from linked list, delete if no longer referenced.
424 */
425 static void
426 xmesa_free_buffer(XMesaBuffer buffer)
427 {
428 XMesaBuffer prev = NULL, b;
429
430 for (b = XMesaBufferList; b; b = b->Next) {
431 if (b == buffer) {
432 struct gl_framebuffer *fb = &buffer->stfb->Base;
433
434 /* unlink buffer from list */
435 if (prev)
436 prev->Next = buffer->Next;
437 else
438 XMesaBufferList = buffer->Next;
439
440 /* mark as delete pending */
441 fb->DeletePending = GL_TRUE;
442
443 /* Since the X window for the XMesaBuffer is going away, we don't
444 * want to dereference this pointer in the future.
445 */
446 b->drawable = 0;
447
448 buffer->tempImage->data = NULL;
449 XDestroyImage(buffer->tempImage);
450
451 /* Unreference. If count = zero we'll really delete the buffer */
452 _mesa_unreference_framebuffer(&fb);
453
454 XFreeGC(b->xm_visual->display, b->gc);
455
456 free(buffer);
457
458 return;
459 }
460 /* continue search */
461 prev = b;
462 }
463 /* buffer not found in XMesaBufferList */
464 _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
465 }
466
467
468
469 /**********************************************************************/
470 /***** Misc Private Functions *****/
471 /**********************************************************************/
472
473
474 /**
475 * When a context is bound for the first time, we can finally finish
476 * initializing the context's visual and buffer information.
477 * \param v the XMesaVisual to initialize
478 * \param b the XMesaBuffer to initialize (may be NULL)
479 * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode
480 * \param window the window/pixmap we're rendering into
481 * \param cmap the colormap associated with the window/pixmap
482 * \return GL_TRUE=success, GL_FALSE=failure
483 */
484 static GLboolean
485 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
486 GLboolean rgb_flag, XMesaDrawable window,
487 XMesaColormap cmap)
488 {
489 #ifdef XFree86Server
490 int client = (window) ? CLIENT_ID(window->id) : 0;
491 #endif
492
493 ASSERT(!b || b->xm_visual == v);
494
495 /* Save true bits/pixel */
496 v->BitsPerPixel = bits_per_pixel(v);
497 assert(v->BitsPerPixel > 0);
498
499 if (rgb_flag == GL_FALSE) {
500 /* COLOR-INDEXED WINDOW: not supported*/
501 return GL_FALSE;
502 }
503 else {
504 /* RGB WINDOW:
505 * We support RGB rendering into almost any kind of visual.
506 */
507 const int xclass = v->mesa_visual.visualType;
508 if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
509 _mesa_warning(NULL,
510 "XMesa: RGB mode rendering not supported in given visual.\n");
511 return GL_FALSE;
512 }
513 v->mesa_visual.indexBits = 0;
514
515 if (v->BitsPerPixel == 32) {
516 /* We use XImages for all front/back buffers. If an X Window or
517 * X Pixmap is 32bpp, there's no guarantee that the alpha channel
518 * will be preserved. For XImages we're in luck.
519 */
520 v->mesa_visual.alphaBits = 8;
521 }
522 }
523
524 /*
525 * If MESA_INFO env var is set print out some debugging info
526 * which can help Brian figure out what's going on when a user
527 * reports bugs.
528 */
529 if (_mesa_getenv("MESA_INFO")) {
530 _mesa_printf("X/Mesa visual = %p\n", (void *) v);
531 _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
532 _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
533 _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
534 }
535
536 if (b && window) {
537 /* these should have been set in create_xmesa_buffer */
538 ASSERT(b->drawable == window);
539
540 /* Setup for single/double buffering */
541 if (v->mesa_visual.doubleBufferMode) {
542 /* Double buffered */
543 b->shm = xmesa_check_for_xshm( v->display );
544 }
545
546 /* X11 graphics context */
547 #ifdef XFree86Server
548 b->gc = CreateScratchGC(v->display, window->depth);
549 #else
550 b->gc = XCreateGC( v->display, window, 0, NULL );
551 #endif
552 XMesaSetFunction( v->display, b->gc, GXcopy );
553 }
554
555 return GL_TRUE;
556 }
557
558
559
560 #define NUM_VISUAL_TYPES 6
561
562 /**
563 * Convert an X visual type to a GLX visual type.
564 *
565 * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
566 * to be converted.
567 * \return If \c visualType is a valid X visual type, a GLX visual type will
568 * be returned. Otherwise \c GLX_NONE will be returned.
569 *
570 * \note
571 * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
572 * DRI CVS tree.
573 */
574 static GLint
575 xmesa_convert_from_x_visual_type( int visualType )
576 {
577 static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
578 GLX_STATIC_GRAY, GLX_GRAY_SCALE,
579 GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
580 GLX_TRUE_COLOR, GLX_DIRECT_COLOR
581 };
582
583 return ( (unsigned) visualType < NUM_VISUAL_TYPES )
584 ? glx_visual_types[ visualType ] : GLX_NONE;
585 }
586
587
588 /**********************************************************************/
589 /***** Public Functions *****/
590 /**********************************************************************/
591
592
593 /*
594 * Create a new X/Mesa visual.
595 * Input: display - X11 display
596 * visinfo - an XVisualInfo pointer
597 * rgb_flag - GL_TRUE = RGB mode,
598 * GL_FALSE = color index mode
599 * alpha_flag - alpha buffer requested?
600 * db_flag - GL_TRUE = double-buffered,
601 * GL_FALSE = single buffered
602 * stereo_flag - stereo visual?
603 * ximage_flag - GL_TRUE = use an XImage for back buffer,
604 * GL_FALSE = use an off-screen pixmap for back buffer
605 * depth_size - requested bits/depth values, or zero
606 * stencil_size - requested bits/stencil values, or zero
607 * accum_red_size - requested bits/red accum values, or zero
608 * accum_green_size - requested bits/green accum values, or zero
609 * accum_blue_size - requested bits/blue accum values, or zero
610 * accum_alpha_size - requested bits/alpha accum values, or zero
611 * num_samples - number of samples/pixel if multisampling, or zero
612 * level - visual level, usually 0
613 * visualCaveat - ala the GLX extension, usually GLX_NONE
614 * Return; a new XMesaVisual or 0 if error.
615 */
616 PUBLIC
617 XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
618 XMesaVisualInfo visinfo,
619 GLboolean rgb_flag,
620 GLboolean alpha_flag,
621 GLboolean db_flag,
622 GLboolean stereo_flag,
623 GLboolean ximage_flag,
624 GLint depth_size,
625 GLint stencil_size,
626 GLint accum_red_size,
627 GLint accum_green_size,
628 GLint accum_blue_size,
629 GLint accum_alpha_size,
630 GLint num_samples,
631 GLint level,
632 GLint visualCaveat )
633 {
634 XMesaVisual v;
635 GLint red_bits, green_bits, blue_bits, alpha_bits;
636
637 #ifndef XFree86Server
638 /* For debugging only */
639 if (_mesa_getenv("MESA_XSYNC")) {
640 /* This makes debugging X easier.
641 * In your debugger, set a breakpoint on _XError to stop when an
642 * X protocol error is generated.
643 */
644 XSynchronize( display, 1 );
645 }
646 #endif
647
648 v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
649 if (!v) {
650 return NULL;
651 }
652
653 v->display = display;
654
655 /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
656 * the struct but we may need some of the information contained in it
657 * at a later time.
658 */
659 #ifndef XFree86Server
660 v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
661 if(!v->visinfo) {
662 _mesa_free(v);
663 return NULL;
664 }
665 MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
666 #endif
667
668 v->ximage_flag = ximage_flag;
669
670 #ifdef XFree86Server
671 /* We could calculate these values by ourselves. nplanes is either the sum
672 * of the red, green, and blue bits or the number index bits.
673 * ColormapEntries is either (1U << index_bits) or
674 * (1U << max(redBits, greenBits, blueBits)).
675 */
676 assert(visinfo->nplanes > 0);
677 v->nplanes = visinfo->nplanes;
678 v->ColormapEntries = visinfo->ColormapEntries;
679
680 v->mesa_visual.redMask = visinfo->redMask;
681 v->mesa_visual.greenMask = visinfo->greenMask;
682 v->mesa_visual.blueMask = visinfo->blueMask;
683 v->mesa_visual.visualID = visinfo->vid;
684 v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
685 #else
686 v->mesa_visual.redMask = visinfo->red_mask;
687 v->mesa_visual.greenMask = visinfo->green_mask;
688 v->mesa_visual.blueMask = visinfo->blue_mask;
689 v->mesa_visual.visualID = visinfo->visualid;
690 v->mesa_visual.screen = visinfo->screen;
691 #endif
692
693 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
694 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
695 #else
696 v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
697 #endif
698
699 v->mesa_visual.visualRating = visualCaveat;
700
701 if (alpha_flag)
702 v->mesa_visual.alphaBits = 8;
703
704 (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
705
706 {
707 const int xclass = v->mesa_visual.visualType;
708 if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
709 red_bits = _mesa_bitcount(GET_REDMASK(v));
710 green_bits = _mesa_bitcount(GET_GREENMASK(v));
711 blue_bits = _mesa_bitcount(GET_BLUEMASK(v));
712 }
713 else {
714 /* this is an approximation */
715 int depth;
716 depth = GET_VISUAL_DEPTH(v);
717 red_bits = depth / 3;
718 depth -= red_bits;
719 green_bits = depth / 2;
720 depth -= green_bits;
721 blue_bits = depth;
722 alpha_bits = 0;
723 assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
724 }
725 alpha_bits = v->mesa_visual.alphaBits;
726 }
727
728 _mesa_initialize_visual( &v->mesa_visual,
729 rgb_flag, db_flag, stereo_flag,
730 red_bits, green_bits,
731 blue_bits, alpha_bits,
732 v->mesa_visual.indexBits,
733 depth_size,
734 stencil_size,
735 accum_red_size, accum_green_size,
736 accum_blue_size, accum_alpha_size,
737 0 );
738
739 /* XXX minor hack */
740 v->mesa_visual.level = level;
741 return v;
742 }
743
744
745 PUBLIC
746 void XMesaDestroyVisual( XMesaVisual v )
747 {
748 #ifndef XFree86Server
749 _mesa_free(v->visinfo);
750 #endif
751 _mesa_free(v);
752 }
753
754
755
756 /**
757 * Create a new XMesaContext.
758 * \param v the XMesaVisual
759 * \param share_list another XMesaContext with which to share display
760 * lists or NULL if no sharing is wanted.
761 * \return an XMesaContext or NULL if error.
762 */
763 PUBLIC
764 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
765 {
766 static GLboolean firstTime = GL_TRUE;
767 struct pipe_context *pipe;
768 XMesaContext c;
769 GLcontext *mesaCtx;
770 uint pf;
771
772 if (firstTime) {
773 _glthread_INIT_MUTEX(_xmesa_lock);
774 firstTime = GL_FALSE;
775 }
776
777 /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
778 c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
779 if (!c)
780 return NULL;
781
782 pf = choose_pixel_format(v);
783 assert(pf);
784
785 c->xm_visual = v;
786 c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */
787
788 if (!getenv("XM_AUB")) {
789 xmesa_mode = XMESA_SOFTPIPE;
790 pipe = xmesa_create_pipe_context( c, pf );
791 }
792 else {
793 xmesa_mode = XMESA_AUB;
794 pipe = xmesa_create_i965simple(xmesa_get_pipe_winsys_aub(v));
795 }
796
797 c->st = st_create_context(pipe, &v->mesa_visual,
798 share_list ? share_list->st : NULL);
799 mesaCtx = c->st->ctx;
800 c->st->ctx->DriverCtx = c;
801
802 #if 00
803 _mesa_enable_sw_extensions(mesaCtx);
804 _mesa_enable_1_3_extensions(mesaCtx);
805 _mesa_enable_1_4_extensions(mesaCtx);
806 _mesa_enable_1_5_extensions(mesaCtx);
807 _mesa_enable_2_0_extensions(mesaCtx);
808 #endif
809
810 #ifdef XFree86Server
811 /* If we're running in the X server, do bounds checking to prevent
812 * segfaults and server crashes!
813 */
814 mesaCtx->Const.CheckArrayBounds = GL_TRUE;
815 #endif
816
817 return c;
818 }
819
820
821
822 PUBLIC
823 void XMesaDestroyContext( XMesaContext c )
824 {
825 st_destroy_context(c->st);
826 _mesa_free(c);
827 }
828
829
830
831 /**
832 * Private function for creating an XMesaBuffer which corresponds to an
833 * X window or pixmap.
834 * \param v the window's XMesaVisual
835 * \param w the window we're wrapping
836 * \return new XMesaBuffer or NULL if error
837 */
838 PUBLIC XMesaBuffer
839 XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
840 {
841 #ifndef XFree86Server
842 XWindowAttributes attr;
843 #endif
844 XMesaBuffer b;
845 XMesaColormap cmap;
846 int depth;
847
848 assert(v);
849 assert(w);
850
851 /* Check that window depth matches visual depth */
852 #ifdef XFree86Server
853 depth = ((XMesaDrawable)w)->depth;
854 #else
855 XGetWindowAttributes( v->display, w, &attr );
856 depth = attr.depth;
857 #endif
858 if (GET_VISUAL_DEPTH(v) != depth) {
859 _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
860 GET_VISUAL_DEPTH(v), depth);
861 return NULL;
862 }
863
864 /* Find colormap */
865 #ifdef XFree86Server
866 cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
867 #else
868 if (attr.colormap) {
869 cmap = attr.colormap;
870 }
871 else {
872 _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
873 /* this is weird, a window w/out a colormap!? */
874 /* OK, let's just allocate a new one and hope for the best */
875 cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
876 }
877 #endif
878
879 b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
880 if (!b)
881 return NULL;
882
883 if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
884 (XMesaDrawable) w, cmap )) {
885 xmesa_free_buffer(b);
886 return NULL;
887 }
888
889 return b;
890 }
891
892
893
894 /**
895 * Create a new XMesaBuffer from an X pixmap.
896 *
897 * \param v the XMesaVisual
898 * \param p the pixmap
899 * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
900 * \c GLX_DIRECT_COLOR visual for the pixmap
901 * \returns new XMesaBuffer or NULL if error
902 */
903 PUBLIC XMesaBuffer
904 XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
905 {
906 XMesaBuffer b;
907
908 assert(v);
909
910 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
911 if (!b)
912 return NULL;
913
914 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
915 (XMesaDrawable) p, cmap)) {
916 xmesa_free_buffer(b);
917 return NULL;
918 }
919
920 return b;
921 }
922
923
924 /**
925 * For GLX_EXT_texture_from_pixmap
926 */
927 XMesaBuffer
928 XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
929 XMesaColormap cmap,
930 int format, int target, int mipmap)
931 {
932 GET_CURRENT_CONTEXT(ctx);
933 XMesaBuffer b;
934 GLuint width, height;
935
936 assert(v);
937
938 b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
939 if (!b)
940 return NULL;
941
942 /* get pixmap size, update framebuffer/renderbuffer dims */
943 xmesa_get_window_size(v->display, b, &width, &height);
944 _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
945
946 if (target == 0) {
947 /* examine dims */
948 if (ctx->Extensions.ARB_texture_non_power_of_two) {
949 target = GLX_TEXTURE_2D_EXT;
950 }
951 else if ( _mesa_bitcount(width) == 1
952 && _mesa_bitcount(height) == 1) {
953 /* power of two size */
954 if (height == 1) {
955 target = GLX_TEXTURE_1D_EXT;
956 }
957 else {
958 target = GLX_TEXTURE_2D_EXT;
959 }
960 }
961 else if (ctx->Extensions.NV_texture_rectangle) {
962 target = GLX_TEXTURE_RECTANGLE_EXT;
963 }
964 else {
965 /* non power of two textures not supported */
966 XMesaDestroyBuffer(b);
967 return 0;
968 }
969 }
970
971 b->TextureTarget = target;
972 b->TextureFormat = format;
973 b->TextureMipmap = mipmap;
974
975 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
976 (XMesaDrawable) p, cmap)) {
977 xmesa_free_buffer(b);
978 return NULL;
979 }
980
981 return b;
982 }
983
984
985
986 XMesaBuffer
987 XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
988 unsigned int width, unsigned int height)
989 {
990 #ifndef XFree86Server
991 XMesaWindow root;
992 XMesaDrawable drawable; /* X Pixmap Drawable */
993 XMesaBuffer b;
994
995 /* allocate pixmap for front buffer */
996 root = RootWindow( v->display, v->visinfo->screen );
997 drawable = XCreatePixmap(v->display, root, width, height,
998 v->visinfo->depth);
999 if (!drawable)
1000 return NULL;
1001
1002 b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1003 if (!b)
1004 return NULL;
1005
1006 if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
1007 drawable, cmap)) {
1008 xmesa_free_buffer(b);
1009 return NULL;
1010 }
1011
1012 return b;
1013 #else
1014 return 0;
1015 #endif
1016 }
1017
1018
1019
1020 /*
1021 * Deallocate an XMesaBuffer structure and all related info.
1022 */
1023 PUBLIC void
1024 XMesaDestroyBuffer(XMesaBuffer b)
1025 {
1026 xmesa_free_buffer(b);
1027 }
1028
1029
1030 /**
1031 * Query the current window size and update the corresponding GLframebuffer
1032 * and all attached renderbuffers.
1033 * Called when:
1034 * 1. the first time a buffer is bound to a context.
1035 * 2. from the XMesaResizeBuffers() API function.
1036 * 3. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too...
1037 * Note: it's possible (and legal) for xmctx to be NULL. That can happen
1038 * when resizing a buffer when no rendering context is bound.
1039 */
1040 void
1041 xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
1042 {
1043 GLuint width, height;
1044 xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
1045 st_resize_framebuffer(drawBuffer->stfb, width, height);
1046 }
1047
1048
1049 /*
1050 * Bind buffer b to context c and make c the current rendering context.
1051 */
1052 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
1053 {
1054 return XMesaMakeCurrent2( c, b, b );
1055 }
1056
1057
1058 /*
1059 * Bind buffer b to context c and make c the current rendering context.
1060 */
1061 PUBLIC
1062 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1063 XMesaBuffer readBuffer )
1064 {
1065 if (c) {
1066 if (!drawBuffer || !readBuffer)
1067 return GL_FALSE; /* must specify buffers! */
1068
1069 #if 0
1070 /* XXX restore this optimization */
1071 if (&(c->mesa) == _mesa_get_current_context()
1072 && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
1073 && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
1074 && xmesa_buffer(c->mesa.DrawBuffer)->wasCurrent) {
1075 /* same context and buffer, do nothing */
1076 return GL_TRUE;
1077 }
1078 #endif
1079
1080 c->xm_buffer = drawBuffer;
1081
1082 /* Call this periodically to detect when the user has begun using
1083 * GL rendering from multiple threads.
1084 */
1085 _glapi_check_multithread();
1086
1087 st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
1088
1089 xmesa_check_and_update_buffer_size(c, drawBuffer);
1090 if (readBuffer != drawBuffer)
1091 xmesa_check_and_update_buffer_size(c, readBuffer);
1092
1093 /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1094 drawBuffer->wasCurrent = GL_TRUE;
1095 }
1096 else {
1097 /* Detach */
1098 st_make_current( NULL, NULL, NULL );
1099 }
1100 return GL_TRUE;
1101 }
1102
1103
1104 /*
1105 * Unbind the context c from its buffer.
1106 */
1107 GLboolean XMesaUnbindContext( XMesaContext c )
1108 {
1109 /* A no-op for XFree86 integration purposes */
1110 return GL_TRUE;
1111 }
1112
1113
1114 XMesaContext XMesaGetCurrentContext( void )
1115 {
1116 GET_CURRENT_CONTEXT(ctx);
1117 if (ctx) {
1118 XMesaContext xmesa = xmesa_context(ctx);
1119 return xmesa;
1120 }
1121 else {
1122 return 0;
1123 }
1124 }
1125
1126
1127 XMesaBuffer XMesaGetCurrentBuffer( void )
1128 {
1129 GET_CURRENT_CONTEXT(ctx);
1130 if (ctx) {
1131 XMesaBuffer xmbuf = xmesa_buffer(ctx->DrawBuffer);
1132 return xmbuf;
1133 }
1134 else {
1135 return 0;
1136 }
1137 }
1138
1139
1140 /* New in Mesa 3.1 */
1141 XMesaBuffer XMesaGetCurrentReadBuffer( void )
1142 {
1143 GET_CURRENT_CONTEXT(ctx);
1144 if (ctx) {
1145 return xmesa_buffer(ctx->ReadBuffer);
1146 }
1147 else {
1148 return 0;
1149 }
1150 }
1151
1152
1153 #ifdef XFree86Server
1154 PUBLIC
1155 GLboolean XMesaForceCurrent(XMesaContext c)
1156 {
1157 if (c) {
1158 _glapi_set_dispatch(c->mesa.CurrentDispatch);
1159
1160 if (&(c->mesa) != _mesa_get_current_context()) {
1161 _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
1162 }
1163 }
1164 else {
1165 _mesa_make_current(NULL, NULL, NULL);
1166 }
1167 return GL_TRUE;
1168 }
1169
1170
1171 PUBLIC
1172 GLboolean XMesaLoseCurrent(XMesaContext c)
1173 {
1174 (void) c;
1175 _mesa_make_current(NULL, NULL, NULL);
1176 return GL_TRUE;
1177 }
1178
1179
1180 PUBLIC
1181 GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask )
1182 {
1183 _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
1184 return GL_TRUE;
1185 }
1186 #endif /* XFree86Server */
1187
1188
1189 #ifndef FX
1190 GLboolean XMesaSetFXmode( GLint mode )
1191 {
1192 (void) mode;
1193 return GL_FALSE;
1194 }
1195 #endif
1196
1197
1198
1199 /*
1200 * Copy the back buffer to the front buffer. If there's no back buffer
1201 * this is a no-op.
1202 */
1203 PUBLIC
1204 void XMesaSwapBuffers( XMesaBuffer b )
1205 {
1206 struct pipe_surface *surf;
1207
1208 /* If we're swapping the buffer associated with the current context
1209 * we have to flush any pending rendering commands first.
1210 */
1211 st_notify_swapbuffers(b->stfb);
1212
1213 surf = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
1214 if (surf) {
1215 if (xmesa_mode == XMESA_AUB)
1216 xmesa_display_aub( surf );
1217 else
1218 xmesa_display_surface(b, surf);
1219 }
1220
1221 xmesa_check_and_update_buffer_size(NULL, b);
1222 }
1223
1224
1225
1226 /*
1227 * Copy sub-region of back buffer to front buffer
1228 */
1229 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1230 {
1231 struct pipe_surface *surf_front
1232 = st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT);
1233 struct pipe_surface *surf_back
1234 = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
1235 struct pipe_context *pipe = NULL; /* XXX fix */
1236
1237 if (!surf_front || !surf_back)
1238 return;
1239
1240 pipe->surface_copy(pipe,
1241 FALSE,
1242 surf_front, x, y, /* dest */
1243 surf_back, x, y, /* src */
1244 width, height);
1245 }
1246
1247
1248
1249 /*
1250 * Return the depth buffer associated with an XMesaBuffer.
1251 * Input: b - the XMesa buffer handle
1252 * Output: width, height - size of buffer in pixels
1253 * bytesPerValue - bytes per depth value (2 or 4)
1254 * buffer - pointer to depth buffer values
1255 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1256 */
1257 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
1258 GLint *bytesPerValue, void **buffer )
1259 {
1260 *width = 0;
1261 *height = 0;
1262 *bytesPerValue = 0;
1263 *buffer = 0;
1264 return GL_FALSE;
1265 }
1266
1267
1268 void XMesaFlush( XMesaContext c )
1269 {
1270 if (c && c->xm_visual->display) {
1271 #ifdef XFree86Server
1272 /* NOT_NEEDED */
1273 #else
1274 XSync( c->xm_visual->display, False );
1275 #endif
1276 }
1277 }
1278
1279
1280
1281 const char *XMesaGetString( XMesaContext c, int name )
1282 {
1283 (void) c;
1284 if (name==XMESA_VERSION) {
1285 return "5.0";
1286 }
1287 else if (name==XMESA_EXTENSIONS) {
1288 return "";
1289 }
1290 else {
1291 return NULL;
1292 }
1293 }
1294
1295
1296
1297 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
1298 {
1299 XMesaBuffer b;
1300 for (b=XMesaBufferList; b; b=b->Next) {
1301 if (b->drawable == d && b->xm_visual->display == dpy) {
1302 return b;
1303 }
1304 }
1305 return NULL;
1306 }
1307
1308
1309 /**
1310 * Free/destroy all XMesaBuffers associated with given display.
1311 */
1312 void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
1313 {
1314 XMesaBuffer b, next;
1315 for (b = XMesaBufferList; b; b = next) {
1316 next = b->Next;
1317 if (b->xm_visual->display == dpy) {
1318 xmesa_free_buffer(b);
1319 }
1320 }
1321 }
1322
1323
1324 /*
1325 * Look for XMesaBuffers whose X window has been destroyed.
1326 * Deallocate any such XMesaBuffers.
1327 */
1328 void XMesaGarbageCollect( void )
1329 {
1330 XMesaBuffer b, next;
1331 for (b=XMesaBufferList; b; b=next) {
1332 next = b->Next;
1333 if (b->xm_visual &&
1334 b->xm_visual->display &&
1335 b->drawable &&
1336 b->type == WINDOW) {
1337 #ifdef XFree86Server
1338 /* NOT_NEEDED */
1339 #else
1340 XSync(b->xm_visual->display, False);
1341 if (!window_exists( b->xm_visual->display, b->drawable )) {
1342 /* found a dead window, free the ancillary info */
1343 XMesaDestroyBuffer( b );
1344 }
1345 #endif
1346 }
1347 }
1348 }
1349
1350
1351 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
1352 GLfloat red, GLfloat green,
1353 GLfloat blue, GLfloat alpha )
1354 {
1355 /* no longer supported */
1356 return 0;
1357 }
1358
1359
1360 /*
1361 * This is typically called when the window size changes and we need
1362 * to reallocate the buffer's back/depth/stencil/accum buffers.
1363 */
1364 PUBLIC void
1365 XMesaResizeBuffers( XMesaBuffer b )
1366 {
1367 GET_CURRENT_CONTEXT(ctx);
1368 XMesaContext xmctx = xmesa_context(ctx);
1369 if (!xmctx)
1370 return;
1371 xmesa_check_and_update_buffer_size(xmctx, b);
1372 }
1373
1374
1375
1376
1377 PUBLIC void
1378 XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
1379 const int *attrib_list)
1380 {
1381 }
1382
1383
1384
1385 PUBLIC void
1386 XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
1387 {
1388 }
1389