llvmpipe: check for texture usage in all scenes
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
index 7f132eb049a97f6535fe02e2b5839aba38e29326..5c0084f37aae4ac0afb24930101538829f4692f5 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  7.5
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
+ * Copyright (C) 2009  VMware, Inc.   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"),
 
 #include "glxheader.h"
 #include "glxapi.h"
-#include "GL/xmesa.h"
-#include "context.h"
-#include "config.h"
-#include "macros.h"
-#include "imports.h"
-#include "mtypes.h"
-#include "version.h"
+#include "main/context.h"
+#include "main/config.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/version.h"
 #include "xfonts.h"
 #include "xmesaP.h"
 
@@ -78,6 +78,7 @@
    "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 "*/ \
@@ -295,6 +296,11 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo,
       }
    }
 
+   if (stereoFlag) {
+      /* stereo not supported */
+      return NULL;
+   }
+
    /* Comparing IDs uses less memory but sometimes fails. */
    /* XXX revisit this after 3.0 is finished. */
    if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
@@ -961,7 +967,7 @@ lookup_extension(Display *dpy, const char *extName)
 {
    _XExtension *ext;
    for (ext = dpy->ext_procs; ext; ext = ext->next) {
-      if (strcmp(ext->name, extName) == 0) {
+      if (ext->name && strcmp(ext->name, extName) == 0) {
          return ext;
       }
    }
@@ -1078,7 +1084,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
             else {
                stereo_flag = GL_TRUE;
             }
-            return NULL; /* stereo not supported */
+            break;
         case GLX_AUX_BUFFERS:
            parselist++;
             numAux = *parselist++;
@@ -1177,11 +1183,12 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
           * GLX_ARB_multisample
           */
          case GLX_SAMPLE_BUFFERS_ARB:
-            /* ms not supported */
-            return NULL;
          case GLX_SAMPLES_ARB:
-            /* ms not supported */
-            return NULL;
+           parselist++;
+           if (*parselist++ != 0)
+              /* ms not supported */
+              return NULL;
+           break;
 
          /*
           * FBConfig attribs.
@@ -1190,10 +1197,10 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
             if (!fbConfig)
                return NULL;
             parselist++;
-            if (*parselist == GLX_RGBA_BIT) {
+            if (*parselist & GLX_RGBA_BIT) {
                rgb_flag = GL_TRUE;
             }
-            else if (*parselist == GLX_COLOR_INDEX_BIT) {
+            else if (*parselist & GLX_COLOR_INDEX_BIT) {
                rgb_flag = GL_FALSE;
             }
             else if (*parselist == 0) {
@@ -1223,6 +1230,30 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
             /* 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;
@@ -1362,6 +1393,25 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list )
 }
 
 
+/**
+ * Init basic fields of a new fake_glx_context.
+ */
+static void
+init_glx_context(struct fake_glx_context *glxCtx, Display *dpy)
+{
+   /* Always return True.  See if anyone's confused... */
+   GLboolean direct = GL_TRUE;
+
+   glxCtx->xmesaContext->direct = direct;
+   glxCtx->glxContext.isDirect = direct;
+   glxCtx->glxContext.currentDpy = dpy;
+   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
+
+   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+}
+
+
+
 static GLXContext
 Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
                        GLXContext share_list, Bool direct )
@@ -1388,7 +1438,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
       xmvis = create_glx_visual( dpy, visinfo );
       if (!xmvis) {
          /* unusable visual */
-         FREE(glxCtx);
+         _mesa_free(glxCtx);
          return NULL;
       }
    }
@@ -1396,16 +1446,11 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
-   glxCtx->xmesaContext->direct = GL_FALSE;
-   glxCtx->glxContext.isDirect = GL_FALSE;
-   glxCtx->glxContext.currentDpy = dpy;
-   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
-
-   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+   init_glx_context(glxCtx, dpy);
 
    return (GLXContext) glxCtx;
 }
@@ -1440,11 +1485,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' */
@@ -1457,12 +1505,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;
@@ -1587,13 +1637,17 @@ Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
 
 
 static Bool
-Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
+Fake_glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
 {
+   int op, ev, err;
    /* Mesa's GLX isn't really an X extension but we try to act like one. */
-   (void) dpy;
-   (void) errorb;
-   (void) event;
-   return True;
+   if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))
+      ev = err = 0;
+   if (errorBase)
+      *errorBase = err;
+   if (eventBase)
+      *eventBase = ev;
+   return True; /* we're faking GLX so always return success */
 }
 
 
