Fix glXCopyContext bug
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
index 31aa873aa64b8c18052c75c6e338377dce15c3ee..e7d98dd2a3da9fd302f32fbbae03c7eb66d8114a 100644 (file)
@@ -1,10 +1,10 @@
-/* $Id: fakeglx.c,v 1.52 2001/05/25 21:51:02 brianp Exp $ */
+/* $Id: fakeglx.c,v 1.66 2002/06/16 03:56:11 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  4.1
  *
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2002  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"),
 
 /* This indicates the client-side GLX API and GLX encoder version. */
 #define CLIENT_MAJOR_VERSION 1
-#define CLIENT_MINOR_VERSION 2
+#define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
 
 /* This indicates the server-side GLX decoder version.
- * GLX 1.3 indicates OpenGL 1.2 support
+ * GLX 1.4 indicates OpenGL 1.3 support
  */
 #define SERVER_MAJOR_VERSION 1
-#define SERVER_MINOR_VERSION 3
+#define SERVER_MINOR_VERSION 4
 
 /* This is appended onto the glXGetClient/ServerString version strings. */
-#define MESA_GLX_VERSION "Mesa 3.5"
+#define MESA_GLX_VERSION "Mesa 4.1"
 
 /* Who implemented this GLX? */
 #define VENDOR "Brian Paul"
@@ -269,8 +269,7 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
             ximageFlag = GL_TRUE;
          }
          else {
-            fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
-            fprintf(stderr, "environment variable, using an XImage.\n");
+            _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
          }
       }
    }
@@ -308,8 +307,8 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
 
    /* Create a new visual and add it to the list. */
 
-   if (NumVisuals>=MAX_VISUALS) {
-      fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
+   if (NumVisuals >= MAX_VISUALS) {
+      _mesa_problem(NULL, "GLX Error: maximum number of visuals exceeded");
       return NULL;
    }
 
@@ -392,7 +391,7 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo )
       }
    }
    else {
-      fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
+      _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
       return NULL;
    }
 }
@@ -578,8 +577,13 @@ static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname)
       }
    }
 
-   fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
-           type, depth );
+   {
+      char s[1000];
+      sprintf(s, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
+              type, depth );
+      _mesa_warning(NULL, s);
+   }
+
    return NULL;
 }
 
@@ -1132,6 +1136,10 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
 {
    XMesaVisual glxvis;
    struct fake_glx_context *glxCtx;
+   struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
+
+   if (!dpy || !visinfo)
+      return 0;
 
    glxCtx = CALLOC_STRUCT(fake_glx_context);
    if (!glxCtx)
@@ -1152,7 +1160,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
    }
 
    glxCtx->xmesaContext = XMesaCreateContext(glxvis,
-                                             (XMesaContext) share_list);
+                                   shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
       FREE(glxCtx);
       return NULL;
@@ -1233,8 +1241,9 @@ 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;
-#ifdef GLX_BUILD_IN_XLIB_MESA
+#else
          __glXSetCurrentContext(ctx);
 #endif
          return True;
@@ -1251,7 +1260,7 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
       MakeCurrent_PrevReadable = 0;
       MakeCurrent_PrevDrawBuffer = 0;
       MakeCurrent_PrevReadBuffer = 0;
-#ifdef GLX_BUILD_IN_XLIB_MESA
+#ifdef GLX_BUILT_IN_XMESA
       /* XXX bind dummy context with __glXSetCurrentContext(ctx); */
 #endif
       return True;
@@ -1331,7 +1340,7 @@ Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
       XMesaDestroyBuffer(b);
    }
    else if (getenv("MESA_DEBUG")) {
-      fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
+      _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
    }
 }
 
@@ -1341,8 +1350,10 @@ static void
 Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
                      unsigned long mask )
 {
-   XMesaContext xm_src = (XMesaContext) src;
-   XMesaContext xm_dst = (XMesaContext) dst;
+   struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src;
+   struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst;
+   XMesaContext xm_src = fakeSrc->xmesaContext;
+   XMesaContext xm_dst = fakeDst->xmesaContext;
    (void) dpy;
    _mesa_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask );
 }
