bumped nouveau DRM interface version number
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
index ca3b69370669c660ad1023988390e6d057cb14b6..1587df66bcd48f1ce8e8db76427d1cc30826326b 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.3
+ * Version:  7.1
  *
- * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2007  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"),
    "GLX_MESA_pixmap_colormap " \
    "GLX_MESA_release_buffers " \
    "GLX_ARB_get_proc_address " \
+   "GLX_EXT_texture_from_pixmap " \
    "GLX_EXT_visual_info " \
    "GLX_EXT_visual_rating " \
-   "GLX_SGI_video_sync " \
+   /*"GLX_SGI_video_sync "*/ \
    "GLX_SGIX_fbconfig " \
    "GLX_SGIX_pbuffer "
 
@@ -345,7 +346,7 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
        */
       xmvis->vishandle = vinfo;
       /* Allocate more space for additional visual */
-      VisualTable = _mesa_realloc( VisualTable, 
+      VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, 
                                    sizeof(XMesaVisual) * NumVisuals, 
                                    sizeof(XMesaVisual) * (NumVisuals + 1));
       /* add xmvis to the list */
@@ -378,6 +379,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;
+}
+
 
 
 /*
@@ -393,6 +412,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) {
@@ -430,15 +451,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,
                                  STENCIL_BITS,
-                                 ACCUM_BITS, /* r */
-                                 ACCUM_BITS, /* g */
-                                 ACCUM_BITS, /* b */
-                                 ACCUM_BITS, /* a */
+                                 accBits, /* r */
+                                 accBits, /* g */
+                                 accBits, /* b */
+                                 accBits, /* a */
                                  0,         /* level */
                                  0          /* numAux */
                                );
@@ -895,6 +916,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                  ***/
 /**********************************************************************/
@@ -1006,7 +1102,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:
@@ -1092,6 +1188,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;
@@ -1105,6 +1203,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 */
@@ -1112,10 +1212,42 @@ 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;
 
+#ifdef GLX_EXT_texture_from_pixmap
+         case GLX_BIND_TO_TEXTURE_RGB_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+            parselist++; /*skip*/
+            break;
+         case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+            parselist++;
+            if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
+                               GLX_TEXTURE_2D_BIT_EXT |
+                               GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
+               /* invalid bit */
+               return NULL;
+            }
+            break;
+         case GLX_Y_INVERTED_EXT:
+            parselist++; /*skip*/
+            break;
+#endif
+
         case None:
             /* end of list */
            break;
@@ -1197,22 +1329,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,
@@ -1228,7 +1364,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;
@@ -1262,7 +1403,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) {
@@ -1270,7 +1413,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       xmvis = create_glx_visual( dpy, visinfo );
       if (!xmvis) {
          /* unusable visual */
-         FREE(glxCtx);
+         _mesa_free(glxCtx);
          return NULL;
       }
    }
@@ -1278,7 +1421,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;
    }
 
@@ -1322,11 +1465,14 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       }
       if (!drawBuffer) {
          /* drawable must be a new window! */
-         drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, xmctx);
+         drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
          if (!drawBuffer) {
             /* Out of memory, or context/drawable depth mismatch */
             return False;
          }
+#ifdef FX
+         FXcreateContext( xmctx->xm_visual, draw, xmctx, drawBuffer );
+#endif
       }
 
       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
@@ -1339,12 +1485,14 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       }
       if (!readBuffer) {
          /* drawable must be a new window! */
-         readBuffer = XMesaCreateWindowBuffer2(glxCtx->xmesaContext->xm_visual,
-                                               read, xmctx);
+         readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
          if (!readBuffer) {
             /* Out of memory, or context/drawable depth mismatch */
             return False;
          }
+#ifdef FX
+         FXcreateContext( xmctx->xm_visual, read, xmctx, readBuffer );
+#endif
       }
 
       MakeCurrent_PrevContext = ctx;
@@ -1461,6 +1609,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 );
 }
 
@@ -1496,6 +1647,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
    MakeCurrent_PrevReadBuffer = 0;
    XMesaDestroyContext( glxCtx->xmesaContext );
    XMesaGarbageCollect();
+   _mesa_free(glxCtx);
 }
 
 
@@ -1751,6 +1903,27 @@ get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
          *value = xmvis->visinfo->visualid;
          break;
 
+#ifdef GLX_EXT_texture_from_pixmap
+      case GLX_BIND_TO_TEXTURE_RGB_EXT:
+         *value = True; /*XXX*/
+         break;
+      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
+         /* XXX review */
+         *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
+         break;
+      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
+         *value = True; /*XXX*/
+         break;
+      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
+         *value = (GLX_TEXTURE_1D_BIT_EXT |
+                   GLX_TEXTURE_2D_BIT_EXT |
+                   GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
+         break;
+      case GLX_Y_INVERTED_EXT:
+         *value = True; /*XXX*/
+         break;
+#endif
+
       default:
         return GLX_BAD_ATTRIBUTE;
    }
