OSDN Git Service

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