@@ -1403,7 +1414,7 @@ Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
       XMesaSwapBuffers(buffer);
    }
    else if (getenv("MESA_DEBUG")) {
-      fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
+      _mesa_warning(NULL, "Mesa: glXSwapBuffers: invalid drawable\n");
    }
 }
 
@@ -1420,7 +1431,7 @@ Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
       XMesaCopySubBuffer(buffer, x, y, width, height);
    }
    else if (getenv("MESA_DEBUG")) {
-      fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
+      _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
    }
 }
 
@@ -1459,7 +1470,6 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
            return 0;
         }
         else {
-           /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
            return GLX_BAD_VISUAL;
         }
       }
@@ -1695,6 +1705,16 @@ Fake_glXGetClientString( Display *dpy, int name )
  * GLX 1.3 and later
  */
 
+/* XXX Move this when done.
+ * Create an XMesaBuffer as a Pbuffer.
+ * New in Mesa 4.0 but untested.
+ */
+extern XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap,
+                                    unsigned int width, unsigned int height );
+
+
+
+/* PBUFFER */
 static GLXFBConfig *
 Fake_glXChooseFBConfig( Display *dpy, int screen,
                         const int *attribList, int *nitems )
@@ -1707,37 +1727,193 @@ Fake_glXChooseFBConfig( Display *dpy, int screen,
 }
 
 
