aboutsummaryrefslogtreecommitdiffstats
path: root/src/mesa/main/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main/context.c')
-rw-r--r--src/mesa/main/context.c167
1 files changed, 107 insertions, 60 deletions
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 00e4c8328e5..08db12b1b67 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -6,9 +6,9 @@
/*
* Mesa 3-D graphics library
- * Version: 6.5
+ * Version: 7.1
*
- * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2007 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"),
@@ -475,19 +475,12 @@ alloc_shared_state( GLcontext *ctx )
if (!ss->Default2DArray)
goto cleanup;
- /* Effectively bind the default textures to all texture units */
- ss->Default1D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default2D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default3D->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->DefaultCubeMap->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->DefaultRect->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default1DArray->RefCount += MAX_TEXTURE_IMAGE_UNITS;
- ss->Default2DArray->RefCount += MAX_TEXTURE_IMAGE_UNITS;
+ /* sanity check */
+ assert(ss->Default1D->RefCount == 1);
_glthread_INIT_MUTEX(ss->TexMutex);
ss->TextureStateStamp = 0;
-
#if FEATURE_EXT_framebuffer_object
ss->FrameBuffers = _mesa_NewHashTable();
if (!ss->FrameBuffers)
@@ -497,10 +490,9 @@ alloc_shared_state( GLcontext *ctx )
goto cleanup;
#endif
-
return GL_TRUE;
- cleanup:
+cleanup:
/* Ran out of memory at some point. Free everything and return NULL */
if (ss->DisplayList)
_mesa_DeleteHashTable(ss->DisplayList);
@@ -552,6 +544,10 @@ alloc_shared_state( GLcontext *ctx )
(*ctx->Driver.DeleteTexture)(ctx, ss->DefaultCubeMap);
if (ss->DefaultRect)
(*ctx->Driver.DeleteTexture)(ctx, ss->DefaultRect);
+ if (ss->Default1DArray)
+ (*ctx->Driver.DeleteTexture)(ctx, ss->Default1DArray);
+ if (ss->Default2DArray)
+ (*ctx->Driver.DeleteTexture)(ctx, ss->Default2DArray);
if (ss)
_mesa_free(ss);
return GL_FALSE;
@@ -644,6 +640,33 @@ delete_shader_cb(GLuint id, void *data, void *userData)
}
}
+/**
+ * Callback for deleting a framebuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+delete_framebuffer_cb(GLuint id, void *data, void *userData)
+{
+ struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
+ /* The fact that the framebuffer is in the hashtable means its refcount
+ * is one, but we're removing from the hashtable now. So clear refcount.
+ */
+ /*assert(fb->RefCount == 1);*/
+ fb->RefCount = 0;
+ fb->Delete(fb);
+}
+
+/**
+ * Callback for deleting a renderbuffer object. Called by _mesa_HashDeleteAll()
+ */
+static void
+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);
+}
+
+
/**
* Deallocate a shared state object and all children structures.
@@ -666,20 +689,6 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
_mesa_HashDeleteAll(ss->DisplayList, delete_displaylist_cb, ctx);
_mesa_DeleteHashTable(ss->DisplayList);
- /*
- * Free texture objects
- */
- ASSERT(ctx->Driver.DeleteTexture);
- /* the default textures */
- ctx->Driver.DeleteTexture(ctx, ss->Default1D);
- ctx->Driver.DeleteTexture(ctx, ss->Default2D);
- ctx->Driver.DeleteTexture(ctx, ss->Default3D);
- ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
- ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
- /* all other textures */
- _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
- _mesa_DeleteHashTable(ss->TexObjects);
-
#if defined(FEATURE_NV_vertex_program) || defined(FEATURE_NV_fragment_program)
_mesa_HashDeleteAll(ss->Programs, delete_program_cb, ctx);
_mesa_DeleteHashTable(ss->Programs);
@@ -711,10 +720,29 @@ free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
#endif
#if FEATURE_EXT_framebuffer_object
+ _mesa_HashDeleteAll(ss->FrameBuffers, delete_framebuffer_cb, ctx);
_mesa_DeleteHashTable(ss->FrameBuffers);
+ _mesa_HashDeleteAll(ss->RenderBuffers, delete_renderbuffer_cb, ctx);
_mesa_DeleteHashTable(ss->RenderBuffers);
#endif
+ /*
+ * Free texture objects (after FBOs since some textures might have
+ * been bound to FBOs).
+ */
+ ASSERT(ctx->Driver.DeleteTexture);
+ /* the default textures */
+ ctx->Driver.DeleteTexture(ctx, ss->Default1D);
+ ctx->Driver.DeleteTexture(ctx, ss->Default2D);
+ ctx->Driver.DeleteTexture(ctx, ss->Default3D);
+ ctx->Driver.DeleteTexture(ctx, ss->DefaultCubeMap);
+ ctx->Driver.DeleteTexture(ctx, ss->DefaultRect);
+ ctx->Driver.DeleteTexture(ctx, ss->Default1DArray);
+ ctx->Driver.DeleteTexture(ctx, ss->Default2DArray);
+ /* all other textures */
+ _mesa_HashDeleteAll(ss->TexObjects, delete_texture_cb, ctx);
+ _mesa_DeleteHashTable(ss->TexObjects);
+
_glthread_DESTROY_MUTEX(ss->Mutex);
_mesa_free(ss);
@@ -971,6 +999,28 @@ init_attrib_groups(GLcontext *ctx)
/**
+ * Update default objects in a GL context with respect to shared state.
+ *
+ * \param ctx GL context.
+ *
+ * Removes references to old default objects, (texture objects, program
+ * objects, etc.) and changes to reference those from the current shared
+ * state.
+ */
+static GLboolean
+update_default_objects(GLcontext *ctx)
+{
+ assert(ctx);
+
+ _mesa_update_default_objects_program(ctx);
+ _mesa_update_default_objects_texture(ctx);
+ _mesa_update_default_objects_buffer_objects(ctx);
+
+ return GL_TRUE;
+}
+
+
+/**
* This is the default function we plug into all dispatch table slots
* This helps prevents a segfault when someone calls a GL function without
* first checking if the extension's supported.
@@ -1168,18 +1218,20 @@ _mesa_create_context(const GLvisual *visual,
void
_mesa_free_context_data( GLcontext *ctx )
{
- /* if we're destroying the current context, unbind it first */
- if (ctx == _mesa_get_current_context()) {
- _mesa_make_current(NULL, NULL, NULL);
- }
- else {
- /* unreference WinSysDraw/Read buffers */
- _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer);
- _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer);
- _mesa_unreference_framebuffer(&ctx->DrawBuffer);
- _mesa_unreference_framebuffer(&ctx->ReadBuffer);
+ if (!_mesa_get_current_context()){
+ /* No current context, but we may need one in order to delete
+ * texture objs, etc. So temporarily bind the context now.
+ */
+ _mesa_make_current(ctx, NULL, NULL);
}
+ /* unreference WinSysDraw/Read buffers */
+ _mesa_unreference_framebuffer(&ctx->WinSysDrawBuffer);
+ _mesa_unreference_framebuffer(&ctx->WinSysReadBuffer);
+ _mesa_unreference_framebuffer(&ctx->DrawBuffer);
+ _mesa_unreference_framebuffer(&ctx->ReadBuffer);
+
+ _mesa_free_attrib_data(ctx);
_mesa_free_lighting_data( ctx );
_mesa_free_eval_data( ctx );
_mesa_free_texture_data( ctx );
@@ -1211,6 +1263,11 @@ _mesa_free_context_data( GLcontext *ctx )
if (ctx->Extensions.String)
_mesa_free((void *) ctx->Extensions.String);
+
+ /* unbind the context if it's currently bound */
+ if (ctx == _mesa_get_current_context()) {
+ _mesa_make_current(NULL, NULL, NULL);
+ }
}
@@ -1442,8 +1499,6 @@ void
_mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
GLframebuffer *readBuffer )
{
- GET_CURRENT_CONTEXT(oldCtx);
-
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(newCtx, "_mesa_make_current()\n");
@@ -1468,13 +1523,6 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
_glapi_set_context((void *) newCtx);
ASSERT(_mesa_get_current_context() == newCtx);
- if (oldCtx) {
- _mesa_unreference_framebuffer(&oldCtx->WinSysDrawBuffer);
- _mesa_unreference_framebuffer(&oldCtx->WinSysReadBuffer);
- _mesa_unreference_framebuffer(&oldCtx->DrawBuffer);
- _mesa_unreference_framebuffer(&oldCtx->ReadBuffer);
- }
-
if (!newCtx) {
_glapi_set_dispatch(NULL); /* none current */
}
@@ -1495,21 +1543,14 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
*/
if (!newCtx->DrawBuffer || newCtx->DrawBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->DrawBuffer, drawBuffer);
- /* fix up the fb fields - these will end up wrong otherwise
- if the DRIdrawable changes, and everything relies on them.
- This is a bit messy (same as needed in _mesa_BindFramebufferEXT) */
- int i;
- GLenum buffers[MAX_DRAW_BUFFERS];
- for(i = 0; i < newCtx->Const.MaxDrawBuffers; i++) {
- buffers[i] = newCtx->Color.DrawBuffer[i];
- }
- _mesa_drawbuffers(newCtx, newCtx->Const.MaxDrawBuffers, buffers, NULL);
}
if (!newCtx->ReadBuffer || newCtx->ReadBuffer->Name == 0) {
_mesa_reference_framebuffer(&newCtx->ReadBuffer, readBuffer);
- _mesa_readbuffer_update_fields(newCtx, newCtx->Pixel.ReadBuffer);
}
+ /* XXX only set this flag if we're really changing the draw/read
+ * framebuffer bindings.
+ */
newCtx->NewState |= _NEW_BUFFERS;
#if 1
@@ -1577,12 +1618,18 @@ GLboolean
_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
{
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
- ctx->Shared->RefCount--;
- if (ctx->Shared->RefCount == 0) {
- free_shared_state(ctx, ctx->Shared);
- }
+ struct gl_shared_state *oldSharedState = ctx->Shared;
+
ctx->Shared = ctxToShare->Shared;
ctx->Shared->RefCount++;
+
+ update_default_objects(ctx);
+
+ oldSharedState->RefCount--;
+ if (oldSharedState->RefCount == 0) {
+ free_shared_state(ctx, oldSharedState);
+ }
+
return GL_TRUE;
}
else {