@@ -1617,6 +1671,7 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
    MakeCurrent_PrevReadBuffer = 0;
    XMesaDestroyContext( glxCtx->xmesaContext );
    XMesaGarbageCollect();
+   _mesa_free(glxCtx);
 }
 
 
@@ -1872,6 +1927,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;
    }
@@ -2106,10 +2182,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 */
 
@@ -2134,16 +2215,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; 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;
    }
@@ -2186,32 +2353,42 @@ Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
             break;
          case GLX_PRESERVED_CONTENTS:
             attrib++;
-            preserveContents = *attrib; /* ignored */
+            preserveContents = *attrib;
             break;
          case GLX_LARGEST_PBUFFER:
             attrib++;
-            useLargest = *attrib; /* ignored */
+            useLargest = *attrib;
             break;
          default:
             return 0;
       }
    }
 
-   /* not used at this time */
-   (void) useLargest;
-   (void) preserveContents;
-
    if (width == 0 || height == 0)
       return 0;
 
+   if (width > MAX_WIDTH || height > MAX_HEIGHT) {
+      /* If allocation would have failed and GLX_LARGEST_PBUFFER is set,
+       * allocate the largest possible buffer.
+       */
+      if (useLargest) {
+         width = MAX_WIDTH;
+         height = MAX_HEIGHT;
+      }
+   }
+
    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
    /* A GLXPbuffer handle must be an X Drawable because that's what
     * glXMakeCurrent takes.
     */
-   if (xmbuf)
+   if (xmbuf) {
+      xmbuf->largestPbuffer = useLargest;
+      xmbuf->preservedContents = preserveContents;
       return (GLXPbuffer) xmbuf->frontxrb->pixmap;
-   else
+   }
+   else {
       return 0;
+   }
 }
 
 
@@ -2233,6 +2410,9 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
    if (!xmbuf)
       return;
 
+   /* make sure buffer's dimensions are up to date */
+   xmesa_check_and_update_buffer_size(NULL, xmbuf);
+
    switch (attribute) {
       case GLX_WIDTH:
          *value = xmbuf->mesa_buffer.Width;
@@ -2241,16 +2421,28 @@ Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
          *value = xmbuf->mesa_buffer.Height;
          break;
       case GLX_PRESERVED_CONTENTS:
-         *value = True;
+         *value = xmbuf->preservedContents;
          break;
       case GLX_LARGEST_PBUFFER:
-         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
+         *value = xmbuf->largestPbuffer;
          break;
       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 */
    }
 }
 
@@ -2277,16 +2469,11 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
                                    shareCtx ? shareCtx->xmesaContext : NULL);
    if (!glxCtx->xmesaContext) {
-      FREE(glxCtx);
+      _mesa_free(glxCtx);
       return NULL;
    }
 
-   glxCtx->xmesaContext->direct = GL_FALSE;
-   glxCtx->glxContext.isDirect = GL_FALSE;
-   glxCtx->glxContext.currentDpy = dpy;
-   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
-
-   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+   init_glx_context(glxCtx, dpy);
 
    return (GLXContext) glxCtx;
 }
@@ -2307,9 +2494,9 @@ Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
       break;
    case GLX_RENDER_TYPE:
       if (xmctx->xm_visual->mesa_visual.rgbMode)
-         *value = GLX_RGBA_BIT;
+         *value = GLX_RGBA_TYPE;
       else
-         *value = GLX_COLOR_INDEX_BIT;
+         *value = GLX_COLOR_INDEX_TYPE;
       break;
    case GLX_SCREEN:
       *value = 0;
@@ -2500,16 +2687,11 @@ 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;
    }
 
-   glxCtx->xmesaContext->direct = GL_FALSE;
-   glxCtx->glxContext.isDirect = GL_FALSE;
-   glxCtx->glxContext.currentDpy = dpy;
-   glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
-
-   assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
+   init_glx_context(glxCtx, dpy);
 
    return (GLXContext) glxCtx;
 }
@@ -2599,10 +2781,10 @@ Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, un
 
    switch (attribute) {
       case GLX_PRESERVED_CONTENTS_SGIX:
-         *value = True;
+         *value = xmbuf->preservedContents;
          break;
       case GLX_LARGEST_PBUFFER_SGIX:
-         *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height;
+         *value = xmbuf->largestPbuffer;
          break;
       case GLX_WIDTH_SGIX:
          *value = xmbuf->mesa_buffer.Width;
@@ -2843,6 +3025,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);
 
@@ -2998,5 +3200,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;
 }