+/* PBUFFER */
 static int
 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
                            int attribute, int *value )
 {
+   XMesaVisual v = NULL; /* XXX Fix this */
    (void) dpy;
    (void) config;
    (void) attribute;
    (void) value;
-   return 0;
+
+   if (!dpy || !config || !value)
+      return -1;
+
+   switch (attribute) {
+      case GLX_FBCONFIG_ID:
+      case GLX_BUFFER_SIZE:
+         if (v->mesa_visual.rgbMode)
+            *value = v->mesa_visual.redBits + v->mesa_visual.greenBits +
+                     v->mesa_visual.blueBits + v->mesa_visual.alphaBits;
+         else
+            *value = v->mesa_visual.indexBits;
+         break;
+      case GLX_LEVEL:
+         *value = v->level;
+         break;
+      case GLX_DOUBLEBUFFER:
+         *value = v->mesa_visual.doubleBufferMode;
+         break;
+      case GLX_STEREO:
+         *value = v->mesa_visual.stereoMode;
+         break;
+      case GLX_AUX_BUFFERS:
+         *value = v->mesa_visual.numAuxBuffers;
+         break;
+      case GLX_RED_SIZE:
+         *value = v->mesa_visual.redBits;
+         break;
+      case GLX_GREEN_SIZE:
+         *value = v->mesa_visual.greenBits;
+         break;
+      case GLX_BLUE_SIZE:
+         *value = v->mesa_visual.blueBits;
+         break;
+      case GLX_ALPHA_SIZE:
+         *value = v->mesa_visual.alphaBits;
+         break;
+      case GLX_DEPTH_SIZE:
+         *value = v->mesa_visual.depthBits;
+         break;
+      case GLX_STENCIL_SIZE:
+         *value = v->mesa_visual.stencilBits;
+         break;
+      case GLX_ACCUM_RED_SIZE:
+         *value = v->mesa_visual.accumRedBits;
+         break;
+      case GLX_ACCUM_GREEN_SIZE:
+         *value = v->mesa_visual.accumGreenBits;
+         break;
+      case GLX_ACCUM_BLUE_SIZE:
+         *value = v->mesa_visual.accumBlueBits;
+         break;
+      case GLX_ACCUM_ALPHA_SIZE:
+         *value = v->mesa_visual.accumAlphaBits;
+         break;
+      case GLX_RENDER_TYPE:
+         *value = 0; /* XXX ??? */
+         break;
+      case GLX_DRAWABLE_TYPE:
+         *value = GLX_PBUFFER_BIT; /* XXX fix? */
+         break;
+      case GLX_X_RENDERABLE:
+         *value = False; /* XXX ??? */
+         break;
+      case GLX_X_VISUAL_TYPE:
+#if defined(__cplusplus) || defined(c_plusplus)
+         switch (v->vishandle->c_class) {
+#else
+         switch (v->vishandle->class) {
+#endif
+            case GrayScale:
+               *value = GLX_GRAY_SCALE;
+               break;
+            case StaticGray:
+               *value = GLX_STATIC_GRAY;
+               break;
+            case StaticColor:
+               *value = GLX_STATIC_COLOR;
+               break;
+            case PseudoColor:
+               *value = GLX_PSEUDO_COLOR;
+               break;
+            case TrueColor:
+               *value = GLX_TRUE_COLOR;
+               break;
+            case DirectColor:
+               *value = GLX_DIRECT_COLOR;
+               break;
+            default:
+               *value = 0;
+         }
+         break;
+      case GLX_CONFIG_CAVEAT:
+         *value = 0; /* XXX ??? */
+         break;
+      case GLX_TRANSPARENT_TYPE:
+         if (v->level == 0) {
+            /* normal planes */
+            *value = GLX_NONE_EXT;
+         }
+         else if (v->level > 0) {
+            /* overlay */
+            if (v->mesa_visual.rgbMode) {
+               *value = GLX_TRANSPARENT_RGB_EXT;
+            }
+            else {
+               *value = GLX_TRANSPARENT_INDEX_EXT;
+            }
+         }
+         else if (v->level < 0) {
+            /* underlay */
+            *value = GLX_NONE_EXT;
+         }
+         break;
+      case GLX_TRANSPARENT_INDEX_VALUE:
+         *value = transparent_pixel( v );
+         break;
+      case GLX_TRANSPARENT_RED_VALUE:
+         *value = 0;  /* not implemented */
+         break;
+      case GLX_TRANSPARENT_GREEN_VALUE:
+         *value = 0;  /* not implemented */
+         break;
+      case GLX_TRANSPARENT_BLUE_VALUE:
+         *value = 0;  /* not implemented */
+         break;
+      case GLX_TRANSPARENT_ALPHA_VALUE:
+         *value = 0;  /* not implemented */
+         break;
+      case GLX_MAX_PBUFFER_WIDTH:
+         *value = DisplayWidth(dpy, v->vishandle->screen);
+         break;
+      case GLX_MAX_PBUFFER_HEIGHT:
+         *value = DisplayHeight(dpy, v->vishandle->screen);
+         break;
+      case GLX_MAX_PBUFFER_PIXELS:
+         *value = DisplayWidth(dpy, v->vishandle->screen) *
+                  DisplayHeight(dpy, v->vishandle->screen);
+         break;
+      case GLX_VISUAL_ID:
+         *value = v->vishandle->visualid;
+         break;
+      default:
+         return GLX_BAD_ATTRIBUTE;
+   }
+
+   return Success;
 }
 
 
+/* PBUFFER */
 static GLXFBConfig *
 Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
 {
+   /* Get list of all X visuals, create FBconfigs from them */
    (void) dpy;
    (void) screen;
-   (void) nelements;
+   nelements = 0;
    return 0;
 }
 
 
+/* PBUFFER */
 static XVisualInfo *
 Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
 {
-   (void) dpy;
-   (void) config;
-   return 0;
+   if (dpy && config) {
+      XMesaVisual v = (XMesaVisual) config;
+      return v->vishandle;
+   }
+   else {
+      return NULL;
+   }
 }
 
 
+/* PBUFFER */
 static GLXWindow
 Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
                       const int *attribList )
@@ -1745,52 +1921,109 @@ Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
    (void) dpy;
    (void) config;
    (void) win;
-   (void) attribList;
-   return 0;
+   (void) attribList;  /* Ignored in GLX 1.3 */
+
+   return win;  /* A hack for now */
 }
 
 
 static void
 Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
 {
-   (void) dpy;
-   (void) window;
-   return;
+   XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window);
+   if (b)
+      XMesaDestroyBuffer(b);
+   /* don't destroy X window */
 }
 
 
