xm_api.c

Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00055 #ifdef __CYGWIN__
00056 #undef WIN32
00057 #undef __WIN32__
00058 #endif
00059 
00060 #include "glxheader.h"
00061 #include "GL/xmesa.h"
00062 #include "xmesaP.h"
00063 #include "main/context.h"
00064 #include "main/framebuffer.h"
00065 
00066 #include "state_tracker/st_public.h"
00067 #include "state_tracker/st_context.h"
00068 #include "pipe/p_defines.h"
00069 #include "pipe/p_screen.h"
00070 #include "pipe/p_context.h"
00071 
00072 #include "xm_winsys_aub.h"
00073 
00077 pipe_mutex _xmesa_lock;
00078 
00079 
00080 int xmesa_mode;
00081 
00082 
00083 /**********************************************************************/
00084 /*****                     X Utility Functions                    *****/
00085 /**********************************************************************/
00086 
00087 
00091 #ifndef XFree86Server
00092 static int host_byte_order( void )
00093 {
00094    int i = 1;
00095    char *cptr = (char *) &i;
00096    return (*cptr==1) ? LSBFirst : MSBFirst;
00097 }
00098 #endif
00099 
00100 
00107 int xmesa_check_for_xshm( XMesaDisplay *display )
00108 {
00109 #if defined(USE_XSHM) && !defined(XFree86Server)
00110    int major, minor, ignore;
00111    Bool pixmaps;
00112 
00113    if (getenv("SP_NO_RAST")) 
00114       return 0;
00115 
00116    if (getenv("MESA_NOSHM")) {
00117       return 0;
00118    }
00119 
00120    if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
00121       if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) {
00122          return (pixmaps==True) ? 2 : 1;
00123       }
00124       else {
00125          return 0;
00126       }
00127    }
00128    else {
00129       return 0;
00130    }
00131 #else
00132    /* No  XSHM support */
00133    return 0;
00134 #endif
00135 }
00136 
00137 
00146 static int
00147 bits_per_pixel( XMesaVisual xmv )
00148 {
00149 #ifdef XFree86Server
00150    const int depth = xmv->nplanes;
00151    int i;
00152    assert(depth > 0);
00153    for (i = 0; i < screenInfo.numPixmapFormats; i++) {
00154       if (screenInfo.formats[i].depth == depth)
00155          return screenInfo.formats[i].bitsPerPixel;
00156    }
00157    return depth;  /* should never get here, but this should be safe */
00158 #else
00159    XMesaDisplay *dpy = xmv->display;
00160    XMesaVisualInfo visinfo = xmv->visinfo;
00161    XMesaImage *img;
00162    int bitsPerPixel;
00163    /* Create a temporary XImage */
00164    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
00165                        ZPixmap, 0,           /*format, offset*/
00166                        (char*) MALLOC(8),    /*data*/
00167                        1, 1,                 /*width, height*/
00168                        32,                   /*bitmap_pad*/
00169                        0                     /*bytes_per_line*/
00170                      );
00171    assert(img);
00172    /* grab the bits/pixel value */
00173    bitsPerPixel = img->bits_per_pixel;
00174    /* free the XImage */
00175    _mesa_free( img->data );
00176    img->data = NULL;
00177    XMesaDestroyImage( img );
00178    return bitsPerPixel;
00179 #endif
00180 }
00181 
00182 
00183 
00184 /*
00185  * Determine if a given X window ID is valid (window exists).
00186  * Do this by calling XGetWindowAttributes() for the window and
00187  * checking if we catch an X error.
00188  * Input:  dpy - the display
00189  *         win - the window to check for existance
00190  * Return:  GL_TRUE - window exists
00191  *          GL_FALSE - window doesn't exist
00192  */
00193 #ifndef XFree86Server
00194 static GLboolean WindowExistsFlag;
00195 
00196 static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
00197 {
00198    (void) dpy;
00199    if (xerr->error_code == BadWindow) {
00200       WindowExistsFlag = GL_FALSE;
00201    }
00202    return 0;
00203 }
00204 
00205 static GLboolean window_exists( XMesaDisplay *dpy, Window win )
00206 {
00207    XWindowAttributes wa;
00208    int (*old_handler)( XMesaDisplay*, XErrorEvent* );
00209    WindowExistsFlag = GL_TRUE;
00210    old_handler = XSetErrorHandler(window_exists_err_handler);
00211    XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
00212    XSetErrorHandler(old_handler);
00213    return WindowExistsFlag;
00214 }
00215 
00216 static Status
00217 get_drawable_size( XMesaDisplay *dpy, Drawable d, uint *width, uint *height )
00218 {
00219    Window root;
00220    Status stat;
00221    int xpos, ypos;
00222    unsigned int w, h, bw, depth;
00223    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
00224    *width = w;
00225    *height = h;
00226    return stat;
00227 }
00228 #endif
00229 
00230 
00237 static void
00238 xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
00239                       GLuint *width, GLuint *height)
00240 {
00241 #ifdef XFree86Server
00242    *width = MIN2(b->drawable->width, MAX_WIDTH);
00243    *height = MIN2(b->drawable->height, MAX_HEIGHT);
00244 #else
00245    Status stat;
00246 
00247    pipe_mutex_lock(_xmesa_lock);
00248    XSync(b->xm_visual->display, 0); /* added for Chromium */
00249    stat = get_drawable_size(dpy, b->drawable, width, height);
00250    pipe_mutex_unlock(_xmesa_lock);
00251 
00252    if (!stat) {
00253       /* probably querying a window that's recently been destroyed */
00254       _mesa_warning(NULL, "XGetGeometry failed!\n");
00255       *width = *height = 1;
00256    }
00257 #endif
00258 }
00259 
00260 
00266 static GLuint
00267 choose_pixel_format(XMesaVisual v)
00268 {
00269    if (   GET_REDMASK(v)   == 0x0000ff
00270        && GET_GREENMASK(v) == 0x00ff00
00271        && GET_BLUEMASK(v)  == 0xff0000
00272        && v->BitsPerPixel == 32) {
00273       if (CHECK_BYTE_ORDER(v)) {
00274          /* no byteswapping needed */
00275          return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */;
00276       }
00277       else {
00278          return PIPE_FORMAT_R8G8B8A8_UNORM;
00279       }
00280    }
00281    else if (   GET_REDMASK(v)   == 0xff0000
00282             && GET_GREENMASK(v) == 0x00ff00
00283             && GET_BLUEMASK(v)  == 0x0000ff
00284             && v->BitsPerPixel == 32) {
00285       if (CHECK_BYTE_ORDER(v)) {
00286          /* no byteswapping needed */
00287          return PIPE_FORMAT_A8R8G8B8_UNORM;
00288       }
00289       else {
00290          return PIPE_FORMAT_B8G8R8A8_UNORM;
00291       }
00292    }
00293    else if (   GET_REDMASK(v)   == 0xf800
00294             && GET_GREENMASK(v) == 0x07e0
00295             && GET_BLUEMASK(v)  == 0x001f
00296             && CHECK_BYTE_ORDER(v)
00297             && v->BitsPerPixel == 16) {
00298       /* 5-6-5 RGB */
00299       return PIPE_FORMAT_R5G6B5_UNORM;
00300    }
00301 
00302    assert(0);
00303    return 0;
00304 }
00305 
00306 
00307 
00308 /**********************************************************************/
00309 /*****                Linked list of XMesaBuffers                 *****/
00310 /**********************************************************************/
00311 
00312 XMesaBuffer XMesaBufferList = NULL;
00313 
00314 
00326 static XMesaBuffer
00327 create_xmesa_buffer(XMesaDrawable d, BufferType type,
00328                     XMesaVisual vis, XMesaColormap cmap)
00329 {
00330    XMesaBuffer b;
00331    GLframebuffer *fb;
00332    enum pipe_format colorFormat, depthFormat, stencilFormat;
00333    uint width, height;
00334 
00335    ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER);
00336 
00337    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
00338    if (!b)
00339       return NULL;
00340 
00341    b->drawable = d;
00342 
00343    b->xm_visual = vis;
00344    b->type = type;
00345    b->cmap = cmap;
00346 
00347    /* determine PIPE_FORMATs for buffers */
00348    colorFormat = choose_pixel_format(vis);
00349 
00350    if (vis->mesa_visual.depthBits == 0)
00351       depthFormat = PIPE_FORMAT_NONE;
00352 #ifdef GALLIUM_CELL /* XXX temporary for Cell! */
00353    else
00354       depthFormat = PIPE_FORMAT_S8Z24_UNORM;
00355 #else
00356    else if (vis->mesa_visual.depthBits <= 16)
00357       depthFormat = PIPE_FORMAT_Z16_UNORM;
00358    else if (vis->mesa_visual.depthBits <= 24)
00359       depthFormat = PIPE_FORMAT_S8Z24_UNORM;
00360    else
00361       depthFormat = PIPE_FORMAT_Z32_UNORM;
00362 #endif
00363 
00364    if (vis->mesa_visual.stencilBits == 8) {
00365       if (depthFormat == PIPE_FORMAT_S8Z24_UNORM)
00366          stencilFormat = depthFormat;
00367       else
00368          stencilFormat = PIPE_FORMAT_S8_UNORM;
00369    }
00370    else {
00371       /* no stencil */
00372       stencilFormat = PIPE_FORMAT_NONE;
00373       if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) {
00374          /* use 24-bit Z, undefined stencil channel */
00375          depthFormat = PIPE_FORMAT_X8Z24_UNORM;
00376       }
00377    }
00378 
00379 
00380    get_drawable_size(vis->display, d, &width, &height);
00381 
00382    /*
00383     * Create framebuffer, but we'll plug in our own renderbuffers below.
00384     */
00385    b->stfb = st_create_framebuffer(&vis->mesa_visual,
00386                                    colorFormat, depthFormat, stencilFormat,
00387                                    width, height,
00388                                    (void *) b);
00389    fb = &b->stfb->Base;
00390 
00391    /*
00392     * Create scratch XImage for xmesa_display_surface()
00393     */
00394    b->tempImage = XCreateImage(vis->display,
00395                                vis->visinfo->visual,
00396                                vis->visinfo->depth,
00397                                ZPixmap, 0,   /* format, offset */
00398                                NULL,         /* data */
00399                                0, 0,         /* size */
00400                                32,           /* bitmap_pad */
00401                                0);           /* bytes_per_line */
00402 
00403    /* GLX_EXT_texture_from_pixmap */
00404    b->TextureTarget = 0;
00405    b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
00406    b->TextureMipmap = 0;
00407 
00408    /* insert buffer into linked list */
00409    b->Next = XMesaBufferList;
00410    XMesaBufferList = b;
00411 
00412    return b;
00413 }
00414 
00415 
00420 XMesaBuffer
00421 xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
00422 {
00423    XMesaBuffer b;
00424    for (b = XMesaBufferList; b; b = b->Next) {
00425       if (b->xm_visual->display == dpy &&
00426           b->cmap == cmap &&
00427           b != notThis) {
00428          return b;
00429       }
00430    }
00431    return NULL;
00432 }
00433 
00434 
00438 static void
00439 xmesa_free_buffer(XMesaBuffer buffer)
00440 {
00441    XMesaBuffer prev = NULL, b;
00442 
00443    for (b = XMesaBufferList; b; b = b->Next) {
00444       if (b == buffer) {
00445          struct gl_framebuffer *fb = &buffer->stfb->Base;
00446 
00447          /* unlink buffer from list */
00448          if (prev)
00449             prev->Next = buffer->Next;
00450          else
00451             XMesaBufferList = buffer->Next;
00452 
00453          /* mark as delete pending */
00454          fb->DeletePending = GL_TRUE;
00455 
00456          /* Since the X window for the XMesaBuffer is going away, we don't
00457           * want to dereference this pointer in the future.
00458           */
00459          b->drawable = 0;
00460 
00461          buffer->tempImage->data = NULL;
00462          XDestroyImage(buffer->tempImage);
00463 
00464          /* Unreference.  If count = zero we'll really delete the buffer */
00465          _mesa_unreference_framebuffer(&fb);
00466 
00467          XFreeGC(b->xm_visual->display, b->gc);
00468 
00469          free(buffer);
00470 
00471          return;
00472       }
00473       /* continue search */
00474       prev = b;
00475    }
00476    /* buffer not found in XMesaBufferList */
00477    _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
00478 }
00479 
00480 
00481 
00482 /**********************************************************************/
00483 /*****                   Misc Private Functions                   *****/
00484 /**********************************************************************/
00485 
00486 
00497 static GLboolean
00498 initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
00499                              GLboolean rgb_flag, XMesaDrawable window,
00500                              XMesaColormap cmap)
00501 {
00502 #ifdef XFree86Server
00503    int client = (window) ? CLIENT_ID(window->id) : 0;
00504 #endif
00505 
00506    ASSERT(!b || b->xm_visual == v);
00507 
00508    /* Save true bits/pixel */
00509    v->BitsPerPixel = bits_per_pixel(v);
00510    assert(v->BitsPerPixel > 0);
00511 
00512    if (rgb_flag == GL_FALSE) {
00513       /* COLOR-INDEXED WINDOW: not supported*/
00514       return GL_FALSE;
00515    }
00516    else {
00517       /* RGB WINDOW:
00518        * We support RGB rendering into almost any kind of visual.
00519        */
00520       const int xclass = v->mesa_visual.visualType;
00521       if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) {
00522          _mesa_warning(NULL,
00523             "XMesa: RGB mode rendering not supported in given visual.\n");
00524          return GL_FALSE;
00525       }
00526       v->mesa_visual.indexBits = 0;
00527 
00528       if (v->BitsPerPixel == 32) {
00529          /* We use XImages for all front/back buffers.  If an X Window or
00530           * X Pixmap is 32bpp, there's no guarantee that the alpha channel
00531           * will be preserved.  For XImages we're in luck.
00532           */
00533          v->mesa_visual.alphaBits = 8;
00534       }
00535    }
00536 
00537    /*
00538     * If MESA_INFO env var is set print out some debugging info
00539     * which can help Brian figure out what's going on when a user
00540     * reports bugs.
00541     */
00542    if (_mesa_getenv("MESA_INFO")) {
00543       _mesa_printf("X/Mesa visual = %p\n", (void *) v);
00544       _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level);
00545       _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
00546       _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
00547    }
00548 
00549    if (b && window) {
00550       /* these should have been set in create_xmesa_buffer */
00551       ASSERT(b->drawable == window);
00552 
00553       /* Setup for single/double buffering */
00554       if (v->mesa_visual.doubleBufferMode) {
00555          /* Double buffered */
00556          b->shm = xmesa_check_for_xshm( v->display );
00557       }
00558 
00559       /* X11 graphics context */
00560 #ifdef XFree86Server
00561       b->gc = CreateScratchGC(v->display, window->depth);
00562 #else
00563       b->gc = XCreateGC( v->display, window, 0, NULL );
00564 #endif
00565       XMesaSetFunction( v->display, b->gc, GXcopy );
00566    }
00567 
00568    return GL_TRUE;
00569 }
00570 
00571 
00572 
00573 #define NUM_VISUAL_TYPES   6
00574 
00587 static GLint
00588 xmesa_convert_from_x_visual_type( int visualType )
00589 {
00590     static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
00591         GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
00592         GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
00593         GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
00594     };
00595 
00596     return ( (unsigned) visualType < NUM_VISUAL_TYPES )
00597         ? glx_visual_types[ visualType ] : GLX_NONE;
00598 }
00599 
00600 
00601 /**********************************************************************/
00602 /*****                       Public Functions                     *****/
00603 /**********************************************************************/
00604 
00605 
00606 /*
00607  * Create a new X/Mesa visual.
00608  * Input:  display - X11 display
00609  *         visinfo - an XVisualInfo pointer
00610  *         rgb_flag - GL_TRUE = RGB mode,
00611  *                    GL_FALSE = color index mode
00612  *         alpha_flag - alpha buffer requested?
00613  *         db_flag - GL_TRUE = double-buffered,
00614  *                   GL_FALSE = single buffered
00615  *         stereo_flag - stereo visual?
00616  *         ximage_flag - GL_TRUE = use an XImage for back buffer,
00617  *                       GL_FALSE = use an off-screen pixmap for back buffer
00618  *         depth_size - requested bits/depth values, or zero
00619  *         stencil_size - requested bits/stencil values, or zero
00620  *         accum_red_size - requested bits/red accum values, or zero
00621  *         accum_green_size - requested bits/green accum values, or zero
00622  *         accum_blue_size - requested bits/blue accum values, or zero
00623  *         accum_alpha_size - requested bits/alpha accum values, or zero
00624  *         num_samples - number of samples/pixel if multisampling, or zero
00625  *         level - visual level, usually 0
00626  *         visualCaveat - ala the GLX extension, usually GLX_NONE
00627  * Return;  a new XMesaVisual or 0 if error.
00628  */
00629 PUBLIC
00630 XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
00631                                XMesaVisualInfo visinfo,
00632                                GLboolean rgb_flag,
00633                                GLboolean alpha_flag,
00634                                GLboolean db_flag,
00635                                GLboolean stereo_flag,
00636                                GLboolean ximage_flag,
00637                                GLint depth_size,
00638                                GLint stencil_size,
00639                                GLint accum_red_size,
00640                                GLint accum_green_size,
00641                                GLint accum_blue_size,
00642                                GLint accum_alpha_size,
00643                                GLint num_samples,
00644                                GLint level,
00645                                GLint visualCaveat )
00646 {
00647    XMesaVisual v;
00648    GLint red_bits, green_bits, blue_bits, alpha_bits;
00649 
00650 #ifndef XFree86Server
00651    /* For debugging only */
00652    if (_mesa_getenv("MESA_XSYNC")) {
00653       /* This makes debugging X easier.
00654        * In your debugger, set a breakpoint on _XError to stop when an
00655        * X protocol error is generated.
00656        */
00657       XSynchronize( display, 1 );
00658    }
00659 #endif
00660 
00661    v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
00662    if (!v) {
00663       return NULL;
00664    }
00665 
00666    v->display = display;
00667 
00668    /* Save a copy of the XVisualInfo struct because the user may X_mesa_free()
00669     * the struct but we may need some of the information contained in it
00670     * at a later time.
00671     */
00672 #ifndef XFree86Server
00673    v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo));
00674    if(!v->visinfo) {
00675       _mesa_free(v);
00676       return NULL;
00677    }
00678    MEMCPY(v->visinfo, visinfo, sizeof(*visinfo));
00679 #endif
00680 
00681    v->ximage_flag = ximage_flag;
00682 
00683 #ifdef XFree86Server
00684    /* We could calculate these values by ourselves.  nplanes is either the sum
00685     * of the red, green, and blue bits or the number index bits.
00686     * ColormapEntries is either (1U << index_bits) or
00687     * (1U << max(redBits, greenBits, blueBits)).
00688     */
00689    assert(visinfo->nplanes > 0);
00690    v->nplanes = visinfo->nplanes;
00691    v->ColormapEntries = visinfo->ColormapEntries;
00692 
00693    v->mesa_visual.redMask = visinfo->redMask;
00694    v->mesa_visual.greenMask = visinfo->greenMask;
00695    v->mesa_visual.blueMask = visinfo->blueMask;
00696    v->mesa_visual.visualID = visinfo->vid;
00697    v->mesa_visual.screen = 0; /* FIXME: What should be done here? */
00698 #else
00699    v->mesa_visual.redMask = visinfo->red_mask;
00700    v->mesa_visual.greenMask = visinfo->green_mask;
00701    v->mesa_visual.blueMask = visinfo->blue_mask;
00702    v->mesa_visual.visualID = visinfo->visualid;
00703    v->mesa_visual.screen = visinfo->screen;
00704 #endif
00705 
00706 #if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus))
00707    v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class);
00708 #else
00709    v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
00710 #endif
00711 
00712    v->mesa_visual.visualRating = visualCaveat;
00713 
00714    if (alpha_flag)
00715       v->mesa_visual.alphaBits = 8;
00716 
00717    (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 );
00718 
00719    {
00720       const int xclass = v->mesa_visual.visualType;
00721       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
00722          red_bits   = _mesa_bitcount(GET_REDMASK(v));
00723          green_bits = _mesa_bitcount(GET_GREENMASK(v));
00724          blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
00725       }
00726       else {
00727          /* this is an approximation */
00728          int depth;
00729          depth = GET_VISUAL_DEPTH(v);
00730          red_bits = depth / 3;
00731          depth -= red_bits;
00732          green_bits = depth / 2;
00733          depth -= green_bits;
00734          blue_bits = depth;
00735          alpha_bits = 0;
00736          assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
00737       }
00738       alpha_bits = v->mesa_visual.alphaBits;
00739    }
00740 
00741    _mesa_initialize_visual( &v->mesa_visual,
00742                             rgb_flag, db_flag, stereo_flag,
00743                             red_bits, green_bits,
00744                             blue_bits, alpha_bits,
00745                             v->mesa_visual.indexBits,
00746                             depth_size,
00747                             stencil_size,
00748                             accum_red_size, accum_green_size,
00749                             accum_blue_size, accum_alpha_size,
00750                             0 );
00751 
00752    /* XXX minor hack */
00753    v->mesa_visual.level = level;
00754    return v;
00755 }
00756 
00757 
00758 PUBLIC
00759 void XMesaDestroyVisual( XMesaVisual v )
00760 {
00761 #ifndef XFree86Server
00762    _mesa_free(v->visinfo);
00763 #endif
00764    _mesa_free(v);
00765 }
00766 
00767 
00768 
00776 PUBLIC
00777 XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
00778 {
00779    static GLboolean firstTime = GL_TRUE;
00780    struct pipe_context *pipe;
00781    XMesaContext c;
00782    GLcontext *mesaCtx;
00783    uint pf;
00784 
00785    if (firstTime) {
00786       pipe_mutex_init(_xmesa_lock);
00787       firstTime = GL_FALSE;
00788    }
00789 
00790    /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */
00791    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
00792    if (!c)
00793       return NULL;
00794 
00795    pf = choose_pixel_format(v);
00796    assert(pf);
00797 
00798    c->xm_visual = v;
00799    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
00800 
00801    if (!getenv("XM_AUB")) {
00802       xmesa_mode = XMESA_SOFTPIPE;
00803       pipe = xmesa_create_pipe_context( c, pf );
00804    }
00805    else {
00806       xmesa_mode = XMESA_AUB;
00807       pipe = xmesa_create_i965simple(xmesa_get_pipe_winsys_aub(v));
00808    }
00809 
00810    if (pipe == NULL)
00811       goto fail;
00812 
00813    c->st = st_create_context(pipe, &v->mesa_visual,
00814                              share_list ? share_list->st : NULL);
00815    if (c->st == NULL)
00816       goto fail;
00817    
00818    mesaCtx = c->st->ctx;
00819    c->st->ctx->DriverCtx = c;
00820 
00821 #if 00
00822    _mesa_enable_sw_extensions(mesaCtx);
00823    _mesa_enable_1_3_extensions(mesaCtx);
00824    _mesa_enable_1_4_extensions(mesaCtx);
00825    _mesa_enable_1_5_extensions(mesaCtx);
00826    _mesa_enable_2_0_extensions(mesaCtx);
00827 #endif
00828 
00829 #ifdef XFree86Server
00830    /* If we're running in the X server, do bounds checking to prevent
00831     * segfaults and server crashes!
00832     */
00833    mesaCtx->Const.CheckArrayBounds = GL_TRUE;
00834 #endif
00835 
00836    return c;
00837 
00838  fail:
00839    if (c->st)
00840       st_destroy_context(c->st);
00841    else if (pipe)
00842       pipe->destroy(pipe);
00843    FREE(c);
00844    return NULL;
00845 }
00846 
00847 
00848 
00849 PUBLIC
00850 void XMesaDestroyContext( XMesaContext c )
00851 {
00852    struct pipe_screen *screen = c->st->pipe->screen;
00853    st_destroy_context(c->st);
00854    /* FIXME: We should destroy the screen here, but if we do so, surfaces may 
00855     * outlive it, causing segfaults
00856    screen->destroy(screen);
00857    */
00858    _mesa_free(c);
00859 }
00860 
00861 
00862 
00870 PUBLIC XMesaBuffer
00871 XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
00872 {
00873 #ifndef XFree86Server
00874    XWindowAttributes attr;
00875 #endif
00876    XMesaBuffer b;
00877    XMesaColormap cmap;
00878    int depth;
00879 
00880    assert(v);
00881    assert(w);
00882 
00883    /* Check that window depth matches visual depth */
00884 #ifdef XFree86Server
00885    depth = ((XMesaDrawable)w)->depth;
00886 #else
00887    XGetWindowAttributes( v->display, w, &attr );
00888    depth = attr.depth;
00889 #endif
00890    if (GET_VISUAL_DEPTH(v) != depth) {
00891       _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
00892                     GET_VISUAL_DEPTH(v), depth);
00893       return NULL;
00894    }
00895 
00896    /* Find colormap */
00897 #ifdef XFree86Server
00898    cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP);
00899 #else
00900    if (attr.colormap) {
00901       cmap = attr.colormap;
00902    }
00903    else {
00904       _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
00905       /* this is weird, a window w/out a colormap!? */
00906       /* OK, let's just allocate a new one and hope for the best */
00907       cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
00908    }
00909 #endif
00910 
00911    b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
00912    if (!b)
00913       return NULL;
00914 
00915    if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode,
00916                                       (XMesaDrawable) w, cmap )) {
00917       xmesa_free_buffer(b);
00918       return NULL;
00919    }
00920 
00921    return b;
00922 }
00923 
00924 
00925 
00935 PUBLIC XMesaBuffer
00936 XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
00937 {
00938    XMesaBuffer b;
00939 
00940    assert(v);
00941 
00942    b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
00943    if (!b)
00944       return NULL;
00945 
00946    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
00947                                      (XMesaDrawable) p, cmap)) {
00948       xmesa_free_buffer(b);
00949       return NULL;
00950    }
00951 
00952    return b;
00953 }
00954 
00955 
00959 XMesaBuffer
00960 XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
00961                                XMesaColormap cmap,
00962                                int format, int target, int mipmap)
00963 {
00964    GET_CURRENT_CONTEXT(ctx);
00965    XMesaBuffer b;
00966    GLuint width, height;
00967 
00968    assert(v);
00969 
00970    b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
00971    if (!b)
00972       return NULL;
00973 
00974    /* get pixmap size, update framebuffer/renderbuffer dims */
00975    xmesa_get_window_size(v->display, b, &width, &height);
00976    _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height);
00977 
00978    if (target == 0) {
00979       /* examine dims */
00980       if (ctx->Extensions.ARB_texture_non_power_of_two) {
00981          target = GLX_TEXTURE_2D_EXT;
00982       }
00983       else if (   _mesa_bitcount(width)  == 1
00984                && _mesa_bitcount(height) == 1) {
00985          /* power of two size */
00986          if (height == 1) {
00987             target = GLX_TEXTURE_1D_EXT;
00988          }
00989          else {
00990             target = GLX_TEXTURE_2D_EXT;
00991          }
00992       }
00993       else if (ctx->Extensions.NV_texture_rectangle) {
00994          target = GLX_TEXTURE_RECTANGLE_EXT;
00995       }
00996       else {
00997          /* non power of two textures not supported */
00998          XMesaDestroyBuffer(b);
00999          return 0;
01000       }
01001    }
01002 
01003    b->TextureTarget = target;
01004    b->TextureFormat = format;
01005    b->TextureMipmap = mipmap;
01006 
01007    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
01008                                      (XMesaDrawable) p, cmap)) {
01009       xmesa_free_buffer(b);
01010       return NULL;
01011    }
01012 
01013    return b;
01014 }
01015 
01016 
01017 
01018 XMesaBuffer
01019 XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
01020                    unsigned int width, unsigned int height)
01021 {
01022 #ifndef XFree86Server
01023    XMesaWindow root;
01024    XMesaDrawable drawable;  /* X Pixmap Drawable */
01025    XMesaBuffer b;
01026 
01027    /* allocate pixmap for front buffer */
01028    root = RootWindow( v->display, v->visinfo->screen );
01029    drawable = XCreatePixmap(v->display, root, width, height,
01030                             v->visinfo->depth);
01031    if (!drawable)
01032       return NULL;
01033 
01034    b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
01035    if (!b)
01036       return NULL;
01037 
01038    if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode,
01039                                      drawable, cmap)) {
01040       xmesa_free_buffer(b);
01041       return NULL;
01042    }
01043 
01044    return b;
01045 #else
01046    return 0;
01047 #endif
01048 }
01049 
01050 
01051 
01052 /*
01053  * Deallocate an XMesaBuffer structure and all related info.
01054  */
01055 PUBLIC void
01056 XMesaDestroyBuffer(XMesaBuffer b)
01057 {
01058    xmesa_free_buffer(b);
01059 }
01060 
01061 
01072 void
01073 xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
01074 {
01075    GLuint width, height;
01076    xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height);
01077    st_resize_framebuffer(drawBuffer->stfb, width, height);
01078 }
01079 
01080 
01081 /*
01082  * Bind buffer b to context c and make c the current rendering context.
01083  */
01084 GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
01085 {
01086    return XMesaMakeCurrent2( c, b, b );
01087 }
01088 
01089 
01090 /*
01091  * Bind buffer b to context c and make c the current rendering context.
01092  */
01093 PUBLIC
01094 GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
01095                              XMesaBuffer readBuffer )
01096 {
01097    if (c) {
01098       if (!drawBuffer || !readBuffer)
01099          return GL_FALSE;  /* must specify buffers! */
01100 
01101 #if 0
01102       /* XXX restore this optimization */
01103       if (&(c->mesa) == _mesa_get_current_context()
01104           && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
01105           && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
01106           && xmesa_buffer(c->mesa.DrawBuffer)->wasCurrent) {
01107          /* same context and buffer, do nothing */
01108          return GL_TRUE;
01109       }
01110 #endif
01111 
01112       c->xm_buffer = drawBuffer;
01113 
01114       /* Call this periodically to detect when the user has begun using
01115        * GL rendering from multiple threads.
01116        */
01117       _glapi_check_multithread();
01118 
01119       st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb);
01120 
01121       xmesa_check_and_update_buffer_size(c, drawBuffer);
01122       if (readBuffer != drawBuffer)
01123          xmesa_check_and_update_buffer_size(c, readBuffer);
01124 
01125       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
01126       drawBuffer->wasCurrent = GL_TRUE;
01127    }
01128    else {
01129       /* Detach */
01130       st_make_current( NULL, NULL, NULL );
01131    }
01132    return GL_TRUE;
01133 }
01134 
01135 
01136 /*
01137  * Unbind the context c from its buffer.
01138  */
01139 GLboolean XMesaUnbindContext( XMesaContext c )
01140 {
01141    /* A no-op for XFree86 integration purposes */
01142    return GL_TRUE;
01143 }
01144 
01145 
01146 XMesaContext XMesaGetCurrentContext( void )
01147 {
01148    GET_CURRENT_CONTEXT(ctx);
01149    if (ctx) {
01150       XMesaContext xmesa = xmesa_context(ctx);
01151       return xmesa;
01152    }
01153    else {
01154       return 0;
01155    }
01156 }
01157 
01158 
01159 XMesaBuffer XMesaGetCurrentBuffer( void )
01160 {
01161    GET_CURRENT_CONTEXT(ctx);
01162    if (ctx) {
01163       XMesaBuffer xmbuf = xmesa_buffer(ctx->DrawBuffer);
01164       return xmbuf;
01165    }
01166    else {
01167       return 0;
01168    }
01169 }
01170 
01171 
01172 /* New in Mesa 3.1 */
01173 XMesaBuffer XMesaGetCurrentReadBuffer( void )
01174 {
01175    GET_CURRENT_CONTEXT(ctx);
01176    if (ctx) {
01177       return xmesa_buffer(ctx->ReadBuffer);
01178    }
01179    else {
01180       return 0;
01181    }
01182 }
01183 
01184 
01185 #ifdef XFree86Server
01186 PUBLIC
01187 GLboolean XMesaForceCurrent(XMesaContext c)
01188 {
01189    if (c) {
01190       _glapi_set_dispatch(c->mesa.CurrentDispatch);
01191 
01192       if (&(c->mesa) != _mesa_get_current_context()) {
01193          _mesa_make_current(&c->mesa, c->mesa.DrawBuffer, c->mesa.ReadBuffer);
01194       }
01195    }
01196    else {
01197       _mesa_make_current(NULL, NULL, NULL);
01198    }
01199    return GL_TRUE;
01200 }
01201 
01202 
01203 PUBLIC
01204 GLboolean XMesaLoseCurrent(XMesaContext c)
01205 {
01206    (void) c;
01207    _mesa_make_current(NULL, NULL, NULL);
01208    return GL_TRUE;
01209 }
01210 
01211 
01212 PUBLIC
01213 GLboolean XMesaCopyContext( XMesaContext xm_src, XMesaContext xm_dst, GLuint mask )
01214 {
01215    _mesa_copy_context(&xm_src->mesa, &xm_dst->mesa, mask);
01216    return GL_TRUE;
01217 }
01218 #endif /* XFree86Server */
01219 
01220 
01221 #ifndef FX
01222 GLboolean XMesaSetFXmode( GLint mode )
01223 {
01224    (void) mode;
01225    return GL_FALSE;
01226 }
01227 #endif
01228 
01229 
01230 
01231 /*
01232  * Copy the back buffer to the front buffer.  If there's no back buffer
01233  * this is a no-op.
01234  */
01235 PUBLIC
01236 void XMesaSwapBuffers( XMesaBuffer b )
01237 {
01238    struct pipe_surface *surf;
01239 
01240    /* If we're swapping the buffer associated with the current context
01241     * we have to flush any pending rendering commands first.
01242     */
01243    st_notify_swapbuffers(b->stfb);
01244 
01245    surf = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
01246    if (surf) {
01247       if (xmesa_mode == XMESA_AUB)
01248          xmesa_display_aub( surf );
01249       else
01250          xmesa_display_surface(b, surf);
01251    }
01252 
01253    xmesa_check_and_update_buffer_size(NULL, b);
01254 }
01255 
01256 
01257 
01258 /*
01259  * Copy sub-region of back buffer to front buffer
01260  */
01261 void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
01262 {
01263    struct pipe_surface *surf_front
01264       = st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT);
01265    struct pipe_surface *surf_back
01266       = st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT);
01267    struct pipe_context *pipe = NULL; /* XXX fix */
01268 
01269    if (!surf_front || !surf_back)
01270       return;
01271 
01272    pipe->surface_copy(pipe,
01273                       FALSE,
01274                       surf_front, x, y,  /* dest */
01275                       surf_back, x, y,   /* src */
01276                       width, height);
01277 }
01278 
01279 
01280 
01281 /*
01282  * Return the depth buffer associated with an XMesaBuffer.
01283  * Input:  b - the XMesa buffer handle
01284  * Output:  width, height - size of buffer in pixels
01285  *          bytesPerValue - bytes per depth value (2 or 4)
01286  *          buffer - pointer to depth buffer values
01287  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
01288  */
01289 GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
01290                                GLint *bytesPerValue, void **buffer )
01291 {
01292    *width = 0;
01293    *height = 0;
01294    *bytesPerValue = 0;
01295    *buffer = 0;
01296    return GL_FALSE;
01297 }
01298 
01299 
01300 void XMesaFlush( XMesaContext c )
01301 {
01302    if (c && c->xm_visual->display) {
01303 #ifdef XFree86Server
01304       /* NOT_NEEDED */
01305 #else
01306       st_finish(c->st);
01307       XSync( c->xm_visual->display, False );
01308 #endif
01309    }
01310 }
01311 
01312 
01313 
01314 const char *XMesaGetString( XMesaContext c, int name )
01315 {
01316    (void) c;
01317    if (name==XMESA_VERSION) {
01318       return "5.0";
01319    }
01320    else if (name==XMESA_EXTENSIONS) {
01321       return "";
01322    }
01323    else {
01324       return NULL;
01325    }
01326 }
01327 
01328 
01329 
01330 XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
01331 {
01332    XMesaBuffer b;
01333    for (b=XMesaBufferList; b; b=b->Next) {
01334       if (b->drawable == d && b->xm_visual->display == dpy) {
01335          return b;
01336       }
01337    }
01338    return NULL;
01339 }
01340 
01341 
01345 void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
01346 {
01347    XMesaBuffer b, next;
01348    for (b = XMesaBufferList; b; b = next) {
01349       next = b->Next;
01350       if (b->xm_visual->display == dpy) {
01351          xmesa_free_buffer(b);
01352       }
01353    }
01354 }
01355 
01356 
01357 /*
01358  * Look for XMesaBuffers whose X window has been destroyed.
01359  * Deallocate any such XMesaBuffers.
01360  */
01361 void XMesaGarbageCollect( void )
01362 {
01363    XMesaBuffer b, next;
01364    for (b=XMesaBufferList; b; b=next) {
01365       next = b->Next;
01366       if (b->xm_visual &&
01367           b->xm_visual->display &&
01368           b->drawable &&
01369           b->type == WINDOW) {
01370 #ifdef XFree86Server
01371          /* NOT_NEEDED */
01372 #else
01373          XSync(b->xm_visual->display, False);
01374          if (!window_exists( b->xm_visual->display, b->drawable )) {
01375             /* found a dead window, free the ancillary info */
01376             XMesaDestroyBuffer( b );
01377          }
01378 #endif
01379       }
01380    }
01381 }
01382 
01383 
01384 unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
01385                                 GLfloat red, GLfloat green,
01386                                 GLfloat blue, GLfloat alpha )
01387 {
01388    /* no longer supported */
01389    return 0;
01390 }
01391 
01392 
01393 /*
01394  * This is typically called when the window size changes and we need
01395  * to reallocate the buffer's back/depth/stencil/accum buffers.
01396  */
01397 PUBLIC void
01398 XMesaResizeBuffers( XMesaBuffer b )
01399 {
01400    GET_CURRENT_CONTEXT(ctx);
01401    XMesaContext xmctx = xmesa_context(ctx);
01402    if (!xmctx)
01403       return;
01404    xmesa_check_and_update_buffer_size(xmctx, b);
01405 }
01406 
01407 
01408 
01409 
01410 PUBLIC void
01411 XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
01412                   const int *attrib_list)
01413 {
01414 }
01415 
01416 
01417 
01418 PUBLIC void
01419 XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
01420 {
01421 }
01422 

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4