mesa: refactor: move glReadPixels code into new readpix.c file
[mesa.git] / src / mesa / main / context.c
index 2ae0e1221d6fbcbe10f2fa241126ecc4fe0846e4..aa9d11299961a1c31f73d40b2365974e1c92867d 100644 (file)
 #include "version.h"
 #include "vtxfmt.h"
 #include "glapi/glthread.h"
-#include "glapi/glapioffsets.h"
 #if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
 #include "shader/program.h"
 #endif
@@ -150,8 +149,6 @@ int MESA_DEBUG_FLAGS = 0;
 /* ubyte -> float conversion */
 GLfloat _mesa_ubyte_to_float_color_tab[256];
 
-static void
-free_shared_state( GLcontext *ctx, struct gl_shared_state *ss );
 
 
 /**
@@ -421,12 +418,14 @@ alloc_shared_state( GLcontext *ctx )
 #endif
 
 #if FEATURE_ARB_vertex_program
-   ss->DefaultVertexProgram = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
+   ss->DefaultVertexProgram = (struct gl_vertex_program *)
+      ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0);
    if (!ss->DefaultVertexProgram)
       goto cleanup;
 #endif
 #if FEATURE_ARB_fragment_program
-   ss->DefaultFragmentProgram = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
+   ss->DefaultFragmentProgram = (struct gl_fragment_program *)
+      ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!ss->DefaultFragmentProgram)
       goto cleanup;
 #endif
@@ -503,12 +502,10 @@ cleanup:
       _mesa_DeleteHashTable(ss->Programs);
 #endif
 #if FEATURE_ARB_vertex_program
-   if (ss->DefaultVertexProgram)
-      ctx->Driver.DeleteProgram(ctx, ss->DefaultVertexProgram);
+   _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
 #endif
 #if FEATURE_ARB_fragment_program
-   if (ss->DefaultFragmentProgram)
-      ctx->Driver.DeleteProgram(ctx, ss->DefaultFragmentProgram);
+   _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
 #endif
 #if FEATURE_ATI_fragment_shader
    if (ss->DefaultFragmentShader)
@@ -548,8 +545,9 @@ cleanup:
       (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray);
    if (ss->Default2DArray)
       (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray);
-   if (ss)
-      _mesa_free(ss);
+
+   _mesa_free(ss);
+
    return GL_FALSE;
 }
 
@@ -584,6 +582,8 @@ delete_program_cb(GLuint id, void *data, void *userData)
 {
    struct gl_program *prog = (struct gl_program *) data;
    GLcontext *ctx = (GLcontext *) userData;
+   ASSERT(prog->RefCount == 1); /* should only be referenced by hash table */
+   prog->RefCount = 0;  /* now going away */
    ctx->Driver.DeleteProgram(ctx, prog);
 }
 
@@ -621,6 +621,21 @@ delete_arrayobj_cb(GLuint id, void *data, void *userData)
    _mesa_delete_array_object(ctx, arrayObj);
 }
 
+/**
+ * Callback for freeing shader program data. Call it before delete_shader_cb
+ * to avoid memory access error.
+ */
+static void
+free_shader_program_data_cb(GLuint id, void *data, void *userData)
+{
+   GLcontext *ctx = (GLcontext *) userData;
+   struct gl_shader_program *shProg = (struct gl_shader_program *) data;
+
+   if (shProg->Type == GL_SHADER_PROGRAM_MESA) {
+       _mesa_free_shader_program_data(ctx, shProg);
+   }
+}
+
 /**
  * Callback for deleting shader and shader programs objects.
  * Called by _mesa_HashDeleteAll().
@@ -652,7 +667,12 @@ delete_framebuffer_cb(GLuint id, void *data, void *userData)
     */
    /*assert(fb->RefCount == 1);*/
    fb->RefCount = 0;
-   fb->Delete(fb);
+
+   /* NOTE: Delete should always be defined but there are two reports
+    * of it being NULL (bugs 13507, 14293).  Work-around for now.
+    */
+   if (fb->Delete)
+      fb->Delete(fb);
 }
 
 /**
@@ -663,7 +683,8 @@ delete_renderbuffer_cb(GLuint id, void *data, void *userData)
 {
    struct gl_renderbuffer *rb = (struct gl_renderbuffer *) data;
    rb->RefCount = 0;  /* see comment for FBOs above */
-   rb->Delete(rb);
+   if (rb->Delete)
+      rb->Delete(rb);
 }
 
 
@@ -689,15 +710,21 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    _mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx);
    _mesa_DeleteHashTable(ss->DisplayList);
 
+#if FEATURE_ARB_shader_objects
+   _mesa_HashWalk(ss->ShaderObjects, free_shader_program_data_cb, ctx);
+   _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
+   _mesa_DeleteHashTable(ss->ShaderObjects);
+#endif
+
 #if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program)
    _mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
    _mesa_DeleteHashTable(ss->Programs);
 #endif
 #if FEATURE_ARB_vertex_program
-   _mesa_delete_program(ctx, ss->DefaultVertexProgram);
+   _mesa_reference_vertprog(ctx, &ss->DefaultVertexProgram, NULL);
 #endif
 #if FEATURE_ARB_fragment_program
-   _mesa_delete_program(ctx, ss->DefaultFragmentProgram);
+   _mesa_reference_fragprog(ctx, &ss->DefaultFragmentProgram, NULL);
 #endif
 
 #if FEATURE_ATI_fragment_shader
@@ -714,11 +741,6 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
    _mesa_HashDeleteAll(ss->ArrayObjects, delete_arrayobj_cb, ctx);
    _mesa_DeleteHashTable(ss->ArrayObjects);
 
-#if FEATURE_ARB_shader_objects
-   _mesa_HashDeleteAll(ss->ShaderObjects, delete_shader_cb, ctx);
-   _mesa_DeleteHashTable(ss->ShaderObjects);
-#endif
-
 #if FEATURE_EXT_framebuffer_object
    _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx);
    _mesa_DeleteHashTable(ss->FrameBuffers);
@@ -763,7 +785,7 @@ _mesa_init_current(GLcontext *ctx)
    }
 
    /* redo special cases: */
-   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 1.0 );
+   ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_WEIGHT], 1.0, 0.0, 0.0, 0.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], 0.0, 0.0, 1.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR0], 1.0, 1.0, 1.0, 1.0 );
    ASSIGN_4V( ctx->Current.Attrib[VERT_ATTRIB_COLOR1], 0.0, 0.0, 0.0, 1.0 );
@@ -962,6 +984,7 @@ init_attrib_groups(GLcontext *ctx)
    _mesa_init_debug( ctx );
    _mesa_init_display_list( ctx );
    _mesa_init_eval( ctx );
+   _mesa_init_fbobjects( ctx );
    _mesa_init_feedback( ctx );
    _mesa_init_fog( ctx );
    _mesa_init_histogram( ctx );
@@ -1230,6 +1253,14 @@ _mesa_free_context_data( GLcontext *ctx )
    _mesa_unreference_framebuffer(&ctx->DrawBuffer);
    _mesa_unreference_framebuffer(&ctx->ReadBuffer);
 
+   _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL);
+   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL);
+   _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, NULL);
+
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL);
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL);
+   _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, NULL);
+
    _mesa_free_attrib_data(ctx);
    _mesa_free_lighting_data( ctx );
    _mesa_free_eval_data( ctx );