Merge branch 'origin'
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
index b0cb52846a1fc9d14dbc7ace6a4362af364dbe3e..eecd52aa32b079fc82733abe2e18312263d7ef29 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -52,6 +52,9 @@
 #include "xfonts.h"
 #include "xmesaP.h"
 
+#ifdef __VMS
+#define _mesa_sprintf sprintf
+#endif
 
 /* This indicates the client-side GLX API and GLX encoder version. */
 #define CLIENT_MAJOR_VERSION 1
@@ -77,7 +80,7 @@
    "GLX_ARB_get_proc_address " \
    "GLX_EXT_visual_info " \
    "GLX_EXT_visual_rating " \
-   "GLX_SGI_video_sync " \
+   /*"GLX_SGI_video_sync "*/ \
    "GLX_SGIX_fbconfig " \
    "GLX_SGIX_pbuffer "
 
@@ -105,8 +108,7 @@ struct fake_glx_context {
 #define DONT_CARE -1
 
 
-#define MAX_VISUALS 100
-static XMesaVisual VisualTable[MAX_VISUALS];
+static XMesaVisual *VisualTable = NULL;
 static int NumVisuals = 0;
 
 
@@ -331,11 +333,6 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
 
    /* Create a new visual and add it to the list. */
 
-   if (NumVisuals >= MAX_VISUALS) {
-      _mesa_problem(NULL, "GLX Error: maximum number of visuals exceeded");
-      return NULL;
-   }
-
    xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
                               stereoFlag, ximageFlag,
                               depth_size, stencil_size,
@@ -347,6 +344,10 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
        * if we need to search for it in find_glx_visual().
        */
       xmvis->vishandle = vinfo;
+      /* Allocate more space for additional visual */
+      VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, 
+                                   sizeof(XMesaVisual) * NumVisuals, 
+                                   sizeof(XMesaVisual) * (NumVisuals + 1));
       /* add xmvis to the list */
       VisualTable[NumVisuals] = xmvis;
       NumVisuals++;
@@ -377,6 +378,24 @@ default_depth_bits(void)
    return zBits;
 }
 
+static GLint
+default_alpha_bits(void)
+{
+   int aBits;
+   const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
+   if (aEnv)
+      aBits = _mesa_atoi(aEnv);
+   else
+      aBits = 0;
+   return aBits;
+}
+
+static GLint
+default_accum_bits(void)
+{
+   return 16;
+}
+
 
 
 /*
@@ -392,6 +411,8 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
 {
    int vislevel;
    GLint zBits = default_depth_bits();
+   GLint accBits = default_accum_bits();
+   GLboolean alphaFlag = default_alpha_bits() > 0;
 
    vislevel = level_of_visual( dpy, visinfo );
    if (vislevel) {
@@ -417,11 +438,8 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
                                  GL_TRUE,   /* double */
                                  GL_FALSE,  /* stereo */
                                  zBits,
-                                 8 * sizeof(GLstencil),
-                                 0 * sizeof(GLaccum), /* r */
-                                 0 * sizeof(GLaccum), /* g */
-                                 0 * sizeof(GLaccum), /* b */
-                                 0 * sizeof(GLaccum), /* a */
+                                 STENCIL_BITS,
+                                 0, 0, 0, 0, /* accum bits */
                                  0,         /* level */
                                  0          /* numAux */
                                );
@@ -432,15 +450,15 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
          /* can be done?  They should use glXChooseVisual(). */
          return save_glx_visual( dpy, visinfo,
                                  GL_TRUE,   /* rgb */
-                                 GL_FALSE,  /* alpha */
+                                 alphaFlag, /* alpha */
                                  GL_TRUE,   /* double */
                                  GL_FALSE,  /* stereo */
                                  zBits,
-                                 8 * sizeof(GLstencil),
-                                 8 * sizeof(GLaccum), /* r */
-                                 8 * sizeof(GLaccum), /* g */
-                                 8 * sizeof(GLaccum), /* b */
-                                 8 * sizeof(GLaccum), /* a */
+                                 STENCIL_BITS,
+                                 accBits, /* r */
+                                 accBits, /* g */
+                                 accBits, /* b */
+                                 accBits, /* a */
                                  0,         /* level */
                                  0          /* numAux */
                                );
@@ -897,6 +915,81 @@ choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
 }
 
 
