new texture compression infrastructure
[mesa.git] / src / mesa / main / context.c
index fa86aaef97e3a8f929c62a68056e8153810b0574..986dbc5aca9912bcaad93032f09f2e15de6f6656 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: context.c,v 1.158 2002/03/29 17:27:59 brianp Exp $ */
+/* $Id: context.c,v 1.177 2002/09/27 02:45:37 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -41,7 +41,6 @@
 #include "get.h"
 #include "glthread.h"
 #include "hash.h"
-#include "imports.h"
 #include "light.h"
 #include "macros.h"
 #include "mem.h"
 #include "state.h"
 #include "teximage.h"
 #include "texobj.h"
+#include "texstate.h"
 #include "mtypes.h"
 #include "varray.h"
 #include "vpstate.h"
 #include "vtxfmt.h"
 #include "math/m_translate.h"
-#include "math/m_vertices.h"
 #include "math/m_matrix.h"
 #include "math/m_xform.h"
 #include "math/mathmod.h"
 #endif
 
 #ifndef MESA_VERBOSE
-int MESA_VERBOSE = 0
-/*                 | VERBOSE_PIPELINE */
-/*                 | VERBOSE_IMMEDIATE */
-/*                 | VERBOSE_VARRAY */
-/*                 | VERBOSE_TEXTURE */
-/*                 | VERBOSE_API */
-/*                 | VERBOSE_DRIVER */
-/*                 | VERBOSE_STATE */
-/*                 | VERBOSE_DISPLAY_LIST */
-;
+int MESA_VERBOSE = 0;
 #endif
 
 #ifndef MESA_DEBUG_FLAGS
-int MESA_DEBUG_FLAGS = 0
-/*                 | DEBUG_ALWAYS_FLUSH */
-;
+int MESA_DEBUG_FLAGS = 0;
 #endif
 
 
+static void
+free_shared_state( GLcontext *ctx, struct gl_shared_state *ss );
+
 
 /**********************************************************************/
 /*****       OpenGL SI-style interface (new in Mesa 3.5)          *****/
 /**********************************************************************/
 
-static GLboolean
-_mesa_DestroyContext(__GLcontext *gc)
+/* Called by window system/device driver (via gc->exports.destroyCurrent())
+ * when the rendering context is to be destroyed.
+ */
+GLboolean
+_mesa_destroyContext(__GLcontext *gc)
 {
    if (gc) {
       _mesa_free_context_data(gc);
@@ -105,6 +99,133 @@ _mesa_DestroyContext(__GLcontext *gc)
    return GL_TRUE;
 }
 
+/* Called by window system/device driver (via gc->exports.loseCurrent())
+ * when the rendering context is made non-current.
+ */
+GLboolean
+_mesa_loseCurrent(__GLcontext *gc)
+{
+   /* XXX unbind context from thread */
+   return GL_TRUE;
+}
+
+/* Called by window system/device driver (via gc->exports.makeCurrent())
+ * when the rendering context is made current.
+ */
+GLboolean
+_mesa_makeCurrent(__GLcontext *gc)
+{
+   /* XXX bind context to thread */
+   return GL_TRUE;
+}
+
+/* Called by window system/device driver - yadda, yadda, yadda.
+ * See above comments.
+ */
+GLboolean
+_mesa_shareContext(__GLcontext *gc, __GLcontext *gcShare)
+{
+   if (gc && gcShare && gc->Shared && gcShare->Shared) {
+      gc->Shared->RefCount--;
+      if (gc->Shared->RefCount == 0) {
+         free_shared_state(gc, gc->Shared);
+      }
+      gc->Shared = gcShare->Shared;
+      gc->Shared->RefCount++;
+      return GL_TRUE;
+   }
+   else {
+      return GL_FALSE;
+   }
+}
+
+GLboolean
+_mesa_copyContext(__GLcontext *dst, const __GLcontext *src, GLuint mask)
+{
+   if (dst && src) {
+      _mesa_copy_context( src, dst, mask );
+      return GL_TRUE;
+   }
+   else {
+      return GL_FALSE;
+   }
+}
+
+GLboolean
+_mesa_forceCurrent(__GLcontext *gc)
+{
+   return GL_TRUE;
+}
+
+GLboolean
+_mesa_notifyResize(__GLcontext *gc)
+{
+   GLint x, y;
+   GLuint width, height;
+   __GLdrawablePrivate *d = gc->imports.getDrawablePrivate(gc);
+   if (!d || !d->getDrawableSize)
+      return GL_FALSE;
+   d->getDrawableSize( d, &x, &y, &width, &height );
+   /* update viewport, resize software buffers, etc. */
+   return GL_TRUE;
+}
+
+void
+_mesa_notifyDestroy(__GLcontext *gc)
+{
+}
+
+/* Called by window system just before swapping buffers.
+ * We have to finish any pending rendering.
+ */
+void
+_mesa_notifySwapBuffers(__GLcontext *gc)
+{
+   FLUSH_VERTICES( gc, 0 );
+}
+
+struct __GLdispatchStateRec *
+_mesa_dispatchExec(__GLcontext *gc)
+{
+   return NULL;
+}
+
+void
+_mesa_beginDispatchOverride(__GLcontext *gc)
+{
+}
+
+void
+_mesa_endDispatchOverride(__GLcontext *gc)
+{
+}
+
+/* Setup the exports.  The window system will call these functions
+ * when it needs Mesa to do something.
+ * NOTE: Device drivers should override these functions!  For example,
+ * the Xlib driver should plug in the XMesa*-style functions into this
+ * structure.  The XMesa-style functions should then call the _mesa_*
+ * version of these functions.  This is an approximation to OO design
+ * (inheritance and virtual functions).
+ */
+static void
+_mesa_init_default_exports(__GLexports *exports)
+{
+    exports->destroyContext = _mesa_destroyContext;
+    exports->loseCurrent = _mesa_loseCurrent;
+    exports->makeCurrent = _mesa_makeCurrent;
+    exports->shareContext = _mesa_shareContext;
+    exports->copyContext = _mesa_copyContext;
+    exports->forceCurrent = _mesa_forceCurrent;
+    exports->notifyResize = _mesa_notifyResize;
+    exports->notifyDestroy = _mesa_notifyDestroy;
+    exports->notifySwapBuffers = _mesa_notifySwapBuffers;
+    exports->dispatchExec = _mesa_dispatchExec;
+    exports->beginDispatchOverride = _mesa_beginDispatchOverride;
+    exports->endDispatchOverride = _mesa_endDispatchOverride;
+}
+
+
 
 /* exported OpenGL SI interface */
 __GLcontext *
@@ -112,12 +233,13 @@ __glCoreCreateContext(__GLimports *imports, __GLcontextModes *modes)
 {
     GLcontext *ctx;
 
-    ctx = (GLcontext *) (*imports->calloc)(0, 1, sizeof(GLcontext));
+    ctx = (GLcontext *) (*imports->calloc)(NULL, 1, sizeof(GLcontext));
     if (ctx == NULL) {
        return NULL;
     }
-   ctx->Driver.CurrentExecPrimitive=0;
+    ctx->Driver.CurrentExecPrimitive=0;  /* XXX why is this here??? */
     ctx->imports = *imports;
+    _mesa_init_default_exports(&(ctx->exports));
 
     _mesa_initialize_visual(&ctx->Visual,
                             modes->rgbMode,
@@ -136,10 +258,7 @@ __glCoreCreateContext(__GLimports *imports, __GLcontextModes *modes)
                             modes->accumAlphaBits,
                             0);
 
-    /* KW: was imports->wscx */
-    _mesa_initialize_context(ctx, &ctx->Visual, NULL, imports->other, GL_FALSE);
-
-    ctx->exports.destroyContext = _mesa_DestroyContext;
+    _mesa_initialize_context(ctx, &ctx->Visual, NULL, imports);
 
     return ctx;
 }
@@ -159,12 +278,6 @@ __glCoreNopDispatch(void)
 }
 
 