@@ -1985,10 +2158,15 @@ Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
    if (!xmvis)
       return 0;
 
-   xmbuf = XMesaCreateWindowBuffer2(xmvis, win, NULL);
+   xmbuf = XMesaCreateWindowBuffer(xmvis, win);
    if (!xmbuf)
       return 0;
 
+#ifdef FX
+   /* XXX this will segfault if actually called */
+   FXcreateContext(xmvis, win, NULL, xmbuf);
+#endif
+
    (void) dpy;
    (void) attribList;  /* Ignored in GLX 1.3 */
 
@@ -2013,16 +2191,102 @@ Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
 {
    XMesaVisual v = (XMesaVisual) config;
    XMesaBuffer b;
-
-   (void) dpy;
-   (void) config;
-   (void) pixmap;
-   (void) attribList;  /* Ignored in GLX 1.3 */
+   const int *attr;
+   int target = 0, format = 0, mipmap = 0;
+   int value;
 
    if (!dpy || !config || !pixmap)
       return 0;
 
-   b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+   for (attr = attribList; *attr; attr++) {
+      switch (*attr) {
+      case GLX_TEXTURE_FORMAT_EXT:
+         attr++;
+         switch (*attr) {
+         case GLX_TEXTURE_FORMAT_NONE_EXT:
+         case GLX_TEXTURE_FORMAT_RGB_EXT:
+         case GLX_TEXTURE_FORMAT_RGBA_EXT:
+            format = *attr;
+            break;
+         default:
+            /* error */
+            return 0;
+         }
+         break;
+      case GLX_TEXTURE_TARGET_EXT:
+         attr++;
+         switch (*attr) {
+         case GLX_TEXTURE_1D_EXT:
+         case GLX_TEXTURE_2D_EXT:
+         case GLX_TEXTURE_RECTANGLE_EXT:
+            target = *attr;
+            break;
+         default:
+            /* error */
+            return 0;
+         }
+         break;
+      case GLX_MIPMAP_TEXTURE_EXT:
+         attr++;
+         if (*attr)
+            mipmap = 1;
+         break;
+      default:
+         /* error */
+         return 0;
+      }
+   }
+
+   if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   if (mipmap) {
+      if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
+                     &value, GL_TRUE) != Success
+          || !value) {
+         return 0; /* error! */
+      }
+   }
+   if (target == GLX_TEXTURE_1D_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+   else if (target == GLX_TEXTURE_2D_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+   if (target == GLX_TEXTURE_RECTANGLE_EXT) {
+      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
+                     &value, GL_TRUE) != Success
+          || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
+         return 0; /* error! */
+      }
+   }
+
+   if (format || target || mipmap) {
+      /* texture from pixmap */
+      b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
+   }
+   else {
+      b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+   }
    if (!b) {
       return 0;
    }
@@ -2087,7 +2351,10 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+   if (xmbuf)
+      return (GLXPbuffer) xmbuf->frontxrb->pixmap;
+   else
+      return 0;
 }
 
 
@@ -2125,8 +2392,20 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
       case GLX_FBCONFIG_ID:
          *value = xmbuf->xm_visual->visinfo->visualid;
          return;
+#ifdef GLX_EXT_texture_from_pixmap
+      case GLX_TEXTURE_FORMAT_EXT:
+         *value = xmbuf->TextureFormat;
+         break;
+      case GLX_TEXTURE_TARGET_EXT:
+         *value = xmbuf->TextureTarget;
+         break;
+      case GLX_MIPMAP_TEXTURE_EXT:
+         *value = xmbuf->TextureMipmap;
+         break;
+#endif
+
       default:
-         return;  /* GLX_BAD_ATTRIBUTE? */
+         return; /* raise BadValue error */
    }
 }
 
@@ -2153,7 +2432,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;
    }
 
@@ -2232,19 +2511,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;
 }
 
@@ -2369,7 +2655,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;
    }
 
@@ -2712,6 +2998,26 @@ Fake_glXGetAGPOffsetMESA( const GLvoid *pointer )
 }
 
 
+/*** GLX_EXT_texture_from_pixmap ***/
+
+static void
+Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
+                        const int *attrib_list)
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+   if (b)
+      XMesaBindTexImage(dpy, b, buffer, attrib_list);
+}
+
+static void
+Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
+{
+   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
+   if (b)
+      XMesaReleaseTexImage(dpy, b, buffer);
+}
+
+
 /* silence warning */
 extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
 
@@ -2867,5 +3173,9 @@ _mesa_GetGLXDispatchTable(void)
    /*** GLX_MESA_agp_offset ***/
    glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA;
 
+   /*** GLX_EXT_texture_from_pixmap ***/
+   glx.BindTexImageEXT = Fake_glXBindTexImageEXT;
+   glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT;
+
    return &glx;
 }