+/**********************************************************************/
+/***             Display-related functions                          ***/
+/**********************************************************************/
+
+
+/**
+ * Free all XMesaVisuals which are associated with the given display.
+ */
+static void
+destroy_visuals_on_display(Display *dpy)
+{
+   int i;
+   for (i = 0; i < NumVisuals; i++) {
+      if (VisualTable[i]->display == dpy) {
+         /* remove this visual */
+         int j;
+         free(VisualTable[i]);
+         for (j = i; j < NumVisuals - 1; j++)
+            VisualTable[j] = VisualTable[j + 1];
+         NumVisuals--;
+      }
+   }
+}
+
+
+/**
+ * Called from XCloseDisplay() to let us free our display-related data.
+ */
+static int
+close_display_callback(Display *dpy, XExtCodes *codes)
+{
+   destroy_visuals_on_display(dpy);
+   xmesa_destroy_buffers_on_display(dpy);
+   return 0;
+}
+
+
+/**
+ * Look for the named extension on given display and return a pointer
+ * to the _XExtension data, or NULL if extension not found.
+ */
+static _XExtension *
+lookup_extension(Display *dpy, const char *extName)
+{
+   _XExtension *ext;
+   for (ext = dpy->ext_procs; ext; ext = ext->next) {
+      if (ext->name && strcmp(ext->name, extName) == 0) {
+         return ext;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Whenever we're given a new Display pointer, call this function to
+ * register our close_display_callback function.
+ */
+static void
+register_with_display(Display *dpy)
+{
+   const char *extName = "MesaGLX";
+   _XExtension *ext;
+
+   ext = lookup_extension(dpy, extName);
+   if (!ext) {
+      XExtCodes *c = XAddExtension(dpy);
+      ext = dpy->ext_procs;  /* new extension is at head of list */
+      assert(c->extension == ext->codes.extension);
+      ext->name = _mesa_strdup(extName);
+      ext->close_display = close_display_callback;
+   }
+}
+
+
 /**********************************************************************/
 /***                  Begin Fake GLX API Functions                  ***/
 /**********************************************************************/
@@ -1008,7 +1101,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
            parselist++;
             {
                GLint size = *parselist++;
-               alpha_flag = size>0 ? 1 : 0;
+               alpha_flag = size ? GL_TRUE : GL_FALSE;
             }
            break;
         case GLX_DEPTH_SIZE:
@@ -1094,6 +1187,8 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
           * FBConfig attribs.
           */
          case GLX_RENDER_TYPE:
+            if (!fbConfig)
+               return NULL;
             parselist++;
             if (*parselist == GLX_RGBA_BIT) {
                rgb_flag = GL_TRUE;
@@ -1107,6 +1202,8 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
             parselist++;
             break;
          case GLX_DRAWABLE_TYPE:
+            if (!fbConfig)
+               return NULL;
             parselist++;
             if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
                return NULL; /* bad bit */
@@ -1114,8 +1211,16 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
             parselist++;
             break;
          case GLX_FBCONFIG_ID:
+            if (!fbConfig)
+               return NULL;
             parselist++;
-            desiredVisualID = *parselist;
+            desiredVisualID = *parselist++;
+            break;
+         case GLX_X_RENDERABLE:
+            if (!fbConfig)
+               return NULL;
+            parselist += 2;
+            /* ignore */
             break;
 
         case None:
@@ -1199,22 +1304,26 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
        * return 16 to maintain performance with earlier versions of Mesa.
        */
       if (depth_size > 24)
-         depth_size = 31;   /* 32 causes int overflow problems */
+         depth_size = 32;
       else if (depth_size > 16)
          depth_size = 24;
       else if (depth_size > 0) {
          depth_size = default_depth_bits();
       }
 
+      if (!alpha_flag) {
+         alpha_flag = default_alpha_bits() > 0;
+      }
+
       /* we only support one size of stencil and accum buffers. */
       if (stencil_size > 0)
          stencil_size = STENCIL_BITS;
       if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 ||
           accumAlphaSize > 0) {
-         accumRedSize = ACCUM_BITS;
-         accumGreenSize = ACCUM_BITS;
-         accumBlueSize = ACCUM_BITS;
-         accumAlphaSize = alpha_flag ? ACCUM_BITS : 0;
+         accumRedSize = 
+         accumGreenSize = 
+         accumBlueSize = default_accum_bits();
+         accumAlphaSize = alpha_flag ? accumRedSize : 0;
       }
 
       xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
@@ -1230,7 +1339,12 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
 static XVisualInfo *
 Fake_glXChooseVisual( Display *dpy, int screen, int *list )
 {
-   XMesaVisual xmvis = choose_visual(dpy, screen, list, GL_FALSE);
+   XMesaVisual xmvis;
+
+   /* register ourselves as an extension on this display */
+   register_with_display(dpy);
+
+   xmvis = choose_visual(dpy, screen, list, GL_FALSE);
    if (xmvis) {
 #if 0
       return xmvis->vishandle;
@@ -1264,7 +1378,9 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       return 0;
 
    /* deallocate unused windows/buffers */
+#if 0
    XMesaGarbageCollect();
+#endif
 
    xmvis = find_glx_visual( dpy, visinfo );
    if (!xmvis) {
@@ -1272,7 +1388,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       xmvis = create_glx_visual( dpy, visinfo );
       if (!xmvis) {
          /* unusable visual */
-         FREE(glxCtx);
+         _mesa_free(glxCtx);
          return NULL;
       }
    }
@@ -1280,7 +1396,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -1359,11 +1475,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
          ((__GLXcontext *) ctx)->currentDpy = dpy;
          ((__GLXcontext *) ctx)->currentDrawable = draw;
-#ifndef GLX_BUILT_IN_XMESA
          ((__GLXcontext *) ctx)->currentReadable = read;
-#else
-         __glXSetCurrentContext(ctx);
-#endif
          return True;
       }
       else {
@@ -1378,9 +1490,6 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       MakeCurrent_PrevReadable = 0;
       MakeCurrent_PrevDrawBuffer = 0;
       MakeCurrent_PrevReadBuffer = 0;
-#ifdef GLX_BUILT_IN_XMESA
-      /* XXX bind dummy context with __glXSetCurrentContext(ctx); */
-#endif
       return True;
    }
    else {
@@ -1418,7 +1527,7 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
    if (!b) {
       return 0;
    }
-   return b->frontbuffer;
+   return b->frontxrb->pixmap;
 }
 
 
@@ -1444,7 +1553,7 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
    if (!b) {
       return 0;
    }
-   return b->frontbuffer;
+   return b->frontxrb->pixmap;
 }
 
 
@@ -1470,6 +1579,9 @@ Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
    XMesaContext xm_src = fakeSrc->xmesaContext;
    XMesaContext xm_dst = fakeDst->xmesaContext;
    (void) dpy;
+   if (MakeCurrent_PrevContext == src) {
+      _mesa_Flush();
+   }
    _mesa_copy_context( &(xm_src->mesa), &(xm_dst->mesa), (GLuint) mask );
 }
 
@@ -1505,6 +1617,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
    MakeCurrent_PrevReadBuffer = 0;
    XMesaDestroyContext( glxCtx->xmesaContext );
    XMesaGarbageCollect();
+   _mesa_free(glxCtx);
 }
 
 
@@ -2096,7 +2209,10 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   return (GLXPbuffer) xmbuf->frontbuffer;
+   if (xmbuf)
+      return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+   else
+      return 0;
 }
 
 