-/**********************************************************************/
-/*****                  Context and Thread management             *****/
-/**********************************************************************/
-
-
-
 /**********************************************************************/
 /***** GL Visual allocation/destruction                           *****/
 /**********************************************************************/
@@ -349,6 +462,8 @@ _mesa_initialize_framebuffer( GLframebuffer *buffer,
    assert(buffer);
    assert(visual);
 
+   BZERO(buffer, sizeof(GLframebuffer));
+
    /* sanity checks */
    if (softwareDepth ) {
       assert(visual->depthBits > 0);
@@ -441,7 +556,7 @@ _glthread_DECLARE_STATIC_MUTEX(OneTimeLock);
  * This function just calls all the various one-time-init functions in Mesa.
  */
 static void
-one_time_init( void )
+one_time_init( GLcontext *ctx )
 {
    static GLboolean alreadyCalled = GL_FALSE;
    _glthread_LOCK_MUTEX(OneTimeLock);
@@ -462,15 +577,16 @@ one_time_init( void )
 #ifdef USE_SPARC_ASM
       _mesa_init_sparc_glapi_relocs();
 #endif
-      if (getenv("MESA_DEBUG")) {
+      if (ctx->imports.getenv(ctx, "MESA_DEBUG")) {
          _glapi_noop_enable_warnings(GL_TRUE);
+         _glapi_set_warning_func( (_glapi_warning_func) _mesa_warning );
       }
       else {
          _glapi_noop_enable_warnings(GL_FALSE);
       }
 
 #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
-   fprintf(stderr, "Mesa DEBUG build %s %s\n", __DATE__, __TIME__);
+      _mesa_debug(ctx, "Mesa DEBUG build %s %s\n", __DATE__, __TIME__);
 #endif
 
       alreadyCalled = GL_TRUE;
@@ -489,7 +605,7 @@ init_matrix_stack( struct matrix_stack *stack,
    stack->MaxDepth = maxDepth;
    stack->DirtyFlag = dirtyFlag;
    /* The stack */
-   stack->Stack = CALLOC(maxDepth * sizeof(GLmatrix));
+   stack->Stack = (GLmatrix *) CALLOC(maxDepth * sizeof(GLmatrix));
    for (i = 0; i < maxDepth; i++) {
       _math_matrix_ctr(&stack->Stack[i]);
       _math_matrix_alloc_inv(&stack->Stack[i]);
@@ -532,26 +648,33 @@ alloc_shared_state( void )
    /* Default Texture objects */
    outOfMemory = GL_FALSE;
 
-   ss->Default1D = _mesa_alloc_texture_object(ss, 0, 1);
+   ss->Default1D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_1D);
    if (!ss->Default1D) {
       outOfMemory = GL_TRUE;
    }
 
-   ss->Default2D = _mesa_alloc_texture_object(ss, 0, 2);
+   ss->Default2D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_2D);
    if (!ss->Default2D) {
       outOfMemory = GL_TRUE;
    }
 
-   ss->Default3D = _mesa_alloc_texture_object(ss, 0, 3);
+   ss->Default3D = _mesa_alloc_texture_object(ss, 0, GL_TEXTURE_3D);
    if (!ss->Default3D) {
       outOfMemory = GL_TRUE;
    }
 
-   ss->DefaultCubeMap = _mesa_alloc_texture_object(ss, 0, 6);
+   ss->DefaultCubeMap = _mesa_alloc_texture_object(ss, 0,
+                                                   GL_TEXTURE_CUBE_MAP_ARB);
    if (!ss->DefaultCubeMap) {
       outOfMemory = GL_TRUE;
    }
 
+   ss->DefaultRect = _mesa_alloc_texture_object(ss, 0,
+                                                GL_TEXTURE_RECTANGLE_NV);
+   if (!ss->DefaultRect) {
+      outOfMemory = GL_TRUE;
+   }
+
    if (!ss->DisplayList || !ss->TexObjects || !ss->VertexPrograms
        || outOfMemory) {
       /* Ran out of memory at some point.  Free everything and return NULL */
@@ -569,6 +692,8 @@ alloc_shared_state( void )
          _mesa_free_texture_object(ss, ss->Default3D);
       if (ss->DefaultCubeMap)
          _mesa_free_texture_object(ss, ss->DefaultCubeMap);
+      if (ss->DefaultRect)
+         _mesa_free_texture_object(ss, ss->DefaultRect);
       FREE(ss);
       return NULL;
    }
@@ -727,6 +852,7 @@ init_texture_unit( GLcontext *ctx, GLuint unit )
    texUnit->Current2D = ctx->Shared->Default2D;
    texUnit->Current3D = ctx->Shared->Default3D;
    texUnit->CurrentCubeMap = ctx->Shared->DefaultCubeMap;
+   texUnit->CurrentRect = ctx->Shared->DefaultRect;
 }
 
 
@@ -784,6 +910,7 @@ init_attrib_groups( GLcontext *ctx )
    ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
    ctx->Const.Max3DTextureLevels = MAX_3D_TEXTURE_LEVELS;
    ctx->Const.MaxCubeTextureLevels = MAX_CUBE_TEXTURE_LEVELS;
+   ctx->Const.MaxTextureRectSize = MAX_TEXTURE_RECT_SIZE;
    ctx->Const.MaxTextureUnits = MAX_TEXTURE_UNITS;
    ctx->Const.MaxTextureMaxAnisotropy = MAX_TEXTURE_MAX_ANISOTROPY;
    ctx->Const.MaxTextureLodBias = MAX_TEXTURE_LOD_BIAS;
@@ -803,7 +930,6 @@ init_attrib_groups( GLcontext *ctx )
    ctx->Const.MaxColorTableSize = MAX_COLOR_TABLE_SIZE;
    ctx->Const.MaxConvolutionWidth = MAX_CONVOLUTION_WIDTH;
    ctx->Const.MaxConvolutionHeight = MAX_CONVOLUTION_HEIGHT;
-   ctx->Const.NumCompressedTextureFormats = 0;
    ctx->Const.MaxClipPlanes = MAX_CLIP_PLANES;
    ctx->Const.MaxLights = MAX_LIGHTS;
 
@@ -851,7 +977,6 @@ init_attrib_groups( GLcontext *ctx )
    ctx->Color.ColorLogicOpEnabled = GL_FALSE;
    ctx->Color.LogicOp = GL_COPY;
    ctx->Color.DitherFlag = GL_TRUE;
-   ctx->Color.MultiDrawBuffer = GL_FALSE;
 
    /* Current group */
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 0.0, 0.0, 0.0, 0.0 );
@@ -869,8 +994,7 @@ init_attrib_groups( GLcontext *ctx )
    ASSIGN_4V( ctx->Current.RasterColor, 1.0, 1.0, 1.0, 1.0 );
    ctx->Current.RasterIndex = 1;
    for (i=0; i<MAX_TEXTURE_UNITS; i++)
-      ASSIGN_4V( ctx->Current.RasterMultiTexCoord[i], 0.0, 0.0, 0.0, 1.0 );
-   ctx->Current.RasterTexCoord = ctx->Current.RasterMultiTexCoord[0];
+      ASSIGN_4V( ctx->Current.RasterTexCoords[i], 0.0, 0.0, 0.0, 1.0 );
    ctx->Current.RasterPosValid = GL_TRUE;
 
 
@@ -1129,7 +1253,11 @@ init_attrib_groups( GLcontext *ctx )
    ctx->Point.MinSize = 0.0;
    ctx->Point.MaxSize = ctx->Const.MaxPointSize;
    ctx->Point.Threshold = 1.0;
-   ctx->Point.SpriteMode = GL_FALSE; /* GL_MESA_sprite_point */
+   ctx->Point.PointSprite = GL_FALSE; /* GL_NV_point_sprite */
+   ctx->Point.SpriteRMode = GL_ZERO; /* GL_NV_point_sprite */
+   for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
+      ctx->Point.CoordReplace[i] = GL_FALSE; /* GL_NV_point_sprite */
+   }
 
    /* Polygon group */
    ctx->Polygon.CullFlag = GL_FALSE;
@@ -1159,18 +1287,28 @@ init_attrib_groups( GLcontext *ctx )
 
    /* Stencil group */
    ctx->Stencil.Enabled = GL_FALSE;
-   ctx->Stencil.Function = GL_ALWAYS;
-   ctx->Stencil.FailFunc = GL_KEEP;
-   ctx->Stencil.ZPassFunc = GL_KEEP;
-   ctx->Stencil.ZFailFunc = GL_KEEP;
-   ctx->Stencil.Ref = 0;
-   ctx->Stencil.ValueMask = STENCIL_MAX;
+   ctx->Stencil.TestTwoSide = GL_FALSE;
+   ctx->Stencil.ActiveFace = 0;  /* 0 = GL_FRONT, 1 = GL_BACK */
+   ctx->Stencil.Function[0] = GL_ALWAYS;
+   ctx->Stencil.Function[1] = GL_ALWAYS;
+   ctx->Stencil.FailFunc[0] = GL_KEEP;
+   ctx->Stencil.FailFunc[1] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[0] = GL_KEEP;
+   ctx->Stencil.ZPassFunc[1] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[0] = GL_KEEP;
+   ctx->Stencil.ZFailFunc[1] = GL_KEEP;
+   ctx->Stencil.Ref[0] = 0;
+   ctx->Stencil.Ref[1] = 0;
+   ctx->Stencil.ValueMask[0] = STENCIL_MAX;
+   ctx->Stencil.ValueMask[1] = STENCIL_MAX;
+   ctx->Stencil.WriteMask[0] = STENCIL_MAX;
+   ctx->Stencil.WriteMask[1] = STENCIL_MAX;
    ctx->Stencil.Clear = 0;
-   ctx->Stencil.WriteMask = STENCIL_MAX;
 
    /* Texture group */
    ctx->Texture.CurrentUnit = 0;      /* multitexture */
-   ctx->Texture._ReallyEnabled = 0;
+   ctx->Texture._ReallyEnabled = 0;   /* XXX obsolete */
+   ctx->Texture._EnabledUnits = 0;
    for (i=0; i<MAX_TEXTURE_UNITS; i++)
       init_texture_unit( ctx, i );
    ctx->Texture.SharedPalette = GL_FALSE;
@@ -1316,11 +1454,12 @@ init_attrib_groups( GLcontext *ctx )
    _mesa_init_colortable(&ctx->ProxyPostColorMatrixColorTable);
 
    /* GL_NV_vertex_program */
-   ctx->VertexProgram.Current = NULL;
-   ctx->VertexProgram.CurrentID = 0;
    ctx->VertexProgram.Enabled = GL_FALSE;
    ctx->VertexProgram.PointSizeEnabled = GL_FALSE;
    ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
+   ctx->VertexProgram.CurrentID = 0;
+   ctx->VertexProgram.ErrorPos = -1;
+   ctx->VertexProgram.Current = NULL;
    for (i = 0; i < VP_NUM_PROG_REGS / 4; i++) {
       ctx->VertexProgram.TrackMatrix[i] = GL_NONE;
       ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV;
@@ -1342,14 +1481,14 @@ init_attrib_groups( GLcontext *ctx )
    ctx->OcclusionResultSaved = GL_FALSE;
 
    /* For debug/development only */
-   ctx->NoRaster = getenv("MESA_NO_RASTER") ? GL_TRUE : GL_FALSE;
+   ctx->NoRaster = ctx->imports.getenv(ctx, "MESA_NO_RASTER") ? GL_TRUE : GL_FALSE;
    ctx->FirstTimeCurrent = GL_TRUE;
 
    /* Dither disable */
-   ctx->NoDither = getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
+   ctx->NoDither = ctx->imports.getenv(ctx, "MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
    if (ctx->NoDither) {
-      if (getenv("MESA_DEBUG")) {
-         fprintf(stderr, "MESA_NO_DITHER set - dithering disabled\n");
+      if (ctx->imports.getenv(ctx, "MESA_DEBUG")) {
+         _mesa_debug(ctx, "MESA_NO_DITHER set - dithering disabled\n");
       }
       ctx->Color.DitherFlag = GL_FALSE;
    }
@@ -1369,25 +1508,26 @@ alloc_proxy_textures( GLcontext *ctx )
    GLboolean out_of_memory;
    GLint i;
 
-   ctx->Texture.Proxy1D = _mesa_alloc_texture_object(NULL, 0, 1);
+   ctx->Texture.Proxy1D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_1D);
    if (!ctx->Texture.Proxy1D) {
       return GL_FALSE;
    }
 
-   ctx->Texture.Proxy2D = _mesa_alloc_texture_object(NULL, 0, 2);
+   ctx->Texture.Proxy2D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_2D);
    if (!ctx->Texture.Proxy2D) {
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
       return GL_FALSE;
    }
 
-   ctx->Texture.Proxy3D = _mesa_alloc_texture_object(NULL, 0, 3);
+   ctx->Texture.Proxy3D = _mesa_alloc_texture_object(NULL, 0, GL_TEXTURE_3D);
    if (!ctx->Texture.Proxy3D) {
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
       return GL_FALSE;
    }
 
-   ctx->Texture.ProxyCubeMap = _mesa_alloc_texture_object(NULL, 0, 6);
+   ctx->Texture.ProxyCubeMap = _mesa_alloc_texture_object(NULL, 0,
+                                                     GL_TEXTURE_CUBE_MAP_ARB);
    if (!ctx->Texture.ProxyCubeMap) {
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
@@ -1395,6 +1535,16 @@ alloc_proxy_textures( GLcontext *ctx )
       return GL_FALSE;
    }
 
+   ctx->Texture.ProxyRect = _mesa_alloc_texture_object(NULL, 0,
+                                                      GL_TEXTURE_RECTANGLE_NV);
+   if (!ctx->Texture.ProxyRect) {
+      _mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
+      _mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
+      _mesa_free_texture_object(NULL, ctx->Texture.Proxy3D);
+      _mesa_free_texture_object(NULL, ctx->Texture.ProxyCubeMap);
+      return GL_FALSE;
+   }
+
    out_of_memory = GL_FALSE;
    for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
       ctx->Texture.Proxy1D->Image[i] = _mesa_alloc_texture_image();
@@ -1408,6 +1558,10 @@ alloc_proxy_textures( GLcontext *ctx )
          out_of_memory = GL_TRUE;
       }
    }
