Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile
  39.  * in support for the MIT Shared Memory extension.  If enabled, when you
  40.  * use an Ximage for the back buffer in double buffered mode, the "swap"
  41.  * operation will be faster.  You must also link with -lXext.
  42.  *
  43.  * Byte swapping:  If the Mesa host and the X display use a different
  44.  * byte order then there's some trickiness to be aware of when using
  45.  * XImages.  The byte ordering used for the XImage is that of the X
  46.  * display, not the Mesa host.
  47.  * The color-to-pixel encoding for True/DirectColor must be done
  48.  * according to the display's visual red_mask, green_mask, and blue_mask.
  49.  * If XPutPixel is used to put a pixel into an XImage then XPutPixel will
  50.  * do byte swapping if needed.  If one wants to directly "poke" the pixel
  51.  * into the XImage's buffer then the pixel must be byte swapped first.  In
  52.  * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format
  53.  * and use XPutPixel everywhere except in the implementation of
  54.  * glClear(GL_COLOR_BUFFER_BIT).  We want this function to be fast so
  55.  * instead of using XPutPixel we "poke" our values after byte-swapping
  56.  * the clear pixel value if needed.
  57.  *
  58.  */
  59.  
  60. #ifdef __CYGWIN__
  61. #undef WIN32
  62. #undef __WIN32__
  63. #endif
  64.  
  65. #include <stdio.h>
  66. #include "glxheader.h"
  67. #include "xmesaP.h"
  68. #include "main/api_exec.h"
  69. #include "main/context.h"
  70. #include "main/extensions.h"
  71. #include "main/framebuffer.h"
  72. #include "main/imports.h"
  73. #include "main/macros.h"
  74. #include "main/renderbuffer.h"
  75. #include "main/teximage.h"
  76. #include "main/version.h"
  77. #include "main/vtxfmt.h"
  78. #include "swrast/swrast.h"
  79. #include "swrast/s_renderbuffer.h"
  80. #include "swrast_setup/swrast_setup.h"
  81. #include "vbo/vbo.h"
  82. #include "tnl/tnl.h"
  83. #include "tnl/t_context.h"
  84. #include "tnl/t_pipeline.h"
  85. #include "drivers/common/driverfuncs.h"
  86. #include "drivers/common/meta.h"
  87.  
  88. /**
  89.  * Global X driver lock
  90.  */
  91. mtx_t _xmesa_lock;
  92.  
  93.  
  94.  
  95. /**********************************************************************/
  96. /*****                     X Utility Functions                    *****/
  97. /**********************************************************************/
  98.  
  99.  
  100. /**
  101.  * Return the host's byte order as LSBFirst or MSBFirst ala X.
  102.  */
  103. static int host_byte_order( void )
  104. {
  105.    int i = 1;
  106.    char *cptr = (char *) &i;
  107.    return (*cptr==1) ? LSBFirst : MSBFirst;
  108. }
  109.  
  110.  
  111. /**
  112.  * Check if the X Shared Memory extension is available.
  113.  * Return:  0 = not available
  114.  *          1 = shared XImage support available
  115.  *          2 = shared Pixmap support available also
  116.  */
  117. static int check_for_xshm( XMesaDisplay *display )
  118. {
  119. #if defined(USE_XSHM)
  120.    int ignore;
  121.  
  122.    if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) {
  123.       /* Note: we're no longer calling XShmQueryVersion() here.  It seems
  124.        * to be flakey (triggers a spurious X protocol error when we close
  125.        * one display connection and start using a new one.  XShm has been
  126.        * around a long time and hasn't changed so if MIT_SHM is supported
  127.        * we assume we're good to go.
  128.        */
  129.       return 2;
  130.    }
  131.    else {
  132.       return 0;
  133.    }
  134. #else
  135.    /* No  XSHM support */
  136.    return 0;
  137. #endif
  138. }
  139.  
  140.  
  141. /**
  142.  * Apply gamma correction to an intensity value in [0..max].  Return the
  143.  * new intensity value.
  144.  */
  145. static GLint
  146. gamma_adjust( GLfloat gamma, GLint value, GLint max )
  147. {
  148.    if (gamma == 1.0) {
  149.       return value;
  150.    }
  151.    else {
  152.       double x = (double) value / (double) max;
  153.       return IROUND_POS((GLfloat) max * pow(x, 1.0F/gamma));
  154.    }
  155. }
  156.  
  157.  
  158.  
  159. /**
  160.  * Return the true number of bits per pixel for XImages.
  161.  * For example, if we request a 24-bit deep visual we may actually need/get
  162.  * 32bpp XImages.  This function returns the appropriate bpp.
  163.  * Input:  dpy - the X display
  164.  *         visinfo - desribes the visual to be used for XImages
  165.  * Return:  true number of bits per pixel for XImages
  166.  */
  167. static int
  168. bits_per_pixel( XMesaVisual xmv )
  169. {
  170.    XMesaDisplay *dpy = xmv->display;
  171.    XMesaVisualInfo visinfo = xmv->visinfo;
  172.    XMesaImage *img;
  173.    int bitsPerPixel;
  174.    /* Create a temporary XImage */
  175.    img = XCreateImage( dpy, visinfo->visual, visinfo->depth,
  176.                        ZPixmap, 0,           /*format, offset*/
  177.                        malloc(8),    /*data*/
  178.                        1, 1,                 /*width, height*/
  179.                        32,                   /*bitmap_pad*/
  180.                        0                     /*bytes_per_line*/
  181.                      );
  182.    assert(img);
  183.    /* grab the bits/pixel value */
  184.    bitsPerPixel = img->bits_per_pixel;
  185.    /* free the XImage */
  186.    free( img->data );
  187.    img->data = NULL;
  188.    XMesaDestroyImage( img );
  189.    return bitsPerPixel;
  190. }
  191.  
  192.  
  193.  
  194. /*
  195.  * Determine if a given X window ID is valid (window exists).
  196.  * Do this by calling XGetWindowAttributes() for the window and
  197.  * checking if we catch an X error.
  198.  * Input:  dpy - the display
  199.  *         win - the window to check for existence
  200.  * Return:  GL_TRUE - window exists
  201.  *          GL_FALSE - window doesn't exist
  202.  */
  203. static GLboolean WindowExistsFlag;
  204.  
  205. static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr )
  206. {
  207.    (void) dpy;
  208.    if (xerr->error_code == BadWindow) {
  209.       WindowExistsFlag = GL_FALSE;
  210.    }
  211.    return 0;
  212. }
  213.  
  214. static GLboolean window_exists( XMesaDisplay *dpy, Window win )
  215. {
  216.    XWindowAttributes wa;
  217.    int (*old_handler)( XMesaDisplay*, XErrorEvent* );
  218.    WindowExistsFlag = GL_TRUE;
  219.    old_handler = XSetErrorHandler(window_exists_err_handler);
  220.    XGetWindowAttributes( dpy, win, &wa ); /* dummy request */
  221.    XSetErrorHandler(old_handler);
  222.    return WindowExistsFlag;
  223. }
  224.  
  225. static Status
  226. get_drawable_size( XMesaDisplay *dpy, Drawable d, GLuint *width, GLuint *height )
  227. {
  228.    Window root;
  229.    Status stat;
  230.    int xpos, ypos;
  231.    unsigned int w, h, bw, depth;
  232.    stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
  233.    *width = w;
  234.    *height = h;
  235.    return stat;
  236. }
  237.  
  238.  
  239. /**
  240.  * Return the size of the window (or pixmap) that corresponds to the
  241.  * given XMesaBuffer.
  242.  * \param width  returns width in pixels
  243.  * \param height  returns height in pixels
  244.  */
  245. void
  246. xmesa_get_window_size(XMesaDisplay *dpy, XMesaBuffer b,
  247.                       GLuint *width, GLuint *height)
  248. {
  249.    Status stat;
  250.  
  251.    mtx_lock(&_xmesa_lock);
  252.    XSync(b->xm_visual->display, 0); /* added for Chromium */
  253.    stat = get_drawable_size(dpy, b->frontxrb->pixmap, width, height);
  254.    mtx_unlock(&_xmesa_lock);
  255.  
  256.    if (!stat) {
  257.       /* probably querying a window that's recently been destroyed */
  258.       _mesa_warning(NULL, "XGetGeometry failed!\n");
  259.       *width = *height = 1;
  260.    }
  261. }
  262.  
  263.  
  264.  
  265. /**********************************************************************/
  266. /*****                Linked list of XMesaBuffers                 *****/
  267. /**********************************************************************/
  268.  
  269. XMesaBuffer XMesaBufferList = NULL;
  270.  
  271.  
  272. /**
  273.  * Allocate a new XMesaBuffer object which corresponds to the given drawable.
  274.  * Note that XMesaBuffer is derived from struct gl_framebuffer.
  275.  * The new XMesaBuffer will not have any size (Width=Height=0).
  276.  *
  277.  * \param d  the corresponding X drawable (window or pixmap)
  278.  * \param type  either WINDOW, PIXMAP or PBUFFER, describing d
  279.  * \param vis  the buffer's visual
  280.  * \param cmap  the window's colormap, if known.
  281.  * \return new XMesaBuffer or NULL if any problem
  282.  */
  283. static XMesaBuffer
  284. create_xmesa_buffer(XMesaDrawable d, BufferType type,
  285.                     XMesaVisual vis, XMesaColormap cmap)
  286. {
  287.    XMesaBuffer b;
  288.  
  289.    assert(type == WINDOW || type == PIXMAP || type == PBUFFER);
  290.  
  291.    b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer);
  292.    if (!b)
  293.       return NULL;
  294.  
  295.    b->display = vis->display;
  296.    b->xm_visual = vis;
  297.    b->type = type;
  298.    b->cmap = cmap;
  299.  
  300.    _mesa_initialize_window_framebuffer(&b->mesa_buffer, &vis->mesa_visual);
  301.    b->mesa_buffer.Delete = xmesa_delete_framebuffer;
  302.  
  303.    /*
  304.     * Front renderbuffer
  305.     */
  306.    b->frontxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_FALSE);
  307.    if (!b->frontxrb) {
  308.       free(b);
  309.       return NULL;
  310.    }
  311.    b->frontxrb->Parent = b;
  312.    b->frontxrb->drawable = d;
  313.    b->frontxrb->pixmap = (XMesaPixmap) d;
  314.    _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_FRONT_LEFT,
  315.                           &b->frontxrb->Base.Base);
  316.  
  317.    /*
  318.     * Back renderbuffer
  319.     */
  320.    if (vis->mesa_visual.doubleBufferMode) {
  321.       b->backxrb = xmesa_new_renderbuffer(NULL, 0, vis, GL_TRUE);
  322.       if (!b->backxrb) {
  323.          /* XXX free front xrb too */
  324.          free(b);
  325.          return NULL;
  326.       }
  327.       b->backxrb->Parent = b;
  328.       /* determine back buffer implementation */
  329.       b->db_mode = vis->ximage_flag ? BACK_XIMAGE : BACK_PIXMAP;
  330.      
  331.       _mesa_add_renderbuffer(&b->mesa_buffer, BUFFER_BACK_LEFT,
  332.                              &b->backxrb->Base.Base);
  333.    }
  334.  
  335.    /*
  336.     * Other renderbuffer (depth, stencil, etc)
  337.     */
  338.    _swrast_add_soft_renderbuffers(&b->mesa_buffer,
  339.                                   GL_FALSE,  /* color */
  340.                                   vis->mesa_visual.haveDepthBuffer,
  341.                                   vis->mesa_visual.haveStencilBuffer,
  342.                                   vis->mesa_visual.haveAccumBuffer,
  343.                                   GL_FALSE,  /* software alpha buffer */
  344.                                   vis->mesa_visual.numAuxBuffers > 0 );
  345.  
  346.    /* GLX_EXT_texture_from_pixmap */
  347.    b->TextureTarget = 0;
  348.    b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT;
  349.    b->TextureMipmap = 0;
  350.  
  351.    /* insert buffer into linked list */
  352.    b->Next = XMesaBufferList;
  353.    XMesaBufferList = b;
  354.  
  355.    return b;
  356. }
  357.  
  358.  
  359. /**
  360.  * Find an XMesaBuffer by matching X display and colormap but NOT matching
  361.  * the notThis buffer.
  362.  */
  363. XMesaBuffer
  364. xmesa_find_buffer(XMesaDisplay *dpy, XMesaColormap cmap, XMesaBuffer notThis)
  365. {
  366.    XMesaBuffer b;
  367.    for (b=XMesaBufferList; b; b=b->Next) {
  368.       if (b->display==dpy && b->cmap==cmap && b!=notThis) {
  369.          return b;
  370.       }
  371.    }
  372.    return NULL;
  373. }
  374.  
  375.  
  376. /**
  377.  * Remove buffer from linked list, delete if no longer referenced.
  378.  */
  379. static void
  380. xmesa_free_buffer(XMesaBuffer buffer)
  381. {
  382.    XMesaBuffer prev = NULL, b;
  383.  
  384.    for (b = XMesaBufferList; b; b = b->Next) {
  385.       if (b == buffer) {
  386.          struct gl_framebuffer *fb = &buffer->mesa_buffer;
  387.  
  388.          /* unlink buffer from list */
  389.          if (prev)
  390.             prev->Next = buffer->Next;
  391.          else
  392.             XMesaBufferList = buffer->Next;
  393.  
  394.          /* mark as delete pending */
  395.          fb->DeletePending = GL_TRUE;
  396.  
  397.          /* Since the X window for the XMesaBuffer is going away, we don't
  398.           * want to dereference this pointer in the future.
  399.           */
  400.          b->frontxrb->drawable = 0;
  401.  
  402.          /* Unreference.  If count = zero we'll really delete the buffer */
  403.          _mesa_reference_framebuffer(&fb, NULL);
  404.  
  405.          return;
  406.       }
  407.       /* continue search */
  408.       prev = b;
  409.    }
  410.    /* buffer not found in XMesaBufferList */
  411.    _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n");
  412. }
  413.  
  414.  
  415.  
  416.  
  417. /**********************************************************************/
  418. /*****                   Misc Private Functions                   *****/
  419. /**********************************************************************/
  420.  
  421.  
  422. /**
  423.  * Setup RGB rendering for a window with a True/DirectColor visual.
  424.  */
  425. static void
  426. setup_truecolor(XMesaVisual v, XMesaBuffer buffer, XMesaColormap cmap)
  427. {
  428.    unsigned long rmask, gmask, bmask;
  429.    (void) buffer;
  430.    (void) cmap;
  431.  
  432.    /* Compute red multiplier (mask) and bit shift */
  433.    v->rshift = 0;
  434.    rmask = GET_REDMASK(v);
  435.    while ((rmask & 1)==0) {
  436.       v->rshift++;
  437.       rmask = rmask >> 1;
  438.    }
  439.  
  440.    /* Compute green multiplier (mask) and bit shift */
  441.    v->gshift = 0;
  442.    gmask = GET_GREENMASK(v);
  443.    while ((gmask & 1)==0) {
  444.       v->gshift++;
  445.       gmask = gmask >> 1;
  446.    }
  447.  
  448.    /* Compute blue multiplier (mask) and bit shift */
  449.    v->bshift = 0;
  450.    bmask = GET_BLUEMASK(v);
  451.    while ((bmask & 1)==0) {
  452.       v->bshift++;
  453.       bmask = bmask >> 1;
  454.    }
  455.  
  456.    /*
  457.     * Compute component-to-pixel lookup tables and dithering kernel
  458.     */
  459.    {
  460.       static GLubyte kernel[16] = {
  461.           0*16,  8*16,  2*16, 10*16,
  462.          12*16,  4*16, 14*16,  6*16,
  463.           3*16, 11*16,  1*16,  9*16,
  464.          15*16,  7*16, 13*16,  5*16,
  465.       };
  466.       GLint rBits = _mesa_bitcount(rmask);
  467.       GLint gBits = _mesa_bitcount(gmask);
  468.       GLint bBits = _mesa_bitcount(bmask);
  469.       GLint maxBits;
  470.       GLuint i;
  471.  
  472.       /* convert pixel components in [0,_mask] to RGB values in [0,255] */
  473.       for (i=0; i<=rmask; i++)
  474.          v->PixelToR[i] = (unsigned char) ((i * 255) / rmask);
  475.       for (i=0; i<=gmask; i++)
  476.          v->PixelToG[i] = (unsigned char) ((i * 255) / gmask);
  477.       for (i=0; i<=bmask; i++)
  478.          v->PixelToB[i] = (unsigned char) ((i * 255) / bmask);
  479.  
  480.       /* convert RGB values from [0,255] to pixel components */
  481.  
  482.       for (i=0;i<256;i++) {
  483.          GLint r = gamma_adjust(v->RedGamma,   i, 255);
  484.          GLint g = gamma_adjust(v->GreenGamma, i, 255);
  485.          GLint b = gamma_adjust(v->BlueGamma,  i, 255);
  486.          v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift;
  487.          v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift;
  488.          v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift;
  489.       }
  490.       /* overflow protection */
  491.       for (i=256;i<512;i++) {
  492.          v->RtoPixel[i] = v->RtoPixel[255];
  493.          v->GtoPixel[i] = v->GtoPixel[255];
  494.          v->BtoPixel[i] = v->BtoPixel[255];
  495.       }
  496.  
  497.       /* setup dithering kernel */
  498.       maxBits = rBits;
  499.       if (gBits > maxBits)  maxBits = gBits;
  500.       if (bBits > maxBits)  maxBits = bBits;
  501.       for (i=0;i<16;i++) {
  502.          v->Kernel[i] = kernel[i] >> maxBits;
  503.       }
  504.  
  505.       v->undithered_pf = PF_Truecolor;
  506.       v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor;
  507.    }
  508.  
  509.    /*
  510.     * Now check for TrueColor visuals which we can optimize.
  511.     */
  512.    if (   GET_REDMASK(v)  ==0x0000ff
  513.        && GET_GREENMASK(v)==0x00ff00
  514.        && GET_BLUEMASK(v) ==0xff0000
  515.        && CHECK_BYTE_ORDER(v)
  516.        && v->BitsPerPixel==32
  517.        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
  518.       /* common 32 bpp config used on SGI, Sun */
  519.       v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; /* ABGR */
  520.    }
  521.    else if (GET_REDMASK(v)  == 0xff0000
  522.          && GET_GREENMASK(v)== 0x00ff00
  523.          && GET_BLUEMASK(v) == 0x0000ff
  524.          && CHECK_BYTE_ORDER(v)
  525.          && v->RedGamma == 1.0 && v->GreenGamma == 1.0 && v->BlueGamma == 1.0){
  526.       if (v->BitsPerPixel==32) {
  527.          /* if 32 bpp, and visual indicates 8 bpp alpha channel */
  528.          if (GET_VISUAL_DEPTH(v) == 32 && v->mesa_visual.alphaBits == 8)
  529.             v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; /* ARGB */
  530.          else
  531.             v->undithered_pf = v->dithered_pf = PF_8R8G8B; /* xRGB */
  532.       }
  533.       else if (v->BitsPerPixel == 24) {
  534.          v->undithered_pf = v->dithered_pf = PF_8R8G8B24; /* RGB */
  535.       }
  536.    }
  537.    else if (GET_REDMASK(v)  ==0xf800
  538.        &&   GET_GREENMASK(v)==0x07e0
  539.        &&   GET_BLUEMASK(v) ==0x001f
  540.        && CHECK_BYTE_ORDER(v)
  541.        && v->BitsPerPixel==16
  542.        && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) {
  543.       /* 5-6-5 RGB */
  544.       v->undithered_pf = PF_5R6G5B;
  545.       v->dithered_pf = PF_Dither_5R6G5B;
  546.    }
  547. }
  548.  
  549.  
  550. /**
  551.  * When a context is bound for the first time, we can finally finish
  552.  * initializing the context's visual and buffer information.
  553.  * \param v  the XMesaVisual to initialize
  554.  * \param b  the XMesaBuffer to initialize (may be NULL)
  555.  * \param rgb_flag  TRUE = RGBA mode, FALSE = color index mode
  556.  * \param window  the window/pixmap we're rendering into
  557.  * \param cmap  the colormap associated with the window/pixmap
  558.  * \return GL_TRUE=success, GL_FALSE=failure
  559.  */
  560. static GLboolean
  561. initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b,
  562.                              XMesaDrawable window,
  563.                              XMesaColormap cmap)
  564. {
  565.    const int xclass = v->visualType;
  566.  
  567.  
  568.    assert(!b || b->xm_visual == v);
  569.  
  570.    /* Save true bits/pixel */
  571.    v->BitsPerPixel = bits_per_pixel(v);
  572.    assert(v->BitsPerPixel > 0);
  573.  
  574.    /* RGB WINDOW:
  575.     * We support RGB rendering into almost any kind of visual.
  576.     */
  577.    if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
  578.       setup_truecolor( v, b, cmap );
  579.    }
  580.    else {
  581.       _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual.\n");
  582.       return GL_FALSE;
  583.    }
  584.    v->mesa_visual.indexBits = 0;
  585.  
  586.    if (getenv("MESA_NO_DITHER")) {
  587.       v->dithered_pf = v->undithered_pf;
  588.    }
  589.  
  590.  
  591.    /*
  592.     * If MESA_INFO env var is set print out some debugging info
  593.     * which can help Brian figure out what's going on when a user
  594.     * reports bugs.
  595.     */
  596.    if (getenv("MESA_INFO")) {
  597.       printf("X/Mesa visual = %p\n", (void *) v);
  598.       printf("X/Mesa dithered pf = %u\n", v->dithered_pf);
  599.       printf("X/Mesa undithered pf = %u\n", v->undithered_pf);
  600.       printf("X/Mesa level = %d\n", v->mesa_visual.level);
  601.       printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v));
  602.       printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel);
  603.    }
  604.  
  605.    if (b && window) {
  606.       /* Do window-specific initializations */
  607.  
  608.       /* these should have been set in create_xmesa_buffer */
  609.       assert(b->frontxrb->drawable == window);
  610.       assert(b->frontxrb->pixmap == (XMesaPixmap) window);
  611.  
  612.       /* Setup for single/double buffering */
  613.       if (v->mesa_visual.doubleBufferMode) {
  614.          /* Double buffered */
  615.          b->shm = check_for_xshm( v->display );
  616.       }
  617.  
  618.       /* X11 graphics contexts */
  619.       b->gc = XCreateGC( v->display, window, 0, NULL );
  620.       XMesaSetFunction( v->display, b->gc, GXcopy );
  621.  
  622.       /* cleargc - for glClear() */
  623.       b->cleargc = XCreateGC( v->display, window, 0, NULL );
  624.       XMesaSetFunction( v->display, b->cleargc, GXcopy );
  625.  
  626.       /*
  627.        * Don't generate Graphics Expose/NoExpose events in swapbuffers().
  628.        * Patch contributed by Michael Pichler May 15, 1995.
  629.        */
  630.       {
  631.          XGCValues gcvalues;
  632.          gcvalues.graphics_exposures = False;
  633.          b->swapgc = XCreateGC(v->display, window,
  634.                                GCGraphicsExposures, &gcvalues);
  635.       }
  636.       XMesaSetFunction( v->display, b->swapgc, GXcopy );
  637.    }
  638.  
  639.    return GL_TRUE;
  640. }
  641.  
  642.  
  643.  
  644. /*
  645.  * Convert an RGBA color to a pixel value.
  646.  */
  647. unsigned long
  648. xmesa_color_to_pixel(struct gl_context *ctx,
  649.                      GLubyte r, GLubyte g, GLubyte b, GLubyte a,
  650.                      GLuint pixelFormat)
  651. {
  652.    XMesaContext xmesa = XMESA_CONTEXT(ctx);
  653.    switch (pixelFormat) {
  654.       case PF_Truecolor:
  655.          {
  656.             unsigned long p;
  657.             PACK_TRUECOLOR( p, r, g, b );
  658.             return p;
  659.          }
  660.       case PF_8A8B8G8R:
  661.          return PACK_8A8B8G8R( r, g, b, a );
  662.       case PF_8A8R8G8B:
  663.          return PACK_8A8R8G8B( r, g, b, a );
  664.       case PF_8R8G8B:
  665.          /* fall through */
  666.       case PF_8R8G8B24:
  667.          return PACK_8R8G8B( r, g, b );
  668.       case PF_5R6G5B:
  669.          return PACK_5R6G5B( r, g, b );
  670.       case PF_Dither_True:
  671.          /* fall through */
  672.       case PF_Dither_5R6G5B:
  673.          {
  674.             unsigned long p;
  675.             PACK_TRUEDITHER(p, 1, 0, r, g, b);
  676.             return p;
  677.          }
  678.       default:
  679.          _mesa_problem(ctx, "Bad pixel format in xmesa_color_to_pixel");
  680.    }
  681.    return 0;
  682. }
  683.  
  684.  
  685. #define NUM_VISUAL_TYPES   6
  686.  
  687. /**
  688.  * Convert an X visual type to a GLX visual type.
  689.  *
  690.  * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
  691.  *        to be converted.
  692.  * \return If \c visualType is a valid X visual type, a GLX visual type will
  693.  *         be returned.  Otherwise \c GLX_NONE will be returned.
  694.  *
  695.  * \note
  696.  * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the
  697.  * DRI CVS tree.
  698.  */
  699. static GLint
  700. xmesa_convert_from_x_visual_type( int visualType )
  701. {
  702.     static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
  703.         GLX_STATIC_GRAY,  GLX_GRAY_SCALE,
  704.         GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
  705.         GLX_TRUE_COLOR,   GLX_DIRECT_COLOR
  706.     };
  707.  
  708.     return ( (unsigned) visualType < NUM_VISUAL_TYPES )
  709.         ? glx_visual_types[ visualType ] : GLX_NONE;
  710. }
  711.  
  712.  
  713. /**********************************************************************/
  714. /*****                       Public Functions                     *****/
  715. /**********************************************************************/
  716.  
  717.  
  718. /*
  719.  * Create a new X/Mesa visual.
  720.  * Input:  display - X11 display
  721.  *         visinfo - an XVisualInfo pointer
  722.  *         rgb_flag - GL_TRUE = RGB mode,
  723.  *                    GL_FALSE = color index mode
  724.  *         alpha_flag - alpha buffer requested?
  725.  *         db_flag - GL_TRUE = double-buffered,
  726.  *                   GL_FALSE = single buffered
  727.  *         stereo_flag - stereo visual?
  728.  *         ximage_flag - GL_TRUE = use an XImage for back buffer,
  729.  *                       GL_FALSE = use an off-screen pixmap for back buffer
  730.  *         depth_size - requested bits/depth values, or zero
  731.  *         stencil_size - requested bits/stencil values, or zero
  732.  *         accum_red_size - requested bits/red accum values, or zero
  733.  *         accum_green_size - requested bits/green accum values, or zero
  734.  *         accum_blue_size - requested bits/blue accum values, or zero
  735.  *         accum_alpha_size - requested bits/alpha accum values, or zero
  736.  *         num_samples - number of samples/pixel if multisampling, or zero
  737.  *         level - visual level, usually 0
  738.  *         visualCaveat - ala the GLX extension, usually GLX_NONE
  739.  * Return;  a new XMesaVisual or 0 if error.
  740.  */
  741. PUBLIC
  742. XMesaVisual XMesaCreateVisual( XMesaDisplay *display,
  743.                                XMesaVisualInfo visinfo,
  744.                                GLboolean rgb_flag,
  745.                                GLboolean alpha_flag,
  746.                                GLboolean db_flag,
  747.                                GLboolean stereo_flag,
  748.                                GLboolean ximage_flag,
  749.                                GLint depth_size,
  750.                                GLint stencil_size,
  751.                                GLint accum_red_size,
  752.                                GLint accum_green_size,
  753.                                GLint accum_blue_size,
  754.                                GLint accum_alpha_size,
  755.                                GLint num_samples,
  756.                                GLint level,
  757.                                GLint visualCaveat )
  758. {
  759.    char *gamma;
  760.    XMesaVisual v;
  761.    GLint red_bits, green_bits, blue_bits, alpha_bits;
  762.  
  763.    /* For debugging only */
  764.    if (getenv("MESA_XSYNC")) {
  765.       /* This makes debugging X easier.
  766.        * In your debugger, set a breakpoint on _XError to stop when an
  767.        * X protocol error is generated.
  768.        */
  769.       XSynchronize( display, 1 );
  770.    }
  771.  
  772.    /* Color-index rendering not supported. */
  773.    if (!rgb_flag)
  774.       return NULL;
  775.  
  776.    v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual);
  777.    if (!v) {
  778.       return NULL;
  779.    }
  780.  
  781.    v->display = display;
  782.  
  783.    /* Save a copy of the XVisualInfo struct because the user may Xfree()
  784.     * the struct but we may need some of the information contained in it
  785.     * at a later time.
  786.     */
  787.    v->visinfo = malloc(sizeof(*visinfo));
  788.    if(!v->visinfo) {
  789.       free(v);
  790.       return NULL;
  791.    }
  792.    memcpy(v->visinfo, visinfo, sizeof(*visinfo));
  793.  
  794.    /* check for MESA_GAMMA environment variable */
  795.    gamma = getenv("MESA_GAMMA");
  796.    if (gamma) {
  797.       v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0;
  798.       sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma );
  799.       if (v->RedGamma<=0.0)    v->RedGamma = 1.0;
  800.       if (v->GreenGamma<=0.0)  v->GreenGamma = v->RedGamma;
  801.       if (v->BlueGamma<=0.0)   v->BlueGamma = v->RedGamma;
  802.    }
  803.    else {
  804.       v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0;
  805.    }
  806.  
  807.    v->ximage_flag = ximage_flag;
  808.  
  809.    v->mesa_visual.redMask = visinfo->red_mask;
  810.    v->mesa_visual.greenMask = visinfo->green_mask;
  811.    v->mesa_visual.blueMask = visinfo->blue_mask;
  812.    v->visualID = visinfo->visualid;
  813.    v->screen = visinfo->screen;
  814.  
  815. #if !(defined(__cplusplus) || defined(c_plusplus))
  816.    v->visualType = xmesa_convert_from_x_visual_type(visinfo->class);
  817. #else
  818.    v->visualType = xmesa_convert_from_x_visual_type(visinfo->c_class);
  819. #endif
  820.  
  821.    v->mesa_visual.visualRating = visualCaveat;
  822.  
  823.    if (alpha_flag)
  824.       v->mesa_visual.alphaBits = 8;
  825.  
  826.    (void) initialize_visual_and_buffer( v, NULL, 0, 0 );
  827.  
  828.    {
  829.       const int xclass = v->visualType;
  830.       if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) {
  831.          red_bits   = _mesa_bitcount(GET_REDMASK(v));
  832.          green_bits = _mesa_bitcount(GET_GREENMASK(v));
  833.          blue_bits  = _mesa_bitcount(GET_BLUEMASK(v));
  834.       }
  835.       else {
  836.          /* this is an approximation */
  837.          int depth;
  838.          depth = GET_VISUAL_DEPTH(v);
  839.          red_bits = depth / 3;
  840.          depth -= red_bits;
  841.          green_bits = depth / 2;
  842.          depth -= green_bits;
  843.          blue_bits = depth;
  844.          alpha_bits = 0;
  845.          assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) );
  846.       }
  847.       alpha_bits = v->mesa_visual.alphaBits;
  848.    }
  849.  
  850.    if (!_mesa_initialize_visual(&v->mesa_visual,
  851.                                 db_flag, stereo_flag,
  852.                                 red_bits, green_bits,
  853.                                 blue_bits, alpha_bits,
  854.                                 depth_size,
  855.                                 stencil_size,
  856.                                 accum_red_size, accum_green_size,
  857.                                 accum_blue_size, accum_alpha_size,
  858.                                 0)) {
  859.       free(v);
  860.       return NULL;
  861.    }
  862.  
  863.    /* XXX minor hack */
  864.    v->mesa_visual.level = level;
  865.    return v;
  866. }
  867.  
  868.  
  869. PUBLIC
  870. void XMesaDestroyVisual( XMesaVisual v )
  871. {
  872.    free(v->visinfo);
  873.    free(v);
  874. }
  875.  
  876.  
  877.  
  878. /**
  879.  * Create a new XMesaContext.
  880.  * \param v  the XMesaVisual
  881.  * \param share_list  another XMesaContext with which to share display
  882.  *                    lists or NULL if no sharing is wanted.
  883.  * \return an XMesaContext or NULL if error.
  884.  */
  885. PUBLIC
  886. XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list )
  887. {
  888.    static GLboolean firstTime = GL_TRUE;
  889.    XMesaContext c;
  890.    struct gl_context *mesaCtx;
  891.    struct dd_function_table functions;
  892.    TNLcontext *tnl;
  893.  
  894.    if (firstTime) {
  895.       mtx_init(&_xmesa_lock, mtx_plain);
  896.       firstTime = GL_FALSE;
  897.    }
  898.  
  899.    /* Note: the XMesaContext contains a Mesa struct gl_context struct (inheritance) */
  900.    c = (XMesaContext) CALLOC_STRUCT(xmesa_context);
  901.    if (!c)
  902.       return NULL;
  903.  
  904.    mesaCtx = &(c->mesa);
  905.  
  906.    /* initialize with default driver functions, then plug in XMesa funcs */
  907.    _mesa_init_driver_functions(&functions);
  908.    xmesa_init_driver_functions(v, &functions);
  909.    if (!_mesa_initialize_context(mesaCtx, API_OPENGL_COMPAT, &v->mesa_visual,
  910.                       share_list ? &(share_list->mesa) : (struct gl_context *) NULL,
  911.                       &functions)) {
  912.       free(c);
  913.       return NULL;
  914.    }
  915.  
  916.    /* Enable this to exercise fixed function -> shader translation
  917.     * with software rendering.
  918.     */
  919.    if (0) {
  920.       mesaCtx->VertexProgram._MaintainTnlProgram = GL_TRUE;
  921.       mesaCtx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
  922.    }
  923.  
  924.    _mesa_enable_sw_extensions(mesaCtx);
  925.  
  926. #if ENABLE_EXT_timer_query
  927.     mesaCtx->Extensions.EXT_timer_query = GL_TRUE;
  928. #endif
  929.  
  930.  
  931.    /* finish up xmesa context initializations */
  932.    c->direct = GL_TRUE;
  933.    c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE;
  934.    c->xm_visual = v;
  935.    c->xm_buffer = NULL;   /* set later by XMesaMakeCurrent */
  936.    c->display = v->display;
  937.    c->pixelformat = v->dithered_pf;      /* Dithering is enabled by default */
  938.  
  939.    /* Initialize the software rasterizer and helper modules.
  940.     */
  941.    if (!_swrast_CreateContext( mesaCtx ) ||
  942.        !_vbo_CreateContext( mesaCtx ) ||
  943.        !_tnl_CreateContext( mesaCtx ) ||
  944.        !_swsetup_CreateContext( mesaCtx )) {
  945.       _mesa_free_context_data(&c->mesa);
  946.       free(c);
  947.       return NULL;
  948.    }
  949.  
  950.    /* tnl setup */
  951.    tnl = TNL_CONTEXT(mesaCtx);
  952.    tnl->Driver.RunPipeline = _tnl_run_pipeline;
  953.    /* swrast setup */
  954.    xmesa_register_swrast_functions( mesaCtx );
  955.    _swsetup_Wakeup(mesaCtx);
  956.  
  957.    _mesa_meta_init(mesaCtx);
  958.  
  959.    _mesa_compute_version(mesaCtx);
  960.  
  961.     /* Exec table initialization requires the version to be computed */
  962.    _mesa_initialize_dispatch_tables(mesaCtx);
  963.    _mesa_initialize_vbo_vtxfmt(mesaCtx);
  964.  
  965.    return c;
  966. }
  967.  
  968.  
  969.  
  970. PUBLIC
  971. void XMesaDestroyContext( XMesaContext c )
  972. {
  973.    struct gl_context *mesaCtx = &c->mesa;
  974.  
  975.    _mesa_meta_free( mesaCtx );
  976.  
  977.    _swsetup_DestroyContext( mesaCtx );
  978.    _swrast_DestroyContext( mesaCtx );
  979.    _tnl_DestroyContext( mesaCtx );
  980.    _vbo_DestroyContext( mesaCtx );
  981.    _mesa_free_context_data( mesaCtx );
  982.    free( c );
  983. }
  984.  
  985.  
  986.  
  987. /**
  988.  * Private function for creating an XMesaBuffer which corresponds to an
  989.  * X window or pixmap.
  990.  * \param v  the window's XMesaVisual
  991.  * \param w  the window we're wrapping
  992.  * \return  new XMesaBuffer or NULL if error
  993.  */
  994. PUBLIC XMesaBuffer
  995. XMesaCreateWindowBuffer(XMesaVisual v, XMesaWindow w)
  996. {
  997.    XWindowAttributes attr;
  998.    XMesaBuffer b;
  999.    XMesaColormap cmap;
  1000.    int depth;
  1001.  
  1002.    assert(v);
  1003.    assert(w);
  1004.  
  1005.    /* Check that window depth matches visual depth */
  1006.    XGetWindowAttributes( v->display, w, &attr );
  1007.    depth = attr.depth;
  1008.    if (GET_VISUAL_DEPTH(v) != depth) {
  1009.       _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n",
  1010.                     GET_VISUAL_DEPTH(v), depth);
  1011.       return NULL;
  1012.    }
  1013.  
  1014.    /* Find colormap */
  1015.    if (attr.colormap) {
  1016.       cmap = attr.colormap;
  1017.    }
  1018.    else {
  1019.       _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w);
  1020.       /* this is weird, a window w/out a colormap!? */
  1021.       /* OK, let's just allocate a new one and hope for the best */
  1022.       cmap = XCreateColormap(v->display, w, attr.visual, AllocNone);
  1023.    }
  1024.  
  1025.    b = create_xmesa_buffer((XMesaDrawable) w, WINDOW, v, cmap);
  1026.    if (!b)
  1027.       return NULL;
  1028.  
  1029.    if (!initialize_visual_and_buffer( v, b, (XMesaDrawable) w, cmap )) {
  1030.       xmesa_free_buffer(b);
  1031.       return NULL;
  1032.    }
  1033.  
  1034.    return b;
  1035. }
  1036.  
  1037.  
  1038.  
  1039. /**
  1040.  * Create a new XMesaBuffer from an X pixmap.
  1041.  *
  1042.  * \param v    the XMesaVisual
  1043.  * \param p    the pixmap
  1044.  * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or
  1045.  *             \c GLX_DIRECT_COLOR visual for the pixmap
  1046.  * \returns new XMesaBuffer or NULL if error
  1047.  */
  1048. PUBLIC XMesaBuffer
  1049. XMesaCreatePixmapBuffer(XMesaVisual v, XMesaPixmap p, XMesaColormap cmap)
  1050. {
  1051.    XMesaBuffer b;
  1052.  
  1053.    assert(v);
  1054.  
  1055.    b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
  1056.    if (!b)
  1057.       return NULL;
  1058.  
  1059.    if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) {
  1060.       xmesa_free_buffer(b);
  1061.       return NULL;
  1062.    }
  1063.  
  1064.    return b;
  1065. }
  1066.  
  1067.  
  1068. /**
  1069.  * For GLX_EXT_texture_from_pixmap
  1070.  */
  1071. XMesaBuffer
  1072. XMesaCreatePixmapTextureBuffer(XMesaVisual v, XMesaPixmap p,
  1073.                                XMesaColormap cmap,
  1074.                                int format, int target, int mipmap)
  1075. {
  1076.    GET_CURRENT_CONTEXT(ctx);
  1077.    XMesaBuffer b;
  1078.    GLuint width, height;
  1079.  
  1080.    assert(v);
  1081.  
  1082.    b = create_xmesa_buffer((XMesaDrawable) p, PIXMAP, v, cmap);
  1083.    if (!b)
  1084.       return NULL;
  1085.  
  1086.    /* get pixmap size, update framebuffer/renderbuffer dims */
  1087.    xmesa_get_window_size(v->display, b, &width, &height);
  1088.    _mesa_resize_framebuffer(NULL, &(b->mesa_buffer), width, height);
  1089.  
  1090.    if (target == 0) {
  1091.       /* examine dims */
  1092.       if (ctx->Extensions.ARB_texture_non_power_of_two) {
  1093.          target = GLX_TEXTURE_2D_EXT;
  1094.       }
  1095.       else if (   _mesa_bitcount(width)  == 1
  1096.                && _mesa_bitcount(height) == 1) {
  1097.          /* power of two size */
  1098.          if (height == 1) {
  1099.             target = GLX_TEXTURE_1D_EXT;
  1100.          }
  1101.          else {
  1102.             target = GLX_TEXTURE_2D_EXT;
  1103.          }
  1104.       }
  1105.       else if (ctx->Extensions.NV_texture_rectangle) {
  1106.          target = GLX_TEXTURE_RECTANGLE_EXT;
  1107.       }
  1108.       else {
  1109.          /* non power of two textures not supported */
  1110.          XMesaDestroyBuffer(b);
  1111.          return 0;
  1112.       }
  1113.    }
  1114.  
  1115.    b->TextureTarget = target;
  1116.    b->TextureFormat = format;
  1117.    b->TextureMipmap = mipmap;
  1118.  
  1119.    if (!initialize_visual_and_buffer(v, b, (XMesaDrawable) p, cmap)) {
  1120.       xmesa_free_buffer(b);
  1121.       return NULL;
  1122.    }
  1123.  
  1124.    return b;
  1125. }
  1126.  
  1127.  
  1128.  
  1129. XMesaBuffer
  1130. XMesaCreatePBuffer(XMesaVisual v, XMesaColormap cmap,
  1131.                    unsigned int width, unsigned int height)
  1132. {
  1133.    XMesaWindow root;
  1134.    XMesaDrawable drawable;  /* X Pixmap Drawable */
  1135.    XMesaBuffer b;
  1136.  
  1137.    /* allocate pixmap for front buffer */
  1138.    root = RootWindow( v->display, v->visinfo->screen );
  1139.    drawable = XCreatePixmap(v->display, root, width, height,
  1140.                             v->visinfo->depth);
  1141.    if (!drawable)
  1142.       return NULL;
  1143.  
  1144.    b = create_xmesa_buffer(drawable, PBUFFER, v, cmap);
  1145.    if (!b)
  1146.       return NULL;
  1147.  
  1148.    if (!initialize_visual_and_buffer(v, b, drawable, cmap)) {
  1149.       xmesa_free_buffer(b);
  1150.       return NULL;
  1151.    }
  1152.  
  1153.    return b;
  1154. }
  1155.  
  1156.  
  1157.  
  1158. /*
  1159.  * Deallocate an XMesaBuffer structure and all related info.
  1160.  */
  1161. PUBLIC void
  1162. XMesaDestroyBuffer(XMesaBuffer b)
  1163. {
  1164.    xmesa_free_buffer(b);
  1165. }
  1166.  
  1167.  
  1168. /**
  1169.  * Query the current window size and update the corresponding struct gl_framebuffer
  1170.  * and all attached renderbuffers.
  1171.  * Called when:
  1172.  *  1. the first time a buffer is bound to a context.
  1173.  *  2. from glViewport to poll for window size changes
  1174.  *  3. from the XMesaResizeBuffers() API function.
  1175.  * Note: it's possible (and legal) for xmctx to be NULL.  That can happen
  1176.  * when resizing a buffer when no rendering context is bound.
  1177.  */
  1178. void
  1179. xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer)
  1180. {
  1181.    GLuint width, height;
  1182.    xmesa_get_window_size(drawBuffer->display, drawBuffer, &width, &height);
  1183.    if (drawBuffer->mesa_buffer.Width != width ||
  1184.        drawBuffer->mesa_buffer.Height != height) {
  1185.       struct gl_context *ctx = xmctx ? &xmctx->mesa : NULL;
  1186.       _mesa_resize_framebuffer(ctx, &(drawBuffer->mesa_buffer), width, height);
  1187.    }
  1188. }
  1189.  
  1190.  
  1191. /*
  1192.  * Bind buffer b to context c and make c the current rendering context.
  1193.  */
  1194. GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b )
  1195. {
  1196.    return XMesaMakeCurrent2( c, b, b );
  1197. }
  1198.  
  1199.  
  1200. /*
  1201.  * Bind buffer b to context c and make c the current rendering context.
  1202.  */
  1203. PUBLIC
  1204. GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer,
  1205.                              XMesaBuffer readBuffer )
  1206. {
  1207.    if (c) {
  1208.       if (!drawBuffer || !readBuffer)
  1209.          return GL_FALSE;  /* must specify buffers! */
  1210.  
  1211.       if (&(c->mesa) == _mesa_get_current_context()
  1212.           && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer
  1213.           && c->mesa.ReadBuffer == &readBuffer->mesa_buffer
  1214.           && XMESA_BUFFER(c->mesa.DrawBuffer)->wasCurrent) {
  1215.          /* same context and buffer, do nothing */
  1216.          return GL_TRUE;
  1217.       }
  1218.  
  1219.       c->xm_buffer = drawBuffer;
  1220.  
  1221.       /* Call this periodically to detect when the user has begun using
  1222.        * GL rendering from multiple threads.
  1223.        */
  1224.       _glapi_check_multithread();
  1225.  
  1226.       xmesa_check_and_update_buffer_size(c, drawBuffer);
  1227.       if (readBuffer != drawBuffer)
  1228.          xmesa_check_and_update_buffer_size(c, readBuffer);
  1229.  
  1230.       _mesa_make_current(&(c->mesa),
  1231.                          &drawBuffer->mesa_buffer,
  1232.                          &readBuffer->mesa_buffer);
  1233.  
  1234.       /*
  1235.        * Must recompute and set these pixel values because colormap
  1236.        * can be different for different windows.
  1237.        */
  1238.       c->clearpixel = xmesa_color_to_pixel( &c->mesa,
  1239.                                             c->clearcolor[0],
  1240.                                             c->clearcolor[1],
  1241.                                             c->clearcolor[2],
  1242.                                             c->clearcolor[3],
  1243.                                             c->xm_visual->undithered_pf);
  1244.       XMesaSetForeground(c->display, drawBuffer->cleargc, c->clearpixel);
  1245.  
  1246.       /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */
  1247.       drawBuffer->wasCurrent = GL_TRUE;
  1248.    }
  1249.    else {
  1250.       /* Detach */
  1251.       _mesa_make_current( NULL, NULL, NULL );
  1252.    }
  1253.    return GL_TRUE;
  1254. }
  1255.  
  1256.  
  1257. /*
  1258.  * Unbind the context c from its buffer.
  1259.  */
  1260. GLboolean XMesaUnbindContext( XMesaContext c )
  1261. {
  1262.    /* A no-op for XFree86 integration purposes */
  1263.    return GL_TRUE;
  1264. }
  1265.  
  1266.  
  1267. XMesaContext XMesaGetCurrentContext( void )
  1268. {
  1269.    GET_CURRENT_CONTEXT(ctx);
  1270.    if (ctx) {
  1271.       XMesaContext xmesa = XMESA_CONTEXT(ctx);
  1272.       return xmesa;
  1273.    }
  1274.    else {
  1275.       return 0;
  1276.    }
  1277. }
  1278.  
  1279.  
  1280. XMesaBuffer XMesaGetCurrentBuffer( void )
  1281. {
  1282.    GET_CURRENT_CONTEXT(ctx);
  1283.    if (ctx) {
  1284.       XMesaBuffer xmbuf = XMESA_BUFFER(ctx->DrawBuffer);
  1285.       return xmbuf;
  1286.    }
  1287.    else {
  1288.       return 0;
  1289.    }
  1290. }
  1291.  
  1292.  
  1293. /* New in Mesa 3.1 */
  1294. XMesaBuffer XMesaGetCurrentReadBuffer( void )
  1295. {
  1296.    GET_CURRENT_CONTEXT(ctx);
  1297.    if (ctx) {
  1298.       return XMESA_BUFFER(ctx->ReadBuffer);
  1299.    }
  1300.    else {
  1301.       return 0;
  1302.    }
  1303. }
  1304.  
  1305.  
  1306.  
  1307. GLboolean XMesaSetFXmode( GLint mode )
  1308. {
  1309.    (void) mode;
  1310.    return GL_FALSE;
  1311. }
  1312.  
  1313.  
  1314.  
  1315. /*
  1316.  * Copy the back buffer to the front buffer.  If there's no back buffer
  1317.  * this is a no-op.
  1318.  */
  1319. PUBLIC
  1320. void XMesaSwapBuffers( XMesaBuffer b )
  1321. {
  1322.    GET_CURRENT_CONTEXT(ctx);
  1323.  
  1324.    if (!b->backxrb) {
  1325.       /* single buffered */
  1326.       return;
  1327.    }
  1328.  
  1329.    /* If we're swapping the buffer associated with the current context
  1330.     * we have to flush any pending rendering commands first.
  1331.     */
  1332.    if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
  1333.       _mesa_notifySwapBuffers(ctx);
  1334.  
  1335.    if (b->db_mode) {
  1336.       if (b->backxrb->ximage) {
  1337.          /* Copy Ximage (back buf) from client memory to server window */
  1338. #if defined(USE_XSHM)
  1339.          if (b->shm) {
  1340.             /*mtx_lock(&_xmesa_lock);*/
  1341.             XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
  1342.                           b->swapgc,
  1343.                           b->backxrb->ximage, 0, 0,
  1344.                           0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
  1345.                           False );
  1346.             /*mtx_unlock(&_xmesa_lock);*/
  1347.          }
  1348.          else
  1349. #endif
  1350.          {
  1351.             /*mtx_lock(&_xmesa_lock);*/
  1352.             XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
  1353.                            b->swapgc,
  1354.                            b->backxrb->ximage, 0, 0,
  1355.                            0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height );
  1356.             /*mtx_unlock(&_xmesa_lock);*/
  1357.          }
  1358.       }
  1359.       else if (b->backxrb->pixmap) {
  1360.          /* Copy pixmap (back buf) to window (front buf) on server */
  1361.          /*mtx_lock(&_xmesa_lock);*/
  1362.          XMesaCopyArea( b->xm_visual->display,
  1363.                         b->backxrb->pixmap,   /* source drawable */
  1364.                         b->frontxrb->drawable,  /* dest. drawable */
  1365.                         b->swapgc,
  1366.                         0, 0, b->mesa_buffer.Width, b->mesa_buffer.Height,
  1367.                         0, 0                 /* dest region */
  1368.                       );
  1369.          /*mtx_unlock(&_xmesa_lock);*/
  1370.       }
  1371.    }
  1372.    XSync( b->xm_visual->display, False );
  1373. }
  1374.  
  1375.  
  1376.  
  1377. /*
  1378.  * Copy sub-region of back buffer to front buffer
  1379.  */
  1380. void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height )
  1381. {
  1382.    GET_CURRENT_CONTEXT(ctx);
  1383.  
  1384.    /* If we're swapping the buffer associated with the current context
  1385.     * we have to flush any pending rendering commands first.
  1386.     */
  1387.    if (ctx && ctx->DrawBuffer == &(b->mesa_buffer))
  1388.       _mesa_notifySwapBuffers(ctx);
  1389.  
  1390.    if (!b->backxrb) {
  1391.       /* single buffered */
  1392.       return;
  1393.    }
  1394.  
  1395.    if (b->db_mode) {
  1396.       int yTop = b->mesa_buffer.Height - y - height;
  1397.       if (b->backxrb->ximage) {
  1398.          /* Copy Ximage from host's memory to server's window */
  1399. #if defined(USE_XSHM)
  1400.          if (b->shm) {
  1401.             /* XXX assuming width and height aren't too large! */
  1402.             XShmPutImage( b->xm_visual->display, b->frontxrb->drawable,
  1403.                           b->swapgc,
  1404.                           b->backxrb->ximage, x, yTop,
  1405.                           x, yTop, width, height, False );
  1406.             /* wait for finished event??? */
  1407.          }
  1408.          else
  1409. #endif
  1410.          {
  1411.             /* XXX assuming width and height aren't too large! */
  1412.             XMesaPutImage( b->xm_visual->display, b->frontxrb->drawable,
  1413.                            b->swapgc,
  1414.                            b->backxrb->ximage, x, yTop,
  1415.                            x, yTop, width, height );
  1416.          }
  1417.       }
  1418.       else {
  1419.          /* Copy pixmap to window on server */
  1420.          XMesaCopyArea( b->xm_visual->display,
  1421.                         b->backxrb->pixmap,           /* source drawable */
  1422.                         b->frontxrb->drawable,        /* dest. drawable */
  1423.                         b->swapgc,
  1424.                         x, yTop, width, height,  /* source region */
  1425.                         x, yTop                  /* dest region */
  1426.                       );
  1427.       }
  1428.    }
  1429. }
  1430.  
  1431.  
  1432. /*
  1433.  * Return a pointer to the XMesa backbuffer Pixmap or XImage.  This function
  1434.  * is a way to get "under the hood" of X/Mesa so one can manipulate the
  1435.  * back buffer directly.
  1436.  * Output:  pixmap - pointer to back buffer's Pixmap, or 0
  1437.  *          ximage - pointer to back buffer's XImage, or NULL
  1438.  * Return:  GL_TRUE = context is double buffered
  1439.  *          GL_FALSE = context is single buffered
  1440.  */
  1441. GLboolean XMesaGetBackBuffer( XMesaBuffer b,
  1442.                               XMesaPixmap *pixmap,
  1443.                               XMesaImage **ximage )
  1444. {
  1445.    if (b->db_mode) {
  1446.       if (pixmap)
  1447.          *pixmap = b->backxrb->pixmap;
  1448.       if (ximage)
  1449.          *ximage = b->backxrb->ximage;
  1450.       return GL_TRUE;
  1451.    }
  1452.    else {
  1453.       *pixmap = 0;
  1454.       *ximage = NULL;
  1455.       return GL_FALSE;
  1456.    }
  1457. }
  1458.  
  1459.  
  1460. /*
  1461.  * Return the depth buffer associated with an XMesaBuffer.
  1462.  * Input:  b - the XMesa buffer handle
  1463.  * Output:  width, height - size of buffer in pixels
  1464.  *          bytesPerValue - bytes per depth value (2 or 4)
  1465.  *          buffer - pointer to depth buffer values
  1466.  * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
  1467.  */
  1468. GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height,
  1469.                                GLint *bytesPerValue, void **buffer )
  1470. {
  1471.    struct gl_renderbuffer *rb
  1472.       = b->mesa_buffer.Attachment[BUFFER_DEPTH].Renderbuffer;
  1473.    struct xmesa_renderbuffer *xrb = xmesa_renderbuffer(rb);
  1474.  
  1475.    if (!xrb || !xrb->Base.Buffer) {
  1476.       *width = 0;
  1477.       *height = 0;
  1478.       *bytesPerValue = 0;
  1479.       *buffer = 0;
  1480.       return GL_FALSE;
  1481.    }
  1482.    else {
  1483.       *width = b->mesa_buffer.Width;
  1484.       *height = b->mesa_buffer.Height;
  1485.       *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16
  1486.          ? sizeof(GLushort) : sizeof(GLuint);
  1487.       *buffer = (void *) xrb->Base.Buffer;
  1488.       return GL_TRUE;
  1489.    }
  1490. }
  1491.  
  1492.  
  1493. void XMesaFlush( XMesaContext c )
  1494. {
  1495.    if (c && c->xm_visual) {
  1496.       XSync( c->xm_visual->display, False );
  1497.    }
  1498. }
  1499.  
  1500.  
  1501.  
  1502. const char *XMesaGetString( XMesaContext c, int name )
  1503. {
  1504.    (void) c;
  1505.    if (name==XMESA_VERSION) {
  1506.       return "5.0";
  1507.    }
  1508.    else if (name==XMESA_EXTENSIONS) {
  1509.       return "";
  1510.    }
  1511.    else {
  1512.       return NULL;
  1513.    }
  1514. }
  1515.  
  1516.  
  1517.  
  1518. XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d )
  1519. {
  1520.    XMesaBuffer b;
  1521.    for (b=XMesaBufferList; b; b=b->Next) {
  1522.       if (b->frontxrb->drawable == d && b->display == dpy) {
  1523.          return b;
  1524.       }
  1525.    }
  1526.    return NULL;
  1527. }
  1528.  
  1529.  
  1530. /**
  1531.  * Free/destroy all XMesaBuffers associated with given display.
  1532.  */
  1533. void xmesa_destroy_buffers_on_display(XMesaDisplay *dpy)
  1534. {
  1535.    XMesaBuffer b, next;
  1536.    for (b = XMesaBufferList; b; b = next) {
  1537.       next = b->Next;
  1538.       if (b->display == dpy) {
  1539.          xmesa_free_buffer(b);
  1540.       }
  1541.    }
  1542. }
  1543.  
  1544.  
  1545. /*
  1546.  * Look for XMesaBuffers whose X window has been destroyed.
  1547.  * Deallocate any such XMesaBuffers.
  1548.  */
  1549. void XMesaGarbageCollect( XMesaDisplay* dpy )
  1550. {
  1551.    XMesaBuffer b, next;
  1552.    for (b=XMesaBufferList; b; b=next) {
  1553.       next = b->Next;
  1554.       if (b->display && b->display == dpy && b->frontxrb->drawable && b->type == WINDOW) {
  1555.          XSync(b->display, False);
  1556.          if (!window_exists( b->display, b->frontxrb->drawable )) {
  1557.             /* found a dead window, free the ancillary info */
  1558.             XMesaDestroyBuffer( b );
  1559.          }
  1560.       }
  1561.    }
  1562. }
  1563.  
  1564.  
  1565. unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y,
  1566.                                 GLfloat red, GLfloat green,
  1567.                                 GLfloat blue, GLfloat alpha )
  1568. {
  1569.    GLint r = (GLint) (red   * 255.0F);
  1570.    GLint g = (GLint) (green * 255.0F);
  1571.    GLint b = (GLint) (blue  * 255.0F);
  1572.    GLint a = (GLint) (alpha * 255.0F);
  1573.  
  1574.    switch (xmesa->pixelformat) {
  1575.       case PF_Truecolor:
  1576.          {
  1577.             unsigned long p;
  1578.             PACK_TRUECOLOR( p, r, g, b );
  1579.             return p;
  1580.          }
  1581.       case PF_8A8B8G8R:
  1582.          return PACK_8A8B8G8R( r, g, b, a );
  1583.       case PF_8A8R8G8B:
  1584.          return PACK_8A8R8G8B( r, g, b, a );
  1585.       case PF_8R8G8B:
  1586.          return PACK_8R8G8B( r, g, b );
  1587.       case PF_5R6G5B:
  1588.          return PACK_5R6G5B( r, g, b );
  1589.       case PF_Dither_5R6G5B:
  1590.          /* fall through */
  1591.       case PF_Dither_True:
  1592.          {
  1593.             unsigned long p;
  1594.             PACK_TRUEDITHER(p, x, y, r, g, b);
  1595.             return p;
  1596.          }
  1597.       default:
  1598.          _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor");
  1599.    }
  1600.    return 0;
  1601. }
  1602.  
  1603.  
  1604. /*
  1605.  * This is typically called when the window size changes and we need
  1606.  * to reallocate the buffer's back/depth/stencil/accum buffers.
  1607.  */
  1608. PUBLIC void
  1609. XMesaResizeBuffers( XMesaBuffer b )
  1610. {
  1611.    GET_CURRENT_CONTEXT(ctx);
  1612.    XMesaContext xmctx = XMESA_CONTEXT(ctx);
  1613.    if (!xmctx)
  1614.       return;
  1615.    xmesa_check_and_update_buffer_size(xmctx, b);
  1616. }
  1617.  
  1618.  
  1619. static GLint
  1620. xbuffer_to_renderbuffer(int buffer)
  1621. {
  1622.    assert(MAX_AUX_BUFFERS <= 4);
  1623.  
  1624.    switch (buffer) {
  1625.    case GLX_FRONT_LEFT_EXT:
  1626.       return BUFFER_FRONT_LEFT;
  1627.    case GLX_FRONT_RIGHT_EXT:
  1628.       return BUFFER_FRONT_RIGHT;
  1629.    case GLX_BACK_LEFT_EXT:
  1630.       return BUFFER_BACK_LEFT;
  1631.    case GLX_BACK_RIGHT_EXT:
  1632.       return BUFFER_BACK_RIGHT;
  1633.    case GLX_AUX0_EXT:
  1634.       return BUFFER_AUX0;
  1635.    case GLX_AUX1_EXT:
  1636.    case GLX_AUX2_EXT:
  1637.    case GLX_AUX3_EXT:
  1638.    case GLX_AUX4_EXT:
  1639.    case GLX_AUX5_EXT:
  1640.    case GLX_AUX6_EXT:
  1641.    case GLX_AUX7_EXT:
  1642.    case GLX_AUX8_EXT:
  1643.    case GLX_AUX9_EXT:
  1644.    default:
  1645.       /* BadValue error */
  1646.       return -1;
  1647.    }
  1648. }
  1649.  
  1650.  
  1651. PUBLIC void
  1652. XMesaBindTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer,
  1653.                   const int *attrib_list)
  1654. {
  1655. #if 0
  1656.    GET_CURRENT_CONTEXT(ctx);
  1657.    const GLuint unit = ctx->Texture.CurrentUnit;
  1658.    struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
  1659.    struct gl_texture_object *texObj;
  1660. #endif
  1661.    struct gl_renderbuffer *rb;
  1662.    struct xmesa_renderbuffer *xrb;
  1663.    GLint b;
  1664.    XMesaImage *img = NULL;
  1665.    GLboolean freeImg = GL_FALSE;
  1666.  
  1667.    b = xbuffer_to_renderbuffer(buffer);
  1668.    if (b < 0)
  1669.       return;
  1670.  
  1671.    if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_NONE_EXT)
  1672.       return; /* BadMatch error */
  1673.  
  1674.    rb = drawable->mesa_buffer.Attachment[b].Renderbuffer;
  1675.    if (!rb) {
  1676.       /* invalid buffer */
  1677.       return;
  1678.    }
  1679.    xrb = xmesa_renderbuffer(rb);
  1680.  
  1681. #if 0
  1682.    switch (drawable->TextureTarget) {
  1683.    case GLX_TEXTURE_1D_EXT:
  1684.       texObj = texUnit->CurrentTex[TEXTURE_1D_INDEX];
  1685.       break;
  1686.    case GLX_TEXTURE_2D_EXT:
  1687.       texObj = texUnit->CurrentTex[TEXTURE_2D_INDEX];
  1688.       break;
  1689.    case GLX_TEXTURE_RECTANGLE_EXT:
  1690.       texObj = texUnit->CurrentTex[TEXTURE_RECT_INDEX];
  1691.       break;
  1692.    default:
  1693.       return; /* BadMatch error */
  1694.    }
  1695. #endif
  1696.  
  1697.    /*
  1698.     * The following is a quick and simple way to implement
  1699.     * BindTexImage.  The better way is to write some new FetchTexel()
  1700.     * functions which would extract texels from XImages.  We'd still
  1701.     * need to use GetImage when texturing from a Pixmap (front buffer)
  1702.     * but texturing from a back buffer (XImage) would avoid an image
  1703.     * copy.
  1704.     */
  1705.  
  1706.    /* get XImage */
  1707.    if (xrb->pixmap) {
  1708.       img = XMesaGetImage(dpy, xrb->pixmap, 0, 0, rb->Width, rb->Height, ~0L,
  1709.                           ZPixmap);
  1710.       freeImg = GL_TRUE;
  1711.    }
  1712.    else if (xrb->ximage) {
  1713.       img = xrb->ximage;
  1714.    }
  1715.  
  1716.    /* store the XImage as a new texture image */
  1717.    if (img) {
  1718.       GLenum format, type, intFormat;
  1719.       if (img->bits_per_pixel == 32) {
  1720.          format = GL_BGRA;
  1721.          type = GL_UNSIGNED_BYTE;
  1722.          intFormat = GL_RGBA;
  1723.       }
  1724.       else if (img->bits_per_pixel == 24) {
  1725.          format = GL_BGR;
  1726.          type = GL_UNSIGNED_BYTE;
  1727.          intFormat = GL_RGB;
  1728.       }
  1729.       else if (img->bits_per_pixel == 16) {
  1730.          format = GL_BGR;
  1731.          type = GL_UNSIGNED_SHORT_5_6_5;
  1732.          intFormat = GL_RGB;
  1733.       }
  1734.       else {
  1735.          _mesa_problem(NULL, "Unexpected XImage format in XMesaBindTexImage");
  1736.          return;
  1737.       }
  1738.       if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGBA_EXT) {
  1739.          intFormat = GL_RGBA;
  1740.       }
  1741.       else if (drawable->TextureFormat == GLX_TEXTURE_FORMAT_RGB_EXT) {
  1742.          intFormat = GL_RGB;
  1743.       }
  1744.  
  1745.       _mesa_TexImage2D(GL_TEXTURE_2D, 0, intFormat, rb->Width, rb->Height, 0,
  1746.                        format, type, img->data);
  1747.  
  1748.       if (freeImg) {
  1749.          XMesaDestroyImage(img);
  1750.       }
  1751.    }
  1752. }
  1753.  
  1754.  
  1755.  
  1756. PUBLIC void
  1757. XMesaReleaseTexImage(XMesaDisplay *dpy, XMesaBuffer drawable, int buffer)
  1758. {
  1759.    const GLint b = xbuffer_to_renderbuffer(buffer);
  1760.    if (b < 0)
  1761.       return;
  1762.  
  1763.    /* no-op for now */
  1764. }
  1765.  
  1766.