@@ -2162,7 +2278,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -2241,19 +2357,26 @@ Fake_glXSwapIntervalSGI(int interval)
 
 /*** GLX_SGI_video_sync ***/
 
+static unsigned int FrameCounter = 0;
+
 static int
 Fake_glXGetVideoSyncSGI(unsigned int *count)
 {
-   (void) count;
+   /* this is a bogus implementation */
+   *count = FrameCounter++;
    return 0;
 }
 
 static int
 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
 {
-   (void) divisor;
-   (void) remainder;
-   (void) count;
+   if (divisor <= 0 || remainder < 0)
+      return GLX_BAD_VALUE;
+   /* this is a bogus implementation */
+   FrameCounter++;
+   while (FrameCounter % divisor != remainder)
+      FrameCounter++;
+   *count = FrameCounter;
    return 0;
 }
 
@@ -2357,7 +2480,7 @@ Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixm
 {
    XMesaVisual xmvis = (XMesaVisual) config;
    XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
-   return xmbuf->frontbuffer; /* need to return an X ID */
+   return xmbuf->frontxrb->pixmap; /* need to return an X ID */
 }
 
 
@@ -2378,7 +2501,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
@@ -2451,7 +2574,7 @@ Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   return (GLXPbuffer) xmbuf->frontbuffer;
+   return (GLXPbuffer) xmbuf->frontxrb->pixmap;
 }