+   ctx->Texture.ProxyRect->Image[0] = _mesa_alloc_texture_image();
+   if (!ctx->Texture.ProxyRect->Image[0])
+      out_of_memory = GL_TRUE;
+
    if (out_of_memory) {
       for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
          if (ctx->Texture.Proxy1D->Image[i]) {
@@ -1423,10 +1577,14 @@ alloc_proxy_textures( GLcontext *ctx )
             _mesa_free_texture_image(ctx->Texture.ProxyCubeMap->Image[i]);
          }
       }
+      if (ctx->Texture.ProxyRect->Image[0]) {
+         _mesa_free_texture_image(ctx->Texture.ProxyRect->Image[0]);
+      }
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy1D);
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy2D);
       _mesa_free_texture_object(NULL, ctx->Texture.Proxy3D);
       _mesa_free_texture_object(NULL, ctx->Texture.ProxyCubeMap);
+      _mesa_free_texture_object(NULL, ctx->Texture.ProxyRect);
       return GL_FALSE;
    }
    else {
@@ -1435,6 +1593,44 @@ alloc_proxy_textures( GLcontext *ctx )
 }
 
 
+static void add_debug_flags( const char *debug )
+{
+#ifdef MESA_DEBUG
+   if (strstr(debug, "varray")) 
+      MESA_VERBOSE |= VERBOSE_VARRAY;
+
+   if (strstr(debug, "tex")) 
+      MESA_VERBOSE |= VERBOSE_TEXTURE;
+
+   if (strstr(debug, "imm")) 
+      MESA_VERBOSE |= VERBOSE_IMMEDIATE;
+
+   if (strstr(debug, "pipe")) 
+      MESA_VERBOSE |= VERBOSE_PIPELINE;
+
+   if (strstr(debug, "driver")) 
+      MESA_VERBOSE |= VERBOSE_DRIVER;
+
+   if (strstr(debug, "state")) 
+      MESA_VERBOSE |= VERBOSE_STATE;
+
+   if (strstr(debug, "api")) 
+      MESA_VERBOSE |= VERBOSE_API;
+
+   if (strstr(debug, "list")) 
+      MESA_VERBOSE |= VERBOSE_DISPLAY_LIST;
+
+   if (strstr(debug, "lighting")) 
+      MESA_VERBOSE |= VERBOSE_LIGHTING;
+   
+   /* Debug flag:
+    */
+   if (strstr(debug, "flush")) 
+      MESA_DEBUG_FLAGS |= DEBUG_ALWAYS_FLUSH;
+#endif
+}
+
+
 /*
  * Initialize a GLcontext struct.  This includes allocating all the
  * other structs and arrays which hang off of the context by pointers.
@@ -1443,25 +1639,33 @@ GLboolean
 _mesa_initialize_context( GLcontext *ctx,
                           const GLvisual *visual,
                           GLcontext *share_list,
-                          void *driver_ctx,
-                          GLboolean direct )
+                          const __GLimports *imports )
 {
    GLuint dispatchSize;
 
-   (void) direct;  /* not used */
+   ASSERT(imports);
+   ASSERT(imports->other); /* other points to the device driver's context */
+
+   /* assing imports */
+   ctx->imports = *imports;
+
+   /* initialize the exports (Mesa functions called by the window system) */
+   _mesa_init_default_exports( &(ctx->exports) );
 
    /* misc one-time initializations */