+/* XXX untested */
 static GLXPixmap
 Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
                       const int *attribList )
 {
+   XMesaVisual v = (XMesaVisual) config;
+   XVisualInfo *visinfo;
+   XMesaBuffer b;
+
    (void) dpy;
    (void) config;
    (void) pixmap;
-   (void) attribList;
-   return 0;
+   (void) attribList;  /* Ignored in GLX 1.3 */
+
+   if (!dpy || !config || !pixmap)
+      return 0;
+
+   visinfo = v->vishandle;
+
+   v = find_glx_visual( dpy, visinfo );
+   if (!v) {
+      v = create_glx_visual( dpy, visinfo );
+      if (!v) {
+         /* unusable visual */
+         return 0;
+      }
+   }
+
+   b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+   if (!b) {
+      return 0;
+   }
+
+   return pixmap;
 }
 
 
 static void
 Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
 {
-   (void) dpy;
-   (void) pixmap;
-   return;
+   XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap);
+   if (b)
+      XMesaDestroyBuffer(b);
+   /* don't destroy X pixmap */
 }
 
 
+/* PBUFFER */
 static GLXPbuffer
 Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
                        const int *attribList )
 {
+   const int *attrib;
+   int width = 0, height = 0;
+   GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
+
    (void) dpy;
    (void) config;
-   (void) attribList;
+
+   for (attrib = attribList; attrib; attrib++) {
+      switch (*attrib) {
+         case GLX_PBUFFER_WIDTH:
+            width = *(++attrib);
+            break;
+         case GLX_PBUFFER_HEIGHT:
+            height = *(++attrib);
+            break;
+         case GLX_PRESERVED_CONTENTS:
+            preserveContents = GL_TRUE; /* ignored */
+            break;
+         case GLX_LARGEST_PBUFFER:
+            useLargest = GL_TRUE; /* ignored */
+            break;
+         default:
+            return 0;
+      }
+   }
+
+   if (width == 0 || height == 0)
+      return 0;
+
+
    return 0;
 }
 
 
+/* PBUFFER */
 static void
 Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
 {
@@ -1799,14 +2032,25 @@ Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
 }
 
 
+/* PBUFFER */
 static void
 Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
                        unsigned int *value )
 {
    (void) dpy;
    (void) draw;
-   (void) attribute;
-   (void) value;
+
+   switch (attribute) {
+      case GLX_WIDTH:
+      case GLX_HEIGHT:
+      case GLX_PRESERVED_CONTENTS:
+      case GLX_LARGEST_PBUFFER:
+      case GLX_FBCONFIG_ID:
+         *value = 0;
+         return;
+      default:
+         return;  /* GLX_BAD_ATTRIBUTE? */
+   }
 }
 
 
@@ -1814,26 +2058,36 @@ static GLXContext
 Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
                           int renderType, GLXContext shareList, Bool direct )
 {
-   (void) dpy;
-   (void) config;
-   (void) renderType;
-   (void) shareList;
-   (void) direct;
-   return 0;
+   XMesaVisual v = (XMesaVisual) config;
+
+   if (!dpy || !config ||
+       (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
+      return 0;
+
+   return Fake_glXCreateContext(dpy, v->vishandle, shareList, direct);
 }
 
 
+/* PBUFFER */
 static int
 Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
 {
    (void) dpy;
    (void) ctx;
-   (void) attribute;
-   (void) value;
-   return 0;
+
+   switch (attribute) {
+   case GLX_FBCONFIG_ID:
+   case GLX_RENDER_TYPE:
+   case GLX_SCREEN:
+      *value = 0;
+      return Success;
+   default:
+      return GLX_BAD_ATTRIBUTE;
+   }
 }
 
 
+/* PBUFFER */
 static void
 Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
 {
@@ -1843,6 +2097,7 @@ Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
 }
 
 
+/* PBUFFER */
 static void
 Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
                           unsigned long *mask )
@@ -1890,11 +2145,7 @@ Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
 static Bool
 Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
 {
-   (void) dpy;
-   (void) draw;
-   (void) read;
-   (void) ctx;
-   return False;
+   return Fake_glXMakeContextCurrent( dpy, draw, read, ctx );
 }
 
 /* not used