Changes to reduce the memory footprint of display lists
[mesa.git] / src / mesa / main / context.c
index 61c1641c4624243c0d1c5dce6bbbc29e88bb7cdc..ea66f135b6e39c19aaa2ff43eb8d9a329e2dc90e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: context.c,v 1.2 1999/08/26 14:50:49 keithw Exp $ */
+/* $Id: context.c,v 1.16 1999/10/19 18:37:02 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -25,6 +25,8 @@
  */
 
 
+/* $XFree86: xc/lib/GL/mesa/src/context.c,v 1.4 1999/04/04 00:20:21 dawes Exp $ */
+
 /*
  * If multi-threading is enabled (-DTHREADS) then each thread has it's
  * own rendering context.  A thread obtains the pointer to its GLcontext
 #ifdef PC_HEADER
 #include "all.h"
 #else
+#ifndef XFree86Server
 #include <assert.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#else
+#include "GL/xf86glx.h"
+#endif
 #include "accum.h"
 #include "alphabuf.h"
 #include "api.h"
@@ -53,6 +59,7 @@
 #include "dlist.h"
 #include "eval.h"
 #include "enums.h"
+#include "extensions.h"
 #include "fog.h"
 #include "hash.h"
 #include "light.h"
@@ -83,6 +90,7 @@
 #include "vbfill.h"
 #include "vbrender.h"
 #include "vbxform.h"
+#include "vertices.h"
 #include "xform.h"
 #ifdef XFree86Server
 #include "GL/xf86glx.h"
 #endif
 
 
+/*
+ * Memory allocation functions.  Called via the MALLOC, CALLOC and
+ * FREE macros when DEBUG symbol is defined.
+ * You might want to set breakpoints on these functions or plug in
+ * other memory allocation functions.  The Mesa sources should only
+ * use the MALLOC and FREE macros (which could also be overriden).
+ *
+ * XXX these functions should probably go into a new glmemory.c file.
+ */
+
+/*
+ * Allocate memory (uninitialized)
+ */
+void *gl_malloc(size_t bytes)
+{
+   return malloc(bytes);
+}
+
+/*
+ * Allocate memory and initialize to zero.
+ */
+void *gl_calloc(size_t bytes)
+{
+   return calloc(1, bytes);
+}
+
+/*
+ * Free memory
+ */
+void gl_free(void *ptr)
+{
+   free(ptr);
+}
+
 
 /**********************************************************************/
 /*****                  Context and Thread management             *****/
@@ -305,6 +347,7 @@ static void one_time_init( void )
       gl_init_translate();
       gl_init_vbrender();
       gl_init_vbxform();
+      gl_init_vertices();
       alreadyCalled = GL_TRUE;
    }
 #if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