-   one_time_init();
+   one_time_init(ctx);
 
+#if 0
    /**
     ** OpenGL SI stuff
     **/
    if (!ctx->imports.malloc) {
-      _mesa_InitDefaultImports(&ctx->imports, driver_ctx, NULL);
+      _mesa_init_default_imports(&ctx->imports, driver_ctx);
    }
    /* exports are setup by the device driver */
+#endif
 
-   ctx->DriverCtx = driver_ctx;
+   ctx->DriverCtx = imports->other;
    ctx->Visual = *visual;
    ctx->DrawBuffer = NULL;
    ctx->ReadBuffer = NULL;
@@ -1486,22 +1690,23 @@ _mesa_initialize_context( GLcontext *ctx,
    ctx->Shared->Default2D->RefCount += MAX_TEXTURE_UNITS;
    ctx->Shared->Default3D->RefCount += MAX_TEXTURE_UNITS;
    ctx->Shared->DefaultCubeMap->RefCount += MAX_TEXTURE_UNITS;
+   ctx->Shared->DefaultRect->RefCount += MAX_TEXTURE_UNITS;
 
    init_attrib_groups( ctx );
 
    if (visual->doubleBufferMode) {
       ctx->Color.DrawBuffer = GL_BACK;
-      ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
-      ctx->Color.DrawDestMask = BACK_LEFT_BIT;
+      ctx->Color._DriverDrawBuffer = GL_BACK_LEFT;
+      ctx->Color._DrawDestMask = BACK_LEFT_BIT;
       ctx->Pixel.ReadBuffer = GL_BACK;
-      ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
+      ctx->Pixel._DriverReadBuffer = GL_BACK_LEFT;
    }
    else {
       ctx->Color.DrawBuffer = GL_FRONT;
-      ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
-      ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
+      ctx->Color._DriverDrawBuffer = GL_FRONT_LEFT;
+      ctx->Color._DrawDestMask = FRONT_LEFT_BIT;
       ctx->Pixel.ReadBuffer = GL_FRONT;
-      ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
+      ctx->Pixel._DriverReadBuffer = GL_FRONT_LEFT;
    }
 
    if (!alloc_proxy_textures(ctx)) {
@@ -1518,6 +1723,8 @@ _mesa_initialize_context( GLcontext *ctx,
    _glapi_add_entrypoint("glCompressedTexSubImage2DARB", 558);
    _glapi_add_entrypoint("glCompressedTexSubImage1DARB", 559);
    _glapi_add_entrypoint("glGetCompressedTexImageARB", 560);
+   /* XXX we should add a bunch of new functions here */
+
 
    /* Find the larger of Mesa's dispatch table and libGL's dispatch table.
     * In practice, this'll be the same for stand-alone Mesa.  But for DRI
@@ -1598,6 +1805,13 @@ _mesa_initialize_context( GLcontext *ctx,
    trInitDispatch(ctx->TraceDispatch);
 #endif
 
+
+   if (ctx->imports.getenv(ctx, "MESA_DEBUG"))
+      add_debug_flags(ctx->imports.getenv(ctx, "MESA_DEBUG"));
+
+   if (ctx->imports.getenv(ctx, "MESA_VERBOSE"))
+      add_debug_flags(ctx->imports.getenv(ctx, "MESA_VERBOSE"));
+
    return GL_TRUE;
 }
 
@@ -1607,25 +1821,31 @@ _mesa_initialize_context( GLcontext *ctx,
  * Allocate and initialize a GLcontext structure.
  * Input:  visual - a GLvisual pointer (we copy the struct contents)
  *         sharelist - another context to share display lists with or NULL
- *         driver_ctx - pointer to device driver's context state struct
+ *         imports - points to a fully-initialized __GLimports object.
  * Return:  pointer to a new __GLcontextRec or NULL if error.
  */
 GLcontext *
 _mesa_create_context( const GLvisual *visual,
                       GLcontext *share_list,
-                      void *driver_ctx,
-                      GLboolean direct )
+                      const __GLimports *imports )
 {
-   GLcontext *ctx = (GLcontext *) CALLOC( sizeof(GLcontext) );
-   if (!ctx) {
+   GLcontext *ctx;
+
+   ASSERT(visual);
+   ASSERT(imports);
+   ASSERT(imports->calloc);
+
+   ctx = (GLcontext *) imports->calloc(NULL, 1, sizeof(GLcontext));
+   if (!ctx)
       return NULL;
-   }
-   ctx->Driver.CurrentExecPrimitive = 0;
-   if (_mesa_initialize_context(ctx, visual, share_list, driver_ctx, direct)) {
+
+   ctx->Driver.CurrentExecPrimitive = 0;  /* XXX why is this here??? */
+
+   if (_mesa_initialize_context(ctx, visual, share_list, imports)) {
       return ctx;
    }
    else {
-      FREE(ctx);
+      imports->free(NULL, ctx);
       return NULL;
    }
 }
@@ -1688,6 +1908,7 @@ _mesa_free_context_data( GLcontext *ctx )
    _mesa_free_texture_object( NULL, ctx->Texture.Proxy2D );
    _mesa_free_texture_object( NULL, ctx->Texture.Proxy3D );
    _mesa_free_texture_object( NULL, ctx->Texture.ProxyCubeMap );
+   _mesa_free_texture_object( NULL, ctx->Texture.ProxyRect );
 
    /* Free evaluator data */
    if (ctx->EvalMap.Map1Vertex3.Points)
@@ -1771,116 +1992,149 @@ void
 _mesa_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
 {
    if (mask & GL_ACCUM_BUFFER_BIT) {
-      MEMCPY( &dst->Accum, &src->Accum, sizeof(struct gl_accum_attrib) );
+      /* OK to memcpy */
+      dst->Accum = src->Accum;
    }
    if (mask & GL_COLOR_BUFFER_BIT) {
-      MEMCPY( &dst->Color, &src->Color, sizeof(struct gl_colorbuffer_attrib) );
+      /* OK to memcpy */
+      dst->Color = src->Color;
    }
    if (mask & GL_CURRENT_BIT) {
-      MEMCPY( &dst->Current, &src->Current, sizeof(struct gl_current_attrib) );
+      /* OK to memcpy */
+      dst->Current = src->Current;
    }
    if (mask & GL_DEPTH_BUFFER_BIT) {
-      MEMCPY( &dst->Depth, &src->Depth, sizeof(struct gl_depthbuffer_attrib) );
+      /* OK to memcpy */
+      dst->Depth = src->Depth;
    }
    if (mask & GL_ENABLE_BIT) {
       /* no op */
    }
    if (mask & GL_EVAL_BIT) {
-      MEMCPY( &dst->Eval, &src->Eval, sizeof(struct gl_eval_attrib) );
+      /* OK to memcpy */
+      dst->Eval = src->Eval;
    }
    if (mask & GL_FOG_BIT) {
-      MEMCPY( &dst->Fog, &src->Fog, sizeof(struct gl_fog_attrib) );
+      /* OK to memcpy */
+      dst->Fog = src->Fog;
    }
    if (mask & GL_HINT_BIT) {
-      MEMCPY( &dst->Hint, &src->Hint, sizeof(struct gl_hint_attrib) );
+      /* OK to memcpy */
+      dst->Hint = src->Hint;
    }
    if (mask & GL_LIGHTING_BIT) {
-      MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light_attrib) );
-      /*       gl_reinit_light_attrib( &dst->Light ); */
+      GLuint i;
+      /* begin with memcpy */
+      MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light) );
+      /* fixup linked lists to prevent pointer insanity */
+      make_empty_list( &(dst->Light.EnabledList) );
+      for (i = 0; i < MAX_LIGHTS; i++) {
+         if (dst->Light.Light[i].Enabled) {
+            insert_at_tail(&(dst->Light.EnabledList), &(dst->Light.Light[i]));
+         }
+      }
    }
    if (mask & GL_LINE_BIT) {
-      MEMCPY( &dst->Line, &src->Line, sizeof(struct gl_line_attrib) );
+      /* OK to memcpy */
+      dst->Line = src->Line;
    }
    if (mask & GL_LIST_BIT) {
-      MEMCPY( &dst->List, &src->List, sizeof(struct gl_list_attrib) );
+      /* OK to memcpy */
+      dst->List = src->List;
    }
    if (mask & GL_PIXEL_MODE_BIT) {
-      MEMCPY( &dst->Pixel, &src->Pixel, sizeof(struct gl_pixel_attrib) );
+      /* OK to memcpy */
+      dst->Pixel = src->Pixel;
    }
    if (mask & GL_POINT_BIT) {
-      MEMCPY( &dst->Point, &src->Point, sizeof(struct gl_point_attrib) );
+      /* OK to memcpy */
+      dst->Point = src->Point;
    }
    if (mask & GL_POLYGON_BIT) {
-      MEMCPY( &dst->Polygon, &src->Polygon, sizeof(struct gl_polygon_attrib) );
+      /* OK to memcpy */
+      dst->Polygon = src->Polygon;
    }
    if (mask & GL_POLYGON_STIPPLE_BIT) {
       /* Use loop instead of MEMCPY due to problem with Portland Group's
        * C compiler.  Reported by John Stone.
        */
-      int i;
-      for (i=0;i<32;i++) {
+      GLuint i;
+      for (i = 0; i < 32; i++) {
          dst->PolygonStipple[i] = src->PolygonStipple[i];
       }
    }
    if (mask & GL_SCISSOR_BIT) {
-      MEMCPY( &dst->Scissor, &src->Scissor, sizeof(struct gl_scissor_attrib) );
+      /* OK to memcpy */
+      dst->Scissor = src->Scissor;
    }
    if (mask & GL_STENCIL_BUFFER_BIT) {
-      MEMCPY( &dst->Stencil, &src->Stencil, sizeof(struct gl_stencil_attrib) );
+      /* OK to memcpy */
+      dst->Stencil = src->Stencil;
    }
    if (mask & GL_TEXTURE_BIT) {
-      MEMCPY( &dst->Texture, &src->Texture, sizeof(struct gl_texture_attrib) );
+      /* Cannot memcpy because of pointers */
+      _mesa_copy_texture_state(src, dst);
    }
    if (mask & GL_TRANSFORM_BIT) {
-      MEMCPY( &dst->Transform, &src->Transform, sizeof(struct gl_transform_attrib) );
+      /* OK to memcpy */
+      dst->Transform = src->Transform;
    }
    if (mask & GL_VIEWPORT_BIT) {
-      MEMCPY( &dst->Viewport, &src->Viewport, sizeof(struct gl_viewport_attrib) );
+      /* Cannot use memcpy, because of pointers in GLmatrix _WindowMap */
+      dst->Viewport.X = src->Viewport.X;
+      dst->Viewport.Y = src->Viewport.Y;
+      dst->Viewport.Width = src->Viewport.Width;
+      dst->Viewport.Height = src->Viewport.Height;
+      dst->Viewport.Near = src->Viewport.Near;
+      dst->Viewport.Far = src->Viewport.Far;
+      _math_matrix_copy(&dst->Viewport._WindowMap, &src->Viewport._WindowMap);
    }
+
    /* XXX FIXME:  Call callbacks?
     */
    dst->NewState = _NEW_ALL;
 }
 
 
