• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * 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  *
39  * Byte swapping:  If the Mesa host and the X display use a different
40  * byte order then there's some trickiness to be aware of when using
41  * XImages.  The byte ordering used for the XImage is that of the X
42  * display, not the Mesa host.
43  * The color-to-pixel encoding for True/DirectColor must be done
44  * according to the display's visual red_mask, green_mask, and blue_mask.
45  * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
46  * do byte swapping if needed.  If one wants to directly "poke" the pixel
47  * into the XImage's buffer then the pixel must be byte swapped first.
48  *
49  */
50 
51 #ifdef __CYGWIN__
52 #undef WIN32
53 #undef __WIN32__
54 #endif
55 
56 #include <stdio.h>
57 #include "xm_api.h"
58 #include "xm_st.h"
59 
60 #include "pipe/p_context.h"
61 #include "pipe/p_defines.h"
62 #include "pipe/p_screen.h"
63 #include "pipe/p_state.h"
64 #include "frontend/api.h"
65 
66 #include "util/u_atomic.h"
67 #include "util/u_inlines.h"
68 #include "util/u_math.h"
69 #include "util/u_memory.h"
70 
71 #include "hud/hud_context.h"
72 
73 #include "main/errors.h"
74 #include "main/mtypes.h"
75 
76 #include "xm_public.h"
77 #include <GL/glx.h>
78 
79 
80 /* Driver interface routines, set up by xlib backend on library
81  * _init().  These are global in the same way that function names are
82  * global.
83  */
84 static struct xm_driver driver;
85 static struct st_api *stapi;
86 
87 /* Default strict invalidate to false.  This means we will not call
88  * XGetGeometry after every swapbuffers, which allows swapbuffers to
89  * remain asynchronous.  For apps running at 100fps with synchronous
90  * swapping, a 10% boost is typical.  For gears, I see closer to 20%
91  * speedup.
92  *
93  * Note that the work of copying data on swapbuffers doesn't disappear
94  * - this change just allows the X server to execute the PutImage
95  * asynchronously without us effectively blocked until its completion.
96  *
97  * This speeds up even llvmpipe's threaded rasterization as the
98  * swapbuffers operation was a large part of the serial component of
99  * an llvmpipe frame.
100  *
101  * The downside of this is correctness - applications which don't call
102  * glViewport on window resizes will get incorrect rendering.  A
103  * better solution would be to have per-frame but asynchronous
104  * invalidation.  Xcb almost looks as if it could provide this, but
105  * the API doesn't seem to quite be there.
106  */
107 boolean xmesa_strict_invalidate = FALSE;
108 
xmesa_set_driver(const struct xm_driver * templ)109 void xmesa_set_driver( const struct xm_driver *templ )
110 {
111    driver = *templ;
112    stapi = driver.create_st_api();
113 
114    xmesa_strict_invalidate =
115       debug_get_bool_option("XMESA_STRICT_INVALIDATE", FALSE);
116 }
117 
118 
119 static int
xmesa_get_param(struct st_manager * smapi,enum st_manager_param param)120 xmesa_get_param(struct st_manager *smapi,
121                 enum st_manager_param param)
122 {
123    switch(param) {
124    case ST_MANAGER_BROKEN_INVALIDATE:
125       return !xmesa_strict_invalidate;
126    default:
127       return 0;
128    }
129 }
130 
131 /* linked list of XMesaDisplay hooks per display */
132 typedef struct _XMesaExtDisplayInfo {
133    struct _XMesaExtDisplayInfo *next;
134    Display *display;
135    struct xmesa_display mesaDisplay;
136 } XMesaExtDisplayInfo;
137 
138 typedef struct _XMesaExtInfo {
139    XMesaExtDisplayInfo *head;
140    int ndisplays;
141 } XMesaExtInfo;
142 
143 static XMesaExtInfo MesaExtInfo;
144 
145 /* hook to delete XMesaDisplay on XDestroyDisplay */
146 extern void
xmesa_close_display(Display * display)147 xmesa_close_display(Display *display)
148 {
149    XMesaExtDisplayInfo *info, *prev;
150 
151    /* These assertions are not valid since screen creation can fail and result
152     * in an empty list
153    assert(MesaExtInfo.ndisplays > 0);
154    assert(MesaExtInfo.head);
155    */
156 
157    _XLockMutex(_Xglobal_lock);
158    /* first find display */
159    prev = NULL;
160    for (info = MesaExtInfo.head; info; info = info->next) {
161       if (info->display == display) {
162          prev = info;
163          break;
164       }
165    }
166 
167    if (info == NULL) {
168       /* no display found */
169       _XUnlockMutex(_Xglobal_lock);
170       return;
171    }
172 
173    /* remove display entry from list */
174    if (prev != MesaExtInfo.head) {
175       prev->next = info->next;
176    } else {
177       MesaExtInfo.head = info->next;
178    }
179    MesaExtInfo.ndisplays--;
180 
181    _XUnlockMutex(_Xglobal_lock);
182 
183    /* don't forget to clean up mesaDisplay */
184    XMesaDisplay xmdpy = &info->mesaDisplay;
185 
186    /**
187     * XXX: Don't destroy the screens here, since there may still
188     * be some dangling screen pointers that are used after this point
189     * if (xmdpy->screen) {
190     *    xmdpy->screen->destroy(xmdpy->screen);
191     * }
192     */
193 
194    if (xmdpy->smapi->destroy)
195       xmdpy->smapi->destroy(xmdpy->smapi);
196    free(xmdpy->smapi);
197 
198    XFree((char *) info);
199 }
200 
201 static XMesaDisplay
xmesa_init_display(Display * display)202 xmesa_init_display( Display *display )
203 {
204    static mtx_t init_mutex = _MTX_INITIALIZER_NP;
205    XMesaDisplay xmdpy;
206    XMesaExtDisplayInfo *info;
207 
208    if (display == NULL) {
209       return NULL;
210    }
211 
212    mtx_lock(&init_mutex);
213 
214    /* Look for XMesaDisplay which corresponds to this display */
215    info = MesaExtInfo.head;
216    while(info) {
217       if (info->display == display) {
218          /* Found it */
219          mtx_unlock(&init_mutex);
220          return  &info->mesaDisplay;
221       }
222       info = info->next;
223    }
224 
225    /* Not found.  Create new XMesaDisplay */
226    /* first allocate X-related resources and hook destroy callback */
227 
228    /* allocate mesa display info */
229    info = (XMesaExtDisplayInfo *) Xmalloc(sizeof(XMesaExtDisplayInfo));
230    if (info == NULL) {
231       mtx_unlock(&init_mutex);
232       return NULL;
233    }
234    info->display = display;
235 
236    xmdpy = &info->mesaDisplay; /* to be filled out below */
237    xmdpy->display = display;
238    xmdpy->pipe = NULL;
239 
240    xmdpy->smapi = CALLOC_STRUCT(st_manager);
241    if (!xmdpy->smapi) {
242       Xfree(info);
243       mtx_unlock(&init_mutex);
244       return NULL;
245    }
246 
247    xmdpy->screen = driver.create_pipe_screen(display);
248    if (!xmdpy->screen) {
249       free(xmdpy->smapi);
250       Xfree(info);
251       mtx_unlock(&init_mutex);
252       return NULL;
253    }
254 
255    /* At this point, both smapi and screen are known to be valid */
256    xmdpy->smapi->screen = xmdpy->screen;
257    xmdpy->smapi->get_param = xmesa_get_param;
258    (void) mtx_init(&xmdpy->mutex, mtx_plain);
259 
260    /* chain to the list of displays */
261    _XLockMutex(_Xglobal_lock);
262    info->next = MesaExtInfo.head;
263    MesaExtInfo.head = info;
264    MesaExtInfo.ndisplays++;
265    _XUnlockMutex(_Xglobal_lock);
266 
267    mtx_unlock(&init_mutex);
268 
269    return xmdpy;
270 }
271 
272 
273 /**********************************************************************/
274 /*****                     X Utility Functions                    *****/
275 /**********************************************************************/
276 
277 
278 /**
279  * Return the host's byte order as LSBFirst or MSBFirst ala X.
280  */
host_byte_order(void)281 static int host_byte_order( void )
282 {
283    int i = 1;
284    char *cptr = (char *) &i;
285    return (*cptr==1) ? LSBFirst : MSBFirst;
286 }
287 
288 
289 
290 
291 /**
292  * Return the true number of bits per pixel for XImages.
293  * For example, if we request a 24-bit deep visual we may actually need/get
294  * 32bpp XImages.  This function returns the appropriate bpp.
295  * Input:  dpy - the X display
296  *         visinfo - desribes the visual to be used for XImages
297  * Return:  true number of bits per pixel for XImages
298  */
299 static int
bits_per_pixel(XMesaVisual xmv)300 bits_per_pixel( XMesaVisual xmv )
301 {
302    Display *dpy = xmv->display;
303    XVisualInfo * visinfo = xmv->visinfo;
304    XImage *img;
305    int bitsPerPixel;
306    /* Create a temporary XImage */
307    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
308 		       ZPixmap, 0,           /*format, offset*/
309 		       malloc(8),    /*data*/
310 		       1, 1,                 /*width, height*/
311 		       32,                   /*bitmap_pad*/
312 		       0                     /*bytes_per_line*/
313                      );
314    assert(img);
315    /* grab the bits/pixel value */
316    bitsPerPixel = img->bits_per_pixel;
317    /* free the XImage */
318    free( img->data );
319    img->data = NULL;
320    XDestroyImage( img );
321    return bitsPerPixel;
322 }
323 
324 
325 
326 /*
327  * Determine if a given X window ID is valid (window exists).
328  * Do this by calling XGetWindowAttributes() for the window and
329  * checking if we catch an X error.
330  * Input:  dpy - the display
331  *         win - the window to check for existence
332  * Return:  GL_TRUE - window exists
333  *          GL_FALSE - window doesn't exist
334  */
335 static GLboolean WindowExistsFlag;
336 
window_exists_err_handler(Display * dpy,XErrorEvent * xerr)337 static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr )
338 {
339    (void) dpy;
340    if (xerr->error_code == BadWindow) {
341       WindowExistsFlag = GL_FALSE;
342    }
343    return 0;
344 }
345 
window_exists(Display * dpy,Window win)346 static GLboolean window_exists( Display *dpy, Window win )
347 {
348    XWindowAttributes wa;
349    int (*old_handler)( Display*, XErrorEvent* );
350    WindowExistsFlag = GL_TRUE;
351    old_handler = XSetErrorHandler(window_exists_err_handler);
352    XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
353    XSetErrorHandler(old_handler);
354    return WindowExistsFlag;
355 }
356 
357 static Status
get_drawable_size(Display * dpy,Drawable d,uint * width,uint * height)358 get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height )
359 {
360    Window root;
361    Status stat;
362    int xpos, ypos;
363    unsigned int w, h, bw, depth;
364    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
365    *width = w;
366    *height = h;
367    return stat;
368 }
369 
370 
371 /**
372  * Return the size of the window (or pixmap) that corresponds to the
373  * given XMesaBuffer.
374  * \param width  returns width in pixels
375  * \param height  returns height in pixels
376  */
377 void
xmesa_get_window_size(Display * dpy,XMesaBuffer b,GLuint * width,GLuint * height)378 xmesa_get_window_size(Display *dpy, XMesaBuffer b,
379                       GLuint *width, GLuint *height)
380 {
381    XMesaDisplay xmdpy = xmesa_init_display(dpy);
382    Status stat;
383 
384    mtx_lock(&xmdpy->mutex);
385    stat = get_drawable_size(dpy, b->ws.drawable, width, height);
386    mtx_unlock(&xmdpy->mutex);
387 
388    if (!stat) {
389       /* probably querying a window that's recently been destroyed */
390       _mesa_warning(NULL, "XGetGeometry failed!\n");
391       *width = *height = 1;
392    }
393 }
394 
395 #define GET_REDMASK(__v)        __v->mesa_visual.redMask
396 #define GET_GREENMASK(__v)      __v->mesa_visual.greenMask
397 #define GET_BLUEMASK(__v)       __v->mesa_visual.blueMask
398 
399 
400 /**
401  * Choose the pixel format for the given visual.
402  * This will tell the gallium driver how to pack pixel data into
403  * drawing surfaces.
404  */
405 static GLuint
choose_pixel_format(XMesaVisual v)406 choose_pixel_format(XMesaVisual v)
407 {
408    boolean native_byte_order = (host_byte_order() ==
409                                 ImageByteOrder(v->display));
410 
411    if (   GET_REDMASK(v)   == 0x0000ff
412        && GET_GREENMASK(v) == 0x00ff00
413        && GET_BLUEMASK(v)  == 0xff0000
414        && v->BitsPerPixel == 32) {
415       if (native_byte_order) {
416          /* no byteswapping needed */
417          return PIPE_FORMAT_RGBA8888_UNORM;
418       }
419       else {
420          return PIPE_FORMAT_ABGR8888_UNORM;
421       }
422    }
423    else if (   GET_REDMASK(v)   == 0xff0000
424             && GET_GREENMASK(v) == 0x00ff00
425             && GET_BLUEMASK(v)  == 0x0000ff
426             && v->BitsPerPixel == 32) {
427       if (native_byte_order) {
428          /* no byteswapping needed */
429          return PIPE_FORMAT_BGRA8888_UNORM;
430       }
431       else {
432          return PIPE_FORMAT_ARGB8888_UNORM;
433       }
434    }
435    else if (   GET_REDMASK(v)   == 0x0000ff00
436             && GET_GREENMASK(v) == 0x00ff0000
437             && GET_BLUEMASK(v)  == 0xff000000
438             && v->BitsPerPixel == 32) {
439       if (native_byte_order) {
440          /* no byteswapping needed */
441          return PIPE_FORMAT_ARGB8888_UNORM;
442       }
443       else {
444          return PIPE_FORMAT_BGRA8888_UNORM;
445       }
446    }
447    else if (   GET_REDMASK(v)   == 0xf800
448             && GET_GREENMASK(v) == 0x07e0
449             && GET_BLUEMASK(v)  == 0x001f
450             && native_byte_order
451             && v->BitsPerPixel == 16) {
452       /* 5-6-5 RGB */
453       return PIPE_FORMAT_B5G6R5_UNORM;
454    }
455 
456    return PIPE_FORMAT_NONE;
457 }
458 
459 
460 /**
461  * Choose a depth/stencil format that satisfies the given depth and
462  * stencil sizes.
463  */
464 static enum pipe_format
choose_depth_stencil_format(XMesaDisplay xmdpy,int depth,int stencil,int sample_count)465 choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil,
466                             int sample_count)
467 {
468    const enum pipe_texture_target target = PIPE_TEXTURE_2D;
469    const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL;
470    enum pipe_format formats[8], fmt;
471    int count, i;
472 
473    count = 0;
474 
475    if (depth <= 16 && stencil == 0) {
476       formats[count++] = PIPE_FORMAT_Z16_UNORM;
477    }
478    if (depth <= 24 && stencil == 0) {
479       formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
480       formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
481    }
482    if (depth <= 24 && stencil <= 8) {
483       formats[count++] = PIPE_FORMAT_S8_UINT_Z24_UNORM;
484       formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_UINT;
485    }
486    if (depth <= 32 && stencil == 0) {
487       formats[count++] = PIPE_FORMAT_Z32_UNORM;
488    }
489 
490    fmt = PIPE_FORMAT_NONE;
491    for (i = 0; i < count; i++) {
492       if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i],
493                                              target, sample_count,
494                                              sample_count, tex_usage)) {
495          fmt = formats[i];
496          break;
497       }
498    }
499 
500    return fmt;
501 }
502 
503 
504 
505 /**********************************************************************/
506 /*****                Linked list of XMesaBuffers                 *****/
507 /**********************************************************************/
508 
509 static XMesaBuffer XMesaBufferList = NULL;
510 
511 
512 /**
513  * Allocate a new XMesaBuffer object which corresponds to the given drawable.
514  * Note that XMesaBuffer is derived from struct gl_framebuffer.
515  * The new XMesaBuffer will not have any size (Width=Height=0).
516  *
517  * \param d  the corresponding X drawable (window or pixmap)
518  * \param type  either WINDOW, PIXMAP or PBUFFER, describing d
519  * \param vis  the buffer's visual
520  * \param cmap  the window's colormap, if known.
521  * \return new XMesaBuffer or NULL if any problem
522  */
523 static XMesaBuffer
create_xmesa_buffer(Drawable d,BufferType type,XMesaVisual vis,Colormap cmap)524 create_xmesa_buffer(Drawable d, BufferType type,
525                     XMesaVisual vis, Colormap cmap)
526 {
527    XMesaDisplay xmdpy = xmesa_init_display(vis->display);
528    XMesaBuffer b;
529 
530    assert(type == WINDOW || type == PIXMAP || type == PBUFFER);
531 
532    if (!xmdpy)
533       return NULL;
534 
535    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
536    if (!b)
537       return NULL;
538 
539    b->ws.drawable = d;
540    b->ws.visual = vis->visinfo->visual;
541    b->ws.depth = vis->visinfo->depth;
542 
543    b->xm_visual = vis;
544    b->type = type;
545    b->cmap = cmap;
546 
547    get_drawable_size(vis->display, d, &b->width, &b->height);
548 
549    /*
550     * Create framebuffer, but we'll plug in our own renderbuffers below.
551     */
552    b->stfb = xmesa_create_st_framebuffer(xmdpy, b);
553 
554    /* GLX_EXT_texture_from_pixmap */
555    b->TextureTarget = 0;
556    b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
557    b->TextureMipmap = 0;
558 
559    /* insert buffer into linked list */
560    b->Next = XMesaBufferList;
561    XMesaBufferList = b;
562 
563    return b;
564 }
565 
566 
567 /**
568  * Find an XMesaBuffer by matching X display and colormap but NOT matching
569  * the notThis buffer.
570  */
571 XMesaBuffer
xmesa_find_buffer(Display * dpy,Colormap cmap,XMesaBuffer notThis)572 xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis)
573 {
574    XMesaBuffer b;
575    for (b = XMesaBufferList; b; b = b->Next) {
576       if (b->xm_visual->display == dpy &&
577           b->cmap == cmap &&
578           b != notThis) {
579          return b;
580       }
581    }
582    return NULL;
583 }
584 
585 
586 /**
587  * Remove buffer from linked list, delete if no longer referenced.
588  */
589 static void
xmesa_free_buffer(XMesaBuffer buffer)590 xmesa_free_buffer(XMesaBuffer buffer)
591 {
592    XMesaBuffer prev = NULL, b;
593 
594    for (b = XMesaBufferList; b; b = b->Next) {
595       if (b == buffer) {
596          /* unlink buffer from list */
597          if (prev)
598             prev->Next = buffer->Next;
599          else
600             XMesaBufferList = buffer->Next;
601 
602          /* Since the X window for the XMesaBuffer is going away, we don't
603           * want to dereference this pointer in the future.
604           */
605          b->ws.drawable = 0;
606 
607          /* Notify the st manager that the associated framebuffer interface
608           * object is no longer valid.
609           */
610          stapi->destroy_drawable(stapi, buffer->stfb);
611 
612          /* XXX we should move the buffer to a delete-pending list and destroy
613           * the buffer until it is no longer current.
614           */
615          xmesa_destroy_st_framebuffer(buffer->stfb);
616 
617          free(buffer);
618 
619          return;
620       }
621       /* continue search */
622       prev = b;
623    }
624    /* buffer not found in XMesaBufferList */
625    _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
626 }
627 
628 
629 
630 /**********************************************************************/
631 /*****                   Misc Private Functions                   *****/
632 /**********************************************************************/
633 
634 
635 /**
636  * When a context is bound for the first time, we can finally finish
637  * initializing the context's visual and buffer information.
638  * \param v  the XMesaVisual to initialize
639  * \param b  the XMesaBuffer to initialize (may be NULL)
640  * \param window  the window/pixmap we're rendering into
641  * \param cmap  the colormap associated with the window/pixmap
642  * \return GL_TRUE=success, GL_FALSE=failure
643  */
644 static GLboolean
initialize_visual_and_buffer(XMesaVisual v,XMesaBuffer b,Drawable window,Colormap cmap)645 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
646                              Drawable window, Colormap cmap)
647 {
648    assert(!b || b->xm_visual == v);
649 
650    /* Save true bits/pixel */
651    v->BitsPerPixel = bits_per_pixel(v);
652    assert(v->BitsPerPixel > 0);
653 
654    /* RGB WINDOW:
655     * We support RGB rendering into almost any kind of visual.
656     */
657    const int xclass = v->visualType;
658    if (xclass != GLX_TRUE_COLOR && xclass != GLX_DIRECT_COLOR) {
659       _mesa_warning(NULL,
660          "XMesa: RGB mode rendering not supported in given visual.\n");
661       return GL_FALSE;
662    }
663 
664    if (v->BitsPerPixel == 32) {
665       /* We use XImages for all front/back buffers.  If an X Window or
666        * X Pixmap is 32bpp, there's no guarantee that the alpha channel
667        * will be preserved.  For XImages we're in luck.
668        */
669       v->mesa_visual.alphaBits = 8;
670    }
671 
672    /*
673     * If MESA_INFO env var is set print out some debugging info
674     * which can help Brian figure out what's going on when a user
675     * reports bugs.
676     */
677    if (getenv("MESA_INFO")) {
678       printf("X/Mesa visual = %p\n", (void *) v);
679       printf("X/Mesa depth = %d\n", v->visinfo->depth);
680       printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
681    }
682 
683    return GL_TRUE;
684 }
685 
686 
687 
688 #define NUM_VISUAL_TYPES   6
689 
690 /**
691  * Convert an X visual type to a GLX visual type.
692  *
693  * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
694  *        to be converted.
695  * \return If \c visualType is a valid X visual type, a GLX visual type will
696  *         be returned.  Otherwise \c GLX_NONE will be returned.
697  *
698  * \note
699  * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
700  * DRI CVS tree.
701  */
702 static GLint
xmesa_convert_from_x_visual_type(int visualType)703 xmesa_convert_from_x_visual_type( int visualType )
704 {
705     static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
706 	GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
707 	GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
708 	GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
709     };
710 
711     return ( (unsigned) visualType < NUM_VISUAL_TYPES )
712 	? glx_visual_types[ visualType ] : GLX_NONE;
713 }
714 
715 
716 /**********************************************************************/
717 /*****                       Public Functions                     *****/
718 /**********************************************************************/
719 
720 
721 /*
722  * Create a new X/Mesa visual.
723  * Input:  display - X11 display
724  *         visinfo - an XVisualInfo pointer
725  *         rgb_flag - GL_TRUE = RGB mode,
726  *                    GL_FALSE = color index mode
727  *         alpha_flag - alpha buffer requested?
728  *         db_flag - GL_TRUE = double-buffered,
729  *                   GL_FALSE = single buffered
730  *         stereo_flag - stereo visual?
731  *         ximage_flag - GL_TRUE = use an XImage for back buffer,
732  *                       GL_FALSE = use an off-screen pixmap for back buffer
733  *         depth_size - requested bits/depth values, or zero
734  *         stencil_size - requested bits/stencil values, or zero
735  *         accum_red_size - requested bits/red accum values, or zero
736  *         accum_green_size - requested bits/green accum values, or zero
737  *         accum_blue_size - requested bits/blue accum values, or zero
738  *         accum_alpha_size - requested bits/alpha accum values, or zero
739  *         num_samples - number of samples/pixel if multisampling, or zero
740  *         level - visual level, usually 0
741  *         visualCaveat - ala the GLX extension, usually GLX_NONE
742  * Return;  a new XMesaVisual or 0 if error.
743  */
744 PUBLIC
XMesaCreateVisual(Display * display,XVisualInfo * visinfo,GLboolean rgb_flag,GLboolean alpha_flag,GLboolean db_flag,GLboolean stereo_flag,GLboolean ximage_flag,GLint depth_size,GLint stencil_size,GLint accum_red_size,GLint accum_green_size,GLint accum_blue_size,GLint accum_alpha_size,GLint num_samples,GLint level,GLint visualCaveat)745 XMesaVisual XMesaCreateVisual( Display *display,
746                                XVisualInfo * visinfo,
747                                GLboolean rgb_flag,
748                                GLboolean alpha_flag,
749                                GLboolean db_flag,
750                                GLboolean stereo_flag,
751                                GLboolean ximage_flag,
752                                GLint depth_size,
753                                GLint stencil_size,
754                                GLint accum_red_size,
755                                GLint accum_green_size,
756                                GLint accum_blue_size,
757                                GLint accum_alpha_size,
758                                GLint num_samples,
759                                GLint level,
760                                GLint visualCaveat )
761 {
762    XMesaDisplay xmdpy = xmesa_init_display(display);
763    XMesaVisual v;
764    GLint red_bits, green_bits, blue_bits, alpha_bits;
765 
766    if (!xmdpy)
767       return NULL;
768 
769    if (!rgb_flag)
770       return NULL;
771 
772    /* For debugging only */
773    if (getenv("MESA_XSYNC")) {
774       /* This makes debugging X easier.
775        * In your debugger, set a breakpoint on _XError to stop when an
776        * X protocol error is generated.
777        */
778       XSynchronize( display, 1 );
779    }
780 
781    v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
782    if (!v) {
783       return NULL;
784    }
785 
786    v->display = display;
787 
788    /* Save a copy of the XVisualInfo struct because the user may Xfree()
789     * the struct but we may need some of the information contained in it
790     * at a later time.
791     */
792    v->visinfo = malloc(sizeof(*visinfo));
793    if (!v->visinfo) {
794       free(v);
795       return NULL;
796    }
797    memcpy(v->visinfo, visinfo, sizeof(*visinfo));
798 
799    v->ximage_flag = ximage_flag;
800 
801    v->mesa_visual.redMask = visinfo->red_mask;
802    v->mesa_visual.greenMask = visinfo->green_mask;
803    v->mesa_visual.blueMask = visinfo->blue_mask;
804    v->visualID = visinfo->visualid;
805    v->screen = visinfo->screen;
806 
807 #if !(defined(__cplusplus) || defined(c_plusplus))
808    v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
809 #else
810    v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
811 #endif
812 
813    if (alpha_flag)
814       v->mesa_visual.alphaBits = 8;
815 
816    (void) initialize_visual_and_buffer( v, NULL, 0, 0 );
817 
818    {
819       const int xclass = v->visualType;
820       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
821          red_bits   = util_bitcount(GET_REDMASK(v));
822          green_bits = util_bitcount(GET_GREENMASK(v));
823          blue_bits  = util_bitcount(GET_BLUEMASK(v));
824       }
825       else {
826          /* this is an approximation */
827          int depth;
828          depth = v->visinfo->depth;
829          red_bits = depth / 3;
830          depth -= red_bits;
831          green_bits = depth / 2;
832          depth -= green_bits;
833          blue_bits = depth;
834          alpha_bits = 0;
835          assert( red_bits + green_bits + blue_bits == v->visinfo->depth );
836       }
837       alpha_bits = v->mesa_visual.alphaBits;
838    }
839 
840    /* initialize visual */
841    {
842       struct gl_config *vis = &v->mesa_visual;
843 
844       vis->doubleBufferMode = db_flag;
845       vis->stereoMode       = stereo_flag;
846 
847       vis->redBits          = red_bits;
848       vis->greenBits        = green_bits;
849       vis->blueBits         = blue_bits;
850       vis->alphaBits        = alpha_bits;
851       vis->rgbBits          = red_bits + green_bits + blue_bits;
852 
853       vis->depthBits      = depth_size;
854       vis->stencilBits    = stencil_size;
855 
856       vis->accumRedBits   = accum_red_size;
857       vis->accumGreenBits = accum_green_size;
858       vis->accumBlueBits  = accum_blue_size;
859       vis->accumAlphaBits = accum_alpha_size;
860 
861       vis->samples = num_samples;
862    }
863 
864    v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
865    if (db_flag)
866       v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
867    if (stereo_flag) {
868       v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK;
869       if (db_flag)
870          v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK;
871    }
872 
873    v->stvis.color_format = choose_pixel_format(v);
874 
875    /* Check format support at requested num_samples (for multisample) */
876    if (!xmdpy->screen->is_format_supported(xmdpy->screen,
877                                            v->stvis.color_format,
878                                            PIPE_TEXTURE_2D, num_samples,
879                                            num_samples,
880                                            PIPE_BIND_RENDER_TARGET))
881       v->stvis.color_format = PIPE_FORMAT_NONE;
882 
883    if (v->stvis.color_format == PIPE_FORMAT_NONE) {
884       free(v->visinfo);
885       free(v);
886       return NULL;
887    }
888 
889    v->stvis.depth_stencil_format =
890       choose_depth_stencil_format(xmdpy, depth_size, stencil_size,
891                                   num_samples);
892 
893    v->stvis.accum_format = (accum_red_size +
894          accum_green_size + accum_blue_size + accum_alpha_size) ?
895       PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
896 
897    v->stvis.samples = num_samples;
898 
899    return v;
900 }
901 
902 
903 PUBLIC
XMesaDestroyVisual(XMesaVisual v)904 void XMesaDestroyVisual( XMesaVisual v )
905 {
906    free(v->visinfo);
907    free(v);
908 }
909 
910 
911 /**
912  * Return the informative name.
913  */
914 const char *
xmesa_get_name(void)915 xmesa_get_name(void)
916 {
917    return stapi->name;
918 }
919 
920 
921 /**
922  * Do per-display initializations.
923  */
924 int
xmesa_init(Display * display)925 xmesa_init( Display *display )
926 {
927    return xmesa_init_display(display) ? 0 : 1;
928 }
929 
930 
931 /**
932  * Create a new XMesaContext.
933  * \param v  the XMesaVisual
934  * \param share_list  another XMesaContext with which to share display
935  *                    lists or NULL if no sharing is wanted.
936  * \return an XMesaContext or NULL if error.
937  */
938 PUBLIC
XMesaCreateContext(XMesaVisual v,XMesaContext share_list,GLuint major,GLuint minor,GLuint profileMask,GLuint contextFlags)939 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list,
940                                  GLuint major, GLuint minor,
941                                  GLuint profileMask, GLuint contextFlags)
942 {
943    XMesaDisplay xmdpy = xmesa_init_display(v->display);
944    struct st_context_attribs attribs;
945    enum st_context_error ctx_err = 0;
946    XMesaContext c;
947 
948    if (!xmdpy)
949       goto no_xmesa_context;
950 
951    /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
952    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
953    if (!c)
954       goto no_xmesa_context;
955 
956    c->xm_visual = v;
957    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
958    c->xm_read_buffer = NULL;
959 
960    memset(&attribs, 0, sizeof(attribs));
961    attribs.visual = v->stvis;
962    attribs.major = major;
963    attribs.minor = minor;
964    if (contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB)
965       attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE;
966    if (contextFlags & GLX_CONTEXT_DEBUG_BIT_ARB)
967       attribs.flags |= ST_CONTEXT_FLAG_DEBUG;
968    if (contextFlags & GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB)
969       attribs.flags |= ST_CONTEXT_FLAG_ROBUST_ACCESS;
970 
971    switch (profileMask) {
972    case GLX_CONTEXT_CORE_PROFILE_BIT_ARB:
973       /* There are no profiles before OpenGL 3.2.  The
974        * GLX_ARB_create_context_profile spec says:
975        *
976        *     "If the requested OpenGL version is less than 3.2,
977        *     GLX_CONTEXT_PROFILE_MASK_ARB is ignored and the functionality
978        *     of the context is determined solely by the requested version."
979        */
980       if (major > 3 || (major == 3 && minor >= 2)) {
981          attribs.profile = ST_PROFILE_OPENGL_CORE;
982          break;
983       }
984       FALLTHROUGH;
985    case GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB:
986       /*
987        * The spec also says:
988        *
989        *     "If version 3.1 is requested, the context returned may implement
990        *     any of the following versions:
991        *
992        *       * Version 3.1. The GL_ARB_compatibility extension may or may not
993        *         be implemented, as determined by the implementation.
994        *       * The core profile of version 3.2 or greater."
995        *
996        * and because Mesa doesn't support GL_ARB_compatibility, the only chance to
997        * honour a 3.1 context is through core profile.
998        */
999       if (major == 3 && minor == 1) {
1000          attribs.profile = ST_PROFILE_OPENGL_CORE;
1001       } else {
1002          attribs.profile = ST_PROFILE_DEFAULT;
1003       }
1004       break;
1005    case GLX_CONTEXT_ES_PROFILE_BIT_EXT:
1006       if (major >= 2) {
1007          attribs.profile = ST_PROFILE_OPENGL_ES2;
1008       } else {
1009          attribs.profile = ST_PROFILE_OPENGL_ES1;
1010       }
1011       break;
1012    default:
1013       assert(0);
1014       goto no_st;
1015    }
1016 
1017    c->st = stapi->create_context(stapi, xmdpy->smapi, &attribs,
1018          &ctx_err, (share_list) ? share_list->st : NULL);
1019    if (c->st == NULL)
1020       goto no_st;
1021 
1022    c->st->st_manager_private = (void *) c;
1023 
1024    c->hud = hud_create(c->st->cso_context, c->st, NULL);
1025 
1026    return c;
1027 
1028 no_st:
1029    free(c);
1030 no_xmesa_context:
1031    return NULL;
1032 }
1033 
1034 
1035 
1036 PUBLIC
XMesaDestroyContext(XMesaContext c)1037 void XMesaDestroyContext( XMesaContext c )
1038 {
1039    if (c->hud) {
1040       hud_destroy(c->hud, NULL);
1041    }
1042 
1043    c->st->destroy(c->st);
1044 
1045    /* FIXME: We should destroy the screen here, but if we do so, surfaces may
1046     * outlive it, causing segfaults
1047    struct pipe_screen *screen = c->st->pipe->screen;
1048    screen->destroy(screen);
1049    */
1050 
1051    free(c);
1052 }
1053 
1054 
1055 
1056 /**
1057  * Private function for creating an XMesaBuffer which corresponds to an
1058  * X window or pixmap.
1059  * \param v  the window's XMesaVisual
1060  * \param w  the window we're wrapping
1061  * \return  new XMesaBuffer or NULL if error
1062  */
1063 PUBLIC XMesaBuffer
XMesaCreateWindowBuffer(XMesaVisual v,Window w)1064 XMesaCreateWindowBuffer(XMesaVisual v, Window w)
1065 {
1066    XWindowAttributes attr;
1067    XMesaBuffer b;
1068    Colormap cmap;
1069    int depth;
1070 
1071    assert(v);
1072    assert(w);
1073 
1074    /* Check that window depth matches visual depth */
1075    XGetWindowAttributes( v->display, w, &attr );
1076    depth = attr.depth;
1077    if (v->visinfo->depth != depth) {
1078       _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
1079                     v->visinfo->depth, depth);
1080       return NULL;
1081    }
1082 
1083    /* Find colormap */
1084    if (attr.colormap) {
1085       cmap = attr.colormap;
1086    }
1087    else {
1088       _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
1089       /* this is weird, a window w/out a colormap!? */
1090       /* OK, let's just allocate a new one and hope for the best */
1091       cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
1092    }
1093 
1094    b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap);
1095    if (!b)
1096       return NULL;
1097 
1098    if (!initialize_visual_and_buffer( v, b, (Drawable) w, cmap )) {
1099       xmesa_free_buffer(b);
1100       return NULL;
1101    }
1102 
1103    return b;
1104 }
1105 
1106 
1107 
1108 /**
1109  * Create a new XMesaBuffer from an X pixmap.
1110  *
1111  * \param v    the XMesaVisual
1112  * \param p    the pixmap
1113  * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
1114  *             \c GLX_DIRECT_COLOR visual for the pixmap
1115  * \returns new XMesaBuffer or NULL if error
1116  */
1117 PUBLIC XMesaBuffer
XMesaCreatePixmapBuffer(XMesaVisual v,Pixmap p,Colormap cmap)1118 XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap)
1119 {
1120    XMesaBuffer b;
1121 
1122    assert(v);
1123 
1124    b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
1125    if (!b)
1126       return NULL;
1127 
1128    if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) {
1129       xmesa_free_buffer(b);
1130       return NULL;
1131    }
1132 
1133    return b;
1134 }
1135 
1136 
1137 /**
1138  * For GLX_EXT_texture_from_pixmap
1139  */
1140 XMesaBuffer
XMesaCreatePixmapTextureBuffer(XMesaVisual v,Pixmap p,Colormap cmap,int format,int target,int mipmap)1141 XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p,
1142                                Colormap cmap,
1143                                int format, int target, int mipmap)
1144 {
1145    GET_CURRENT_CONTEXT(ctx);
1146    XMesaBuffer b;
1147 
1148    assert(v);
1149 
1150    b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap);
1151    if (!b)
1152       return NULL;
1153 
1154    /* get pixmap size */
1155    xmesa_get_window_size(v->display, b, &b->width, &b->height);
1156 
1157    if (target == 0) {
1158       /* examine dims */
1159       if (ctx->Extensions.ARB_texture_non_power_of_two) {
1160          target = GLX_TEXTURE_2D_EXT;
1161       }
1162       else if (   util_bitcount(b->width)  == 1
1163                && util_bitcount(b->height) == 1) {
1164          /* power of two size */
1165          if (b->height == 1) {
1166             target = GLX_TEXTURE_1D_EXT;
1167          }
1168          else {
1169             target = GLX_TEXTURE_2D_EXT;
1170          }
1171       }
1172       else if (ctx->Extensions.NV_texture_rectangle) {
1173          target = GLX_TEXTURE_RECTANGLE_EXT;
1174       }
1175       else {
1176          /* non power of two textures not supported */
1177          XMesaDestroyBuffer(b);
1178          return 0;
1179       }
1180    }
1181 
1182    b->TextureTarget = target;
1183    b->TextureFormat = format;
1184    b->TextureMipmap = mipmap;
1185 
1186    if (!initialize_visual_and_buffer(v, b, (Drawable) p, cmap)) {
1187       xmesa_free_buffer(b);
1188       return NULL;
1189    }
1190 
1191    return b;
1192 }
1193 
1194 
1195 
1196 XMesaBuffer
XMesaCreatePBuffer(XMesaVisual v,Colormap cmap,unsigned int width,unsigned int height)1197 XMesaCreatePBuffer(XMesaVisual v, Colormap cmap,
1198                    unsigned int width, unsigned int height)
1199 {
1200    Window root;
1201    Drawable drawable;  /* X Pixmap Drawable */
1202    XMesaBuffer b;
1203 
1204    /* allocate pixmap for front buffer */
1205    root = RootWindow( v->display, v->visinfo->screen );
1206    drawable = XCreatePixmap(v->display, root, width, height,
1207                             v->visinfo->depth);
1208    if (!drawable)
1209       return NULL;
1210 
1211    b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
1212    if (!b)
1213       return NULL;
1214 
1215    if (!initialize_visual_and_buffer(v, b, drawable, cmap)) {
1216       xmesa_free_buffer(b);
1217       return NULL;
1218    }
1219 
1220    return b;
1221 }
1222 
1223 
1224 
1225 /*
1226  * Deallocate an XMesaBuffer structure and all related info.
1227  */
1228 PUBLIC void
XMesaDestroyBuffer(XMesaBuffer b)1229 XMesaDestroyBuffer(XMesaBuffer b)
1230 {
1231    xmesa_free_buffer(b);
1232 }
1233 
1234 
1235 /**
1236  * Notify the binding context to validate the buffer.
1237  */
1238 void
xmesa_notify_invalid_buffer(XMesaBuffer b)1239 xmesa_notify_invalid_buffer(XMesaBuffer b)
1240 {
1241    p_atomic_inc(&b->stfb->stamp);
1242 }
1243 
1244 
1245 /**
1246  * Query the current drawable size and notify the binding context.
1247  */
1248 void
xmesa_check_buffer_size(XMesaBuffer b)1249 xmesa_check_buffer_size(XMesaBuffer b)
1250 {
1251    GLuint old_width, old_height;
1252 
1253    if (!b)
1254       return;
1255 
1256    if (b->type == PBUFFER)
1257       return;
1258 
1259    old_width = b->width;
1260    old_height = b->height;
1261 
1262    xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height);
1263 
1264    if (b->width != old_width || b->height != old_height)
1265       xmesa_notify_invalid_buffer(b);
1266 }
1267 
1268 
1269 /*
1270  * Bind buffer b to context c and make c the current rendering context.
1271  */
1272 PUBLIC
XMesaMakeCurrent2(XMesaContext c,XMesaBuffer drawBuffer,XMesaBuffer readBuffer)1273 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
1274                              XMesaBuffer readBuffer )
1275 {
1276    XMesaContext old_ctx = XMesaGetCurrentContext();
1277 
1278    if (old_ctx && old_ctx != c) {
1279       XMesaFlush(old_ctx);
1280       old_ctx->xm_buffer = NULL;
1281       old_ctx->xm_read_buffer = NULL;
1282    }
1283 
1284    if (c) {
1285       if (!drawBuffer != !readBuffer) {
1286          return GL_FALSE;  /* must specify zero or two buffers! */
1287       }
1288 
1289       if (c == old_ctx &&
1290 	  c->xm_buffer == drawBuffer &&
1291 	  c->xm_read_buffer == readBuffer)
1292 	 return GL_TRUE;
1293 
1294       xmesa_check_buffer_size(drawBuffer);
1295       if (readBuffer != drawBuffer)
1296          xmesa_check_buffer_size(readBuffer);
1297 
1298       c->xm_buffer = drawBuffer;
1299       c->xm_read_buffer = readBuffer;
1300 
1301       stapi->make_current(stapi, c->st,
1302                           drawBuffer ? drawBuffer->stfb : NULL,
1303                           readBuffer ? readBuffer->stfb : NULL);
1304 
1305       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
1306       if (drawBuffer)
1307          drawBuffer->wasCurrent = GL_TRUE;
1308    }
1309    else {
1310       /* Detach */
1311       stapi->make_current(stapi, NULL, NULL, NULL);
1312 
1313    }
1314    return GL_TRUE;
1315 }
1316 
1317 
1318 /*
1319  * Unbind the context c from its buffer.
1320  */
XMesaUnbindContext(XMesaContext c)1321 GLboolean XMesaUnbindContext( XMesaContext c )
1322 {
1323    /* A no-op for XFree86 integration purposes */
1324    return GL_TRUE;
1325 }
1326 
1327 
XMesaGetCurrentContext(void)1328 XMesaContext XMesaGetCurrentContext( void )
1329 {
1330    struct st_context_iface *st = stapi->get_current(stapi);
1331    return (XMesaContext) (st) ? st->st_manager_private : NULL;
1332 }
1333 
1334 
1335 
1336 /**
1337  * Swap front and back color buffers and have winsys display front buffer.
1338  * If there's no front color buffer no swap actually occurs.
1339  */
1340 PUBLIC
XMesaSwapBuffers(XMesaBuffer b)1341 void XMesaSwapBuffers( XMesaBuffer b )
1342 {
1343    XMesaContext xmctx = XMesaGetCurrentContext();
1344 
1345    /* Need to draw HUD before flushing */
1346    if (xmctx && xmctx->hud) {
1347       struct pipe_resource *back =
1348          xmesa_get_framebuffer_resource(b->stfb, ST_ATTACHMENT_BACK_LEFT);
1349       hud_run(xmctx->hud, NULL, back);
1350    }
1351 
1352    if (xmctx && xmctx->xm_buffer == b) {
1353       xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
1354    }
1355 
1356    xmesa_swap_st_framebuffer(b->stfb);
1357 }
1358 
1359 
1360 
1361 /*
1362  * Copy sub-region of back buffer to front buffer
1363  */
XMesaCopySubBuffer(XMesaBuffer b,int x,int y,int width,int height)1364 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
1365 {
1366    XMesaContext xmctx = XMesaGetCurrentContext();
1367 
1368    xmctx->st->flush( xmctx->st, ST_FLUSH_FRONT, NULL, NULL, NULL);
1369 
1370    xmesa_copy_st_framebuffer(b->stfb,
1371          ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT,
1372          x, b->height - y - height, width, height);
1373 }
1374 
1375 
1376 
XMesaFlush(XMesaContext c)1377 void XMesaFlush( XMesaContext c )
1378 {
1379    if (c && c->xm_visual->display) {
1380       XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display);
1381       struct pipe_fence_handle *fence = NULL;
1382 
1383       c->st->flush(c->st, ST_FLUSH_FRONT, &fence, NULL, NULL);
1384       if (fence) {
1385          xmdpy->screen->fence_finish(xmdpy->screen, NULL, fence,
1386                                      PIPE_TIMEOUT_INFINITE);
1387          xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL);
1388       }
1389       XFlush( c->xm_visual->display );
1390    }
1391 }
1392 
1393 
1394 
1395 
1396 
XMesaFindBuffer(Display * dpy,Drawable d)1397 XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d )
1398 {
1399    XMesaBuffer b;
1400    for (b = XMesaBufferList; b; b = b->Next) {
1401       if (b->ws.drawable == d && b->xm_visual->display == dpy) {
1402          return b;
1403       }
1404    }
1405    return NULL;
1406 }
1407 
1408 
1409 /**
1410  * Free/destroy all XMesaBuffers associated with given display.
1411  */
xmesa_destroy_buffers_on_display(Display * dpy)1412 void xmesa_destroy_buffers_on_display(Display *dpy)
1413 {
1414    XMesaBuffer b, next;
1415    for (b = XMesaBufferList; b; b = next) {
1416       next = b->Next;
1417       if (b->xm_visual->display == dpy) {
1418          xmesa_free_buffer(b);
1419          /* delete head of list? */
1420          if (XMesaBufferList == b) {
1421             XMesaBufferList = next;
1422          }
1423       }
1424    }
1425 }
1426 
1427 
1428 /*
1429  * Look for XMesaBuffers whose X window has been destroyed.
1430  * Deallocate any such XMesaBuffers.
1431  */
XMesaGarbageCollect(void)1432 void XMesaGarbageCollect( void )
1433 {
1434    XMesaBuffer b, next;
1435    for (b=XMesaBufferList; b; b=next) {
1436       next = b->Next;
1437       if (b->xm_visual &&
1438           b->xm_visual->display &&
1439           b->ws.drawable &&
1440           b->type == WINDOW) {
1441          XSync(b->xm_visual->display, False);
1442          if (!window_exists( b->xm_visual->display, b->ws.drawable )) {
1443             /* found a dead window, free the ancillary info */
1444             XMesaDestroyBuffer( b );
1445          }
1446       }
1447    }
1448 }
1449 
1450 
xmesa_attachment_type(int glx_attachment)1451 static enum st_attachment_type xmesa_attachment_type(int glx_attachment)
1452 {
1453    switch(glx_attachment) {
1454       case GLX_FRONT_LEFT_EXT:
1455          return ST_ATTACHMENT_FRONT_LEFT;
1456       case GLX_FRONT_RIGHT_EXT:
1457          return ST_ATTACHMENT_FRONT_RIGHT;
1458       case GLX_BACK_LEFT_EXT:
1459          return ST_ATTACHMENT_BACK_LEFT;
1460       case GLX_BACK_RIGHT_EXT:
1461          return ST_ATTACHMENT_BACK_RIGHT;
1462       default:
1463          assert(0);
1464          return ST_ATTACHMENT_FRONT_LEFT;
1465    }
1466 }
1467 
1468 
1469 PUBLIC void
XMesaBindTexImage(Display * dpy,XMesaBuffer drawable,int buffer,const int * attrib_list)1470 XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer,
1471                   const int *attrib_list)
1472 {
1473    struct st_context_iface *st = stapi->get_current(stapi);
1474    struct st_framebuffer_iface* stfbi = drawable->stfb;
1475    struct pipe_resource *res;
1476    int x, y, w, h;
1477    enum st_attachment_type st_attachment = xmesa_attachment_type(buffer);
1478 
1479    x = 0;
1480    y = 0;
1481    w = drawable->width;
1482    h = drawable->height;
1483 
1484    /* We need to validate our attachments before using them,
1485     * in case the texture doesn't exist yet. */
1486    xmesa_st_framebuffer_validate_textures(stfbi, w, h, 1 << st_attachment);
1487    res = xmesa_get_attachment(stfbi, st_attachment);
1488 
1489    if (res) {
1490       struct pipe_context* pipe = xmesa_get_context(stfbi);
1491       enum pipe_format internal_format = res->format;
1492       struct pipe_transfer *tex_xfer;
1493       char *map;
1494       int line, byte_width;
1495       XImage *img;
1496 
1497       internal_format = choose_pixel_format(drawable->xm_visual);
1498 
1499       map = pipe_texture_map(pipe, res,
1500                               0, 0,    /* level, layer */
1501                               PIPE_MAP_WRITE,
1502                               x, y,
1503                               w, h, &tex_xfer);
1504       if (!map)
1505          return;
1506 
1507       /* Grab the XImage that we want to turn into a texture. */
1508       img = XGetImage(dpy,
1509                       drawable->ws.drawable,
1510                       x, y,
1511                       w, h,
1512                       AllPlanes,
1513                       ZPixmap);
1514 
1515       if (!img) {
1516          pipe_texture_unmap(pipe, tex_xfer);
1517          return;
1518       }
1519 
1520       /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. */
1521       byte_width = w * ((img->bits_per_pixel + 7) / 8);
1522 
1523       for (line = 0; line < h; line++)
1524          memcpy(&map[line * tex_xfer->stride],
1525                 &img->data[line * img->bytes_per_line],
1526                 byte_width);
1527 
1528       pipe_texture_unmap(pipe, tex_xfer);
1529 
1530       st->teximage(st,
1531                    ST_TEXTURE_2D,
1532                    0,    /* level */
1533                    internal_format,
1534                    res,
1535                    FALSE /* no mipmap */);
1536 
1537    }
1538 }
1539 
1540 
1541 
1542 PUBLIC void
XMesaReleaseTexImage(Display * dpy,XMesaBuffer drawable,int buffer)1543 XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer)
1544 {
1545 }
1546 
1547 
1548 void
XMesaCopyContext(XMesaContext src,XMesaContext dst,unsigned long mask)1549 XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask)
1550 {
1551    if (dst->st->copy)
1552       dst->st->copy(dst->st, src->st, mask);
1553 }
1554