@@ -318,11 +361,11 @@ static void one_time_init( void )
  */
 static struct gl_shared_state *alloc_shared_state( void )
 {
-   GLuint i;
+   GLuint d;
    struct gl_shared_state *ss;
    GLboolean outOfMemory;
 
-   ss = (struct gl_shared_state*) calloc( 1, sizeof(struct gl_shared_state) );
+   ss = CALLOC_STRUCT(gl_shared_state);
    if (!ss)
       return NULL;
 
@@ -332,16 +375,13 @@ static struct gl_shared_state *alloc_shared_state( void )
 
    /* Default Texture objects */
    outOfMemory = GL_FALSE;
-   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
-      GLuint d;
-      for (d = 1 ; d <= 3 ; d++) {
-        ss->DefaultD[d][i] = gl_alloc_texture_object(ss, 0, d);
-        if (!ss->DefaultD[d][i]) {
-           outOfMemory = GL_TRUE;
-           break;
-        }
-        ss->DefaultD[d][i]->RefCount++; /* don't free if not in use */
+   for (d = 1 ; d <= 3 ; d++) {
+      ss->DefaultD[d] = gl_alloc_texture_object(ss, 0, d);
+      if (!ss->DefaultD[d]) {
+         outOfMemory = GL_TRUE;
+         break;
       }
+      ss->DefaultD[d]->RefCount++; /* don't free if not in use */
    }
 
    if (!ss->DisplayList || !ss->TexObjects || outOfMemory) {
@@ -350,15 +390,13 @@ static struct gl_shared_state *alloc_shared_state( void )
          DeleteHashTable(ss->DisplayList);
       if (ss->TexObjects)
          DeleteHashTable(ss->TexObjects);
-      for (i=0;i<MAX_TEXTURE_UNITS;i++) {
-         if (ss->DefaultD[1][i])
-            gl_free_texture_object(ss, ss->DefaultD[1][i]);
-         if (ss->DefaultD[2][i])
-            gl_free_texture_object(ss, ss->DefaultD[2][i]);
-         if (ss->DefaultD[3][i])
-            gl_free_texture_object(ss, ss->DefaultD[3][i]);
-      }
-      free(ss);
+      if (ss->DefaultD[1])
+         gl_free_texture_object(ss, ss->DefaultD[1]);
+      if (ss->DefaultD[2])
+         gl_free_texture_object(ss, ss->DefaultD[2]);
+      if (ss->DefaultD[3])
+         gl_free_texture_object(ss, ss->DefaultD[3]);
+      FREE(ss);
       return NULL;
    }
    else {
@@ -394,7 +432,7 @@ static void free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    }
    DeleteHashTable(ss->TexObjects);
 
-   free(ss);
+   FREE(ss);
 }
 
 
@@ -477,9 +515,9 @@ static void init_texture_unit( GLcontext *ctx, GLuint unit )
    ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
    ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
 
-   texUnit->CurrentD[1] = ctx->Shared->DefaultD[1][unit];
-   texUnit->CurrentD[2] = ctx->Shared->DefaultD[2][unit];
-   texUnit->CurrentD[3] = ctx->Shared->DefaultD[3][unit];
+   texUnit->CurrentD[1] = ctx->Shared->DefaultD[1];
+   texUnit->CurrentD[2] = ctx->Shared->DefaultD[2];
+   texUnit->CurrentD[3] = ctx->Shared->DefaultD[3];
 }
 
 
@@ -537,7 +575,7 @@ static void init_1d_map( struct gl_1d_map *map, int n, const float *initial )
    map->Order = 1;
    map->u1 = 0.0;
    map->u2 = 1.0;