-/*
- * Set the current context, binding the given frame buffer to the context.
- */
-void
-_mesa_make_current( GLcontext *newCtx, GLframebuffer *buffer )
-{
-   _mesa_make_current2( newCtx, buffer, buffer );
-}
-
 
 static void print_info( void )
 {
-   fprintf(stderr, "Mesa GL_VERSION = %s\n",
+   _mesa_debug(NULL, "Mesa GL_VERSION = %s\n",
           (char *) _mesa_GetString(GL_VERSION));
-   fprintf(stderr, "Mesa GL_RENDERER = %s\n",
+   _mesa_debug(NULL, "Mesa GL_RENDERER = %s\n",
           (char *) _mesa_GetString(GL_RENDERER));
-   fprintf(stderr, "Mesa GL_VENDOR = %s\n",
+   _mesa_debug(NULL, "Mesa GL_VENDOR = %s\n",
           (char *) _mesa_GetString(GL_VENDOR));
-   fprintf(stderr, "Mesa GL_EXTENSIONS = %s\n",
+   _mesa_debug(NULL, "Mesa GL_EXTENSIONS = %s\n",
           (char *) _mesa_GetString(GL_EXTENSIONS));
 #if defined(THREADS)
-   fprintf(stderr, "Mesa thread-safe: YES\n");
+   _mesa_debug(NULL, "Mesa thread-safe: YES\n");
 #else
-   fprintf(stderr, "Mesa thread-safe: NO\n");
+   _mesa_debug(NULL, "Mesa thread-safe: NO\n");
 #endif
 #if defined(USE_X86_ASM)
-   fprintf(stderr, "Mesa x86-optimized: YES\n");
+   _mesa_debug(NULL, "Mesa x86-optimized: YES\n");
 #else
-   fprintf(stderr, "Mesa x86-optimized: NO\n");
+   _mesa_debug(NULL, "Mesa x86-optimized: NO\n");
 #endif
 #if defined(USE_SPARC_ASM)
-   fprintf(stderr, "Mesa sparc-optimized: YES\n");
+   _mesa_debug(NULL, "Mesa sparc-optimized: YES\n");
 #else
-   fprintf(stderr, "Mesa sparc-optimized: NO\n");
+   _mesa_debug(NULL, "Mesa sparc-optimized: NO\n");
 #endif
 }
 
 
+/*
+ * Set the current context, binding the given frame buffer to the context.
+ */
+void
+_mesa_make_current( GLcontext *newCtx, GLframebuffer *buffer )
+{
+   _mesa_make_current2( newCtx, buffer, buffer );
+}
+
+
 /*
  * Bind the given context to the given draw-buffer and read-buffer
  * and make it the current context for this thread.
@@ -1890,7 +2144,7 @@ _mesa_make_current2( GLcontext *newCtx, GLframebuffer *drawBuffer,
                      GLframebuffer *readBuffer )
 {
    if (MESA_VERBOSE)
-      fprintf(stderr, "_mesa_make_current2()\n");
+      _mesa_debug(newCtx, "_mesa_make_current2()\n");
 
    /* Check that the context's and framebuffer's visuals are compatible.
     * We could do a lot more checking here but this'll catch obvious
@@ -1926,9 +2180,42 @@ _mesa_make_current2( GLcontext *newCtx, GLframebuffer *drawBuffer,
         newCtx->DrawBuffer = drawBuffer;
         newCtx->ReadBuffer = readBuffer;
         newCtx->NewState |= _NEW_BUFFERS;
-        /* _mesa_update_state( newCtx ); */
+
+         if (drawBuffer->Width == 0 && drawBuffer->Height == 0) {
+            /* get initial window size */
+            GLuint bufWidth, bufHeight;
+
+            /* ask device driver for size of output buffer */
+            (*newCtx->Driver.GetBufferSize)( drawBuffer, &bufWidth, &bufHeight );
+
+            if (drawBuffer->Width == bufWidth && drawBuffer->Height == bufHeight)
+               return; /* size is as expected */
+
+            drawBuffer->Width = bufWidth;
+            drawBuffer->Height = bufHeight;
+
+            newCtx->Driver.ResizeBuffers( drawBuffer );
+         }
+
+         if (readBuffer != drawBuffer &&
+             readBuffer->Width == 0 && readBuffer->Height == 0) {
+            /* get initial window size */
+            GLuint bufWidth, bufHeight;
+
+            /* ask device driver for size of output buffer */
+            (*newCtx->Driver.GetBufferSize)( readBuffer, &bufWidth, &bufHeight );
+
+            if (readBuffer->Width == bufWidth && readBuffer->Height == bufHeight)
+               return; /* size is as expected */
+
+            readBuffer->Width = bufWidth;
+            readBuffer->Height = bufHeight;
+
+            newCtx->Driver.ResizeBuffers( readBuffer );
+         }
       }
 
+      /* This is only for T&L - a bit out of place, or misnamed (BP) */
       if (newCtx->Driver.MakeCurrent)
         newCtx->Driver.MakeCurrent( newCtx, drawBuffer, readBuffer );
 
@@ -1938,7 +2225,7 @@ _mesa_make_current2( GLcontext *newCtx, GLframebuffer *drawBuffer,
        * information.
        */
       if (newCtx->FirstTimeCurrent) {
-        if (getenv("MESA_INFO")) {
+        if (newCtx->imports.getenv(newCtx, "MESA_INFO")) {
            print_info();
         }
         newCtx->FirstTimeCurrent = GL_FALSE;
@@ -1993,96 +2280,12 @@ _mesa_get_dispatch(GLcontext *ctx)
 
 
 /*
- * This function is called when the Mesa user has stumbled into a code
- * path which may not be implemented fully or correctly.
- */
-void _mesa_problem( const GLcontext *ctx, const char *s )
-{
-   fprintf( stderr, "Mesa implementation error: %s\n", s );
-#ifdef XF86DRI
-   fprintf( stderr, "Please report to the DRI bug database at dri.sourceforge.net\n");
-#else
-   fprintf( stderr, "Please report to the Mesa bug database at www.mesa3d.org\n" );
-#endif
-   (void) ctx;
-}
-
-
-
-/*
- * This is called to inform the user that he or she has tried to do
- * something illogical or if there's likely a bug in their program
- * (like enabled depth testing without a depth buffer).
+ * Record the given error code and call the driver's Error function if defined.
+ * This is called via _mesa_error().
  */
 void
-_mesa_warning( const GLcontext *ctx, const char *s )
+_mesa_record_error( GLcontext *ctx, GLenum error )
 {
-   (*ctx->imports.warning)((__GLcontext *) ctx, (char *) s);
-}
-
-
-
-/*
- * This is Mesa's error handler.  Normally, all that's done is the updating
- * of the current error value.  If Mesa is compiled with -DDEBUG or if the
- * environment variable "MESA_DEBUG" is defined then a real error message
- * is printed to stderr.
- * Input:  ctx - the GL context
- *         error - the error value
- *         where - usually the name of function where error was detected
- */
-void
-_mesa_error( GLcontext *ctx, GLenum error, const char *where )
-{
-   const char *debugEnv = getenv("MESA_DEBUG");
-   GLboolean debug;
-
-#ifdef DEBUG
-   if (debugEnv && strstr(debugEnv, "silent"))
-      debug = GL_FALSE;
-   else
-      debug = GL_TRUE;
-#else
-   if (debugEnv)
-      debug = GL_TRUE;
-   else
-      debug = GL_FALSE;
-#endif
-
-   if (debug) {
-      const char *errstr;
-      switch (error) {
-        case GL_NO_ERROR:
-           errstr = "GL_NO_ERROR";
-           break;
-        case GL_INVALID_VALUE:
-           errstr = "GL_INVALID_VALUE";
-           break;
-        case GL_INVALID_ENUM:
-           errstr = "GL_INVALID_ENUM";
-           break;
-        case GL_INVALID_OPERATION:
-           errstr = "GL_INVALID_OPERATION";
-           break;
-        case GL_STACK_OVERFLOW:
-           errstr = "GL_STACK_OVERFLOW";
-           break;
-        case GL_STACK_UNDERFLOW:
-           errstr = "GL_STACK_UNDERFLOW";
-           break;
-        case GL_OUT_OF_MEMORY:
-           errstr = "GL_OUT_OF_MEMORY";
-           break;
-         case GL_TABLE_TOO_LARGE:
-            errstr = "GL_TABLE_TOO_LARGE";
-            break;
-        default:
-           errstr = "unknown";
-           break;
-      }
-      fprintf(stderr, "Mesa user error: %s in %s\n", errstr, where);
-   }
-
    if (!ctx)
       return;
 
@@ -2097,7 +2300,6 @@ _mesa_error( GLcontext *ctx, GLenum error, const char *where )
 }
 
 
-
 void
 _mesa_Finish( void )
 {