-   map->Points = (GLfloat *) malloc(n * sizeof(GLfloat));
+   map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
    if (map->Points) {
       GLint i;
       for (i=0;i<n;i++)
@@ -556,7 +594,7 @@ static void init_2d_map( struct gl_2d_map *map, int n, const float *initial )
    map->u2 = 1.0;
    map->v1 = 0.0;
    map->v2 = 1.0;
-   map->Points = (GLfloat *) malloc(n * sizeof(GLfloat));
+   map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
    if (map->Points) {
       GLint i;
       for (i=0;i<n;i++)
@@ -581,7 +619,6 @@ static void initialize_context( GLcontext *ctx )
       ctx->Const.MaxTextureUnits = MAX_TEXTURE_UNITS;
       ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
 
-
       /* Modelview matrix */
       gl_matrix_ctr( &ctx->ModelView );
       gl_matrix_alloc_inv( &ctx->ModelView );
@@ -1002,9 +1039,6 @@ static void initialize_context( GLcontext *ctx )
       ctx->IntegerAccumMode = GL_TRUE;
       ctx->IntegerAccumScaler = 0.0;
 
-      /* multitexture */
-      ctx->TexCoordUnit = 0;
-
       /* Renderer and client attribute stacks */
       ctx->AttribStackDepth = 0;
       ctx->ClientAttribStackDepth = 0;
@@ -1092,7 +1126,7 @@ GLvisual *gl_create_visual( GLboolean rgbFlag,
       return NULL;
    }
 
-   vis = (GLvisual *) calloc( 1, sizeof(GLvisual) );
+   vis = (GLvisual *) CALLOC( sizeof(GLvisual) );
    if (!vis) {
       return NULL;
    }
@@ -1119,7 +1153,7 @@ GLvisual *gl_create_visual( GLboolean rgbFlag,
 
 void gl_destroy_visual( GLvisual *vis )
 {
-   free( vis );
+   FREE( vis );
 }
 
 
@@ -1187,8 +1221,6 @@ static GLboolean alloc_proxy_textures( GLcontext *ctx )
 
 
 
-#define MALLOC_STRUCT(T)  (struct T *) malloc( sizeof(struct T) )
-
 /*
  * Allocate and initialize a GLcontext structure.
  * Input:  visual - a GLvisual pointer
@@ -1217,7 +1249,7 @@ GLcontext *gl_create_context( GLvisual *visual,
    /* misc one-time initializations */
    one_time_init();
 
-   ctx = (GLcontext *) calloc( 1, sizeof(GLcontext) );
+   ctx = (GLcontext *) CALLOC( sizeof(GLcontext) );
    if (!ctx) {
       return NULL;
    }
@@ -1228,15 +1260,15 @@ GLcontext *gl_create_context( GLvisual *visual,
 
    ctx->VB = gl_vb_create_for_immediate( ctx );
    if (!ctx->VB) {
-      free( ctx );
+      FREE( ctx );
       return NULL;
    }
    ctx->input = ctx->VB->IM;
 
    ctx->PB = gl_alloc_pb();
    if (!ctx->PB) {
-      free( ctx->VB );
-      free( ctx );
+      FREE( ctx->VB );
+      FREE( ctx );
       return NULL;
    }
 
@@ -1248,9 +1280,9 @@ GLcontext *gl_create_context( GLvisual *visual,
       /* allocate new group of display lists */
       ctx->Shared = alloc_shared_state();
       if (!ctx->Shared) {
-         free(ctx->VB);
-         free(ctx->PB);
-         free(ctx);
+         FREE(ctx->VB);
+         FREE(ctx->PB);
+         FREE(ctx);
          return NULL;
       }
    }
@@ -1291,6 +1323,15 @@ GLcontext *gl_create_context( GLvisual *visual,
       ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
    }
 
+   
+   /* Fill in some driver defaults now.
+    */
+   ctx->Driver.AllocDepthBuffer = gl_alloc_depth_buffer;
+   ctx->Driver.ReadDepthSpanFloat = gl_read_depth_span_float;
+   ctx->Driver.ReadDepthSpanInt = gl_read_depth_span_int;
+
+   
+
 #ifdef PROFILE
    init_timings( ctx );
 #endif
@@ -1298,9 +1339,9 @@ GLcontext *gl_create_context( GLvisual *visual,
 #ifdef GL_VERSION_1_1
    if (!alloc_proxy_textures(ctx)) {
       free_shared_state(ctx, ctx->Shared);
-      free(ctx->VB);
-      free(ctx->PB);
-      free(ctx);
+      FREE(ctx->VB);
+      FREE(ctx->PB);
+      FREE(ctx);
       return NULL;
    }
 #endif
@@ -1341,10 +1382,17 @@ void gl_destroy_context( GLcontext *ctx )
       for (i = 0 ; i < MAX_MODELVIEW_STACK_DEPTH ; i++) {
         gl_matrix_dtr( &ctx->ModelViewStack[i] );
       }
+      gl_matrix_dtr( &ctx->ProjectionMatrix );
+      for (i = 0 ; i < MAX_PROJECTION_STACK_DEPTH ; i++) {
+        gl_matrix_dtr( &ctx->ProjectionStack[i] );
+      }
+
+      FREE( ctx->PB );
 
+      if(ctx->input != ctx->VB->IM)
+         gl_immediate_free( ctx->input );
 
-      free( ctx->PB );
-      free( ctx->VB );
+      gl_vb_free( ctx->VB );
 
       ctx->Shared->RefCount--;
       assert(ctx->Shared->RefCount>=0);
@@ -1354,9 +1402,9 @@ void gl_destroy_context( GLcontext *ctx )
       }
 
       foreach_s( s, tmps, ctx->ShineTabList ) {
-        free( s );
+        FREE( s );
       }
-      free( ctx->ShineTabList );
+      FREE( ctx->ShineTabList );
 
       /* Free proxy texture objects */
       gl_free_texture_object( NULL, ctx->Texture.Proxy1D );
@@ -1365,44 +1413,52 @@ void gl_destroy_context( GLcontext *ctx )
 
       /* Free evaluator data */
       if (ctx->EvalMap.Map1Vertex3.Points)
-         free( ctx->EvalMap.Map1Vertex3.Points );
+         FREE( ctx->EvalMap.Map1Vertex3.Points );
       if (ctx->EvalMap.Map1Vertex4.Points)
-         free( ctx->EvalMap.Map1Vertex4.Points );
+         FREE( ctx->EvalMap.Map1Vertex4.Points );
       if (ctx->EvalMap.Map1Index.Points)
-         free( ctx->EvalMap.Map1Index.Points );
+         FREE( ctx->EvalMap.Map1Index.Points );
       if (ctx->EvalMap.Map1Color4.Points)
-         free( ctx->EvalMap.Map1Color4.Points );
+         FREE( ctx->EvalMap.Map1Color4.Points );
       if (ctx->EvalMap.Map1Normal.Points)
-         free( ctx->EvalMap.Map1Normal.Points );
+         FREE( ctx->EvalMap.Map1Normal.Points );
       if (ctx->EvalMap.Map1Texture1.Points)
-         free( ctx->EvalMap.Map1Texture1.Points );
+         FREE( ctx->EvalMap.Map1Texture1.Points );
       if (ctx->EvalMap.Map1Texture2.Points)
-         free( ctx->EvalMap.Map1Texture2.Points );
+         FREE( ctx->EvalMap.Map1Texture2.Points );
       if (ctx->EvalMap.Map1Texture3.Points)
-         free( ctx->EvalMap.Map1Texture3.Points );
+         FREE( ctx->EvalMap.Map1Texture3.Points );
       if (ctx->EvalMap.Map1Texture4.Points)
-         free( ctx->EvalMap.Map1Texture4.Points );
+         FREE( ctx->EvalMap.Map1Texture4.Points );
 
       if (ctx->EvalMap.Map2Vertex3.Points)
-         free( ctx->EvalMap.Map2Vertex3.Points );
+         FREE( ctx->EvalMap.Map2Vertex3.Points );
       if (ctx->EvalMap.Map2Vertex4.Points)
-         free( ctx->EvalMap.Map2Vertex4.Points );
+         FREE( ctx->EvalMap.Map2Vertex4.Points );
       if (ctx->EvalMap.Map2Index.Points)
-         free( ctx->EvalMap.Map2Index.Points );
+         FREE( ctx->EvalMap.Map2Index.Points );
       if (ctx->EvalMap.Map2Color4.Points)
-         free( ctx->EvalMap.Map2Color4.Points );
+         FREE( ctx->EvalMap.Map2Color4.Points );
       if (ctx->EvalMap.Map2Normal.Points)
-         free( ctx->EvalMap.Map2Normal.Points );
+         FREE( ctx->EvalMap.Map2Normal.Points );
       if (ctx->EvalMap.Map2Texture1.Points)
-         free( ctx->EvalMap.Map2Texture1.Points );
+         FREE( ctx->EvalMap.Map2Texture1.Points );
       if (ctx->EvalMap.Map2Texture2.Points)
-         free( ctx->EvalMap.Map2Texture2.Points );
+         FREE( ctx->EvalMap.Map2Texture2.Points );
       if (ctx->EvalMap.Map2Texture3.Points)
-         free( ctx->EvalMap.Map2Texture3.Points );
+         FREE( ctx->EvalMap.Map2Texture3.Points );
       if (ctx->EvalMap.Map2Texture4.Points)
-         free( ctx->EvalMap.Map2Texture4.Points );
+         FREE( ctx->EvalMap.Map2Texture4.Points );
 
-      free( (void *) ctx );
+      /* Free cache of immediate buffers. */
+      while (ctx->nr_im_queued-- > 0) {
+         struct immediate * next = ctx->freed_im_queue->next;
+         FREE( ctx->freed_im_queue );
+         ctx->freed_im_queue = next;
+      }
+      gl_extensions_dtr(ctx);
+
+      FREE( (void *) ctx );
 
 #ifndef THREADS
       if (ctx==CC) {
@@ -1427,7 +1483,7 @@ GLframebuffer *gl_create_framebuffer( GLvisual *visual )
 {
    GLframebuffer *buffer;
 
-   buffer = (GLframebuffer *) calloc( 1, sizeof(GLframebuffer) );
+   buffer = (GLframebuffer *) CALLOC( sizeof(GLframebuffer) );
    if (!buffer) {
       return NULL;
    }
@@ -1446,27 +1502,27 @@ void gl_destroy_framebuffer( GLframebuffer *buffer )
 {
    if (buffer) {
       if (buffer->Depth) {
-         free( buffer->Depth );
+         FREE( buffer->Depth );
       }
       if (buffer->Accum) {
-         free( buffer->Accum );
+         FREE( buffer->Accum );
       }
       if (buffer->Stencil) {
-         free( buffer->Stencil );
+         FREE( buffer->Stencil );
       }
       if (buffer->FrontLeftAlpha) {
-         free( buffer->FrontLeftAlpha );
+         FREE( buffer->FrontLeftAlpha );
       }
       if (buffer->BackLeftAlpha) {
-         free( buffer->BackLeftAlpha );
+         FREE( buffer->BackLeftAlpha );
       }
       if (buffer->FrontRightAlpha) {
-         free( buffer->FrontRightAlpha );
+         FREE( buffer->FrontRightAlpha );
       }
       if (buffer->BackRightAlpha) {
-         free( buffer->BackRightAlpha );
+         FREE( buffer->BackRightAlpha );
       }
-      free(buffer);
+      FREE(buffer);
    }
 }
 
@@ -1751,7 +1807,7 @@ GLenum gl_GetError( GLcontext *ctx )
 {
    GLenum e = ctx->ErrorValue;
 
-   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL( ctx, "glGetError", 0);
+   ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL( ctx, "glGetError", (GLenum) 0);
 
    if (MESA_VERBOSE & VERBOSE_API)
       fprintf(stderr, "glGetError <-- %s\n", gl_lookup_enum_by_nr(e));
@@ -2073,8 +2129,13 @@ void gl_update_state( GLcontext *ctx )
       ctx->Texture.Unit[1].LastEnvMode = ctx->Texture.Unit[1].EnvMode;
    }
 
-   if ((ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) == 0)
+   if ((ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) == 0) {
+
+      if (MESA_VERBOSE&VERBOSE_STATE)
+        fprintf(stderr, "update_state: goto finished\n");
+
       goto finished;
+   }
 
    if (ctx->NewState & NEW_TEXTURE_MATRIX) {
       ctx->Enabled &= ~(ENABLE_TEXMAT0|ENABLE_TEXMAT1);
@@ -2171,31 +2232,30 @@ void gl_update_state( GLcontext *ctx )
            }
         }
 
-        /*
-         * Update Device Driver interface
+        /* The driver isn't managing the depth buffer.
          */
-        ctx->Driver.AllocDepthBuffer = gl_alloc_depth_buffer;
-        if (ctx->Depth.Mask) {
-           switch (ctx->Depth.Func) {
-           case GL_LESS:
-              ctx->Driver.DepthTestSpan = gl_depth_test_span_less;
-              ctx->Driver.DepthTestPixels = gl_depth_test_pixels_less;
-              break;
-           case GL_GREATER:
-              ctx->Driver.DepthTestSpan = gl_depth_test_span_greater;
-              ctx->Driver.DepthTestPixels = gl_depth_test_pixels_greater;
-              break;
-           default:
+        if (ctx->Driver.AllocDepthBuffer == gl_alloc_depth_buffer) 
+        {
+           if (ctx->Depth.Mask) {
+              switch (ctx->Depth.Func) {
+              case GL_LESS:
+                 ctx->Driver.DepthTestSpan = gl_depth_test_span_less;
+                 ctx->Driver.DepthTestPixels = gl_depth_test_pixels_less;
+                 break;
+              case GL_GREATER:
+                 ctx->Driver.DepthTestSpan = gl_depth_test_span_greater;
+                 ctx->Driver.DepthTestPixels = gl_depth_test_pixels_greater;
+                 break;
+              default:
+                 ctx->Driver.DepthTestSpan = gl_depth_test_span_generic;
+                 ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic;
+              }
+           }
+           else {
               ctx->Driver.DepthTestSpan = gl_depth_test_span_generic;
               ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic;
            }
         }
-        else {
-           ctx->Driver.DepthTestSpan = gl_depth_test_span_generic;
-           ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic;
-        }
-        ctx->Driver.ReadDepthSpanFloat = gl_read_depth_span_float;
-        ctx->Driver.ReadDepthSpanInt = gl_read_depth_span_int;
       }
 
       if (ctx->NewState & NEW_LIGHTING) {
@@ -2210,6 +2270,7 @@ void gl_update_state( GLcontext *ctx )
 
    if (ctx->NewState & (NEW_POLYGON | NEW_LIGHTING)) {
 
+      ctx->TriangleCaps &= ~DD_TRI_CULL_FRONT_BACK;
 
       if (ctx->NewState & NEW_POLYGON) {
         /* Setup CullBits bitmask */
@@ -2229,7 +2290,8 @@ void gl_update_state( GLcontext *ctx )
            default:
            case GL_FRONT_AND_BACK:
               ctx->backface_sign = 0;
-              ctx->Polygon.CullBits = 3;
+              ctx->Polygon.CullBits = 0;
+              ctx->TriangleCaps |= DD_TRI_CULL_FRONT_BACK;
               break;
            }
         }