Commit 4b654d41 authored by Brian's avatar Brian

For _mesa_share_state(), update the context's references to the new share...

For _mesa_share_state(), update the context's references to the new share group's objects (Shane Blackett)
parent dbef6158
......@@ -601,8 +601,8 @@ WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,
WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,
HGLRC hglrc2)
{
(void) hglrc1; (void) hglrc2;
return(TRUE);
WMesaShareLists(hglrc1, hglrc2);
return(TRUE);
}
......
......@@ -1401,6 +1401,11 @@ void WMesaSwapBuffers( HDC hdc )
}
}
void WMesaShareLists(WMesaContext ctx_to_share, WMesaContext ctx)
{
_mesa_share_state(&ctx->gl_ctx, &ctx_to_share->gl_ctx);
}
/* This is hopefully a temporary hack to define some needed dispatch
* table entries. Hopefully, I'll find a better solution. The
* dispatch table generation scripts ought to be making these dummy
......
......@@ -409,6 +409,101 @@ _mesa_init_buffer_objects( GLcontext *ctx )
ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj;
}
/**
* Bind the specified target to buffer for the specified context.
*/
static void
bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
{
struct gl_buffer_object *oldBufObj;
struct gl_buffer_object *newBufObj = NULL;
struct gl_buffer_object **bindTarget = NULL;
switch (target) {
case GL_ARRAY_BUFFER_ARB:
bindTarget = &ctx->Array.ArrayBufferObj;
break;
case GL_ELEMENT_ARRAY_BUFFER_ARB:
bindTarget = &ctx->Array.ElementArrayBufferObj;
break;
case GL_PIXEL_PACK_BUFFER_EXT:
bindTarget = &ctx->Pack.BufferObj;
break;
case GL_PIXEL_UNPACK_BUFFER_EXT:
bindTarget = &ctx->Unpack.BufferObj;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)");
return;
}
/* Get pointer to old buffer object (to be unbound) */
oldBufObj = get_buffer(ctx, target);
if (oldBufObj && oldBufObj->Name == buffer)
return; /* rebinding the same buffer object- no change */
/*
* Get pointer to new buffer object (newBufObj)
*/
if (buffer == 0) {
/* The spec says there's not a buffer object named 0, but we use
* one internally because it simplifies things.
*/
newBufObj = ctx->Array.NullBufferObj;
}
else {
/* non-default buffer object */
newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
if (!newBufObj) {
/* if this is a new buffer object id, allocate a buffer object now */
ASSERT(ctx->Driver.NewBufferObject);
newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
if (!newBufObj) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
return;
}
_mesa_save_buffer_object(ctx, newBufObj);
}
}
/* Make new binding */
*bindTarget = newBufObj;
newBufObj->RefCount++;
/* Pass BindBuffer call to device driver */
if (ctx->Driver.BindBuffer && newBufObj)
ctx->Driver.BindBuffer( ctx, target, newBufObj );
/* decr ref count on old buffer obj, delete if needed */
if (oldBufObj) {
oldBufObj->RefCount--;
assert(oldBufObj->RefCount >= 0);
if (oldBufObj->RefCount == 0) {
assert(oldBufObj->Name != 0);
ASSERT(ctx->Driver.DeleteBuffer);
ctx->Driver.DeleteBuffer( ctx, oldBufObj );
}
}
}
/**
* Update the default buffer objects in the given context to reference those
* specified in the shared state and release those referencing the old
* shared state.
*/
void
_mesa_update_default_objects_buffer_objects(GLcontext *ctx)
{
/* Bind the NullBufferObj to remove references to those
* in the shared context hash table.
*/
bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0);
bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0);
bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0);
}
/**
* When we're about to read pixel data out of a PBO (via glDrawPixels,
......@@ -493,76 +588,9 @@ void GLAPIENTRY
_mesa_BindBufferARB(GLenum target, GLuint buffer)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *oldBufObj;
struct gl_buffer_object *newBufObj = NULL;
struct gl_buffer_object **bindTarget = NULL;
ASSERT_OUTSIDE_BEGIN_END(ctx);
switch (target) {
case GL_ARRAY_BUFFER_ARB:
bindTarget = &ctx->Array.ArrayBufferObj;
break;
case GL_ELEMENT_ARRAY_BUFFER_ARB:
bindTarget = &ctx->Array.ElementArrayBufferObj;
break;
case GL_PIXEL_PACK_BUFFER_EXT:
bindTarget = &ctx->Pack.BufferObj;
break;
case GL_PIXEL_UNPACK_BUFFER_EXT:
bindTarget = &ctx->Unpack.BufferObj;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)");
return;
}
/* Get pointer to old buffer object (to be unbound) */
oldBufObj = get_buffer(ctx, target);
if (oldBufObj && oldBufObj->Name == buffer)
return; /* rebinding the same buffer object- no change */
/*
* Get pointer to new buffer object (newBufObj)
*/
if (buffer == 0) {
/* The spec says there's not a buffer object named 0, but we use
* one internally because it simplifies things.
*/
newBufObj = ctx->Array.NullBufferObj;
}
else {
/* non-default buffer object */
newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
if (!newBufObj) {
/* if this is a new buffer object id, allocate a buffer object now */
ASSERT(ctx->Driver.NewBufferObject);
newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target);
if (!newBufObj) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
return;
}
_mesa_save_buffer_object(ctx, newBufObj);
}
}
/* Make new binding */
*bindTarget = newBufObj;
newBufObj->RefCount++;
/* Pass BindBuffer call to device driver */
if (ctx->Driver.BindBuffer && newBufObj)
ctx->Driver.BindBuffer( ctx, target, newBufObj );
/* decr ref count on old buffer obj, delete if needed */
if (oldBufObj) {
oldBufObj->RefCount--;
assert(oldBufObj->RefCount >= 0);
if (oldBufObj->RefCount == 0) {
assert(oldBufObj->Name != 0);
ASSERT(ctx->Driver.DeleteBuffer);
ctx->Driver.DeleteBuffer( ctx, oldBufObj );
}
}
bind_buffer_object(ctx, target, buffer);
}
......@@ -658,9 +686,9 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
_mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
}
/* The ID is immediately freed for re-use */
_mesa_remove_buffer_object(ctx, bufObj);
_mesa_unbind_buffer_object(ctx, bufObj);
/* The ID is immediately freed for re-use */
_mesa_remove_buffer_object(ctx, bufObj);
_mesa_unbind_buffer_object(ctx, bufObj);
}
}
......
......@@ -38,6 +38,9 @@
extern void
_mesa_init_buffer_objects( GLcontext *ctx );
extern void
_mesa_update_default_objects_buffer_objects(GLcontext *ctx);
extern struct gl_buffer_object *
_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target );
......
......@@ -998,6 +998,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
......@@ -1605,12 +1627,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 {
......
......@@ -3202,3 +3202,27 @@ _mesa_free_texture_data(GLcontext *ctx)
_mesa_TexEnvProgramCacheDestroy( ctx );
}
/**
* Update the default texture objects in the given context to reference those
* specified in the shared state and release those referencing the old
* shared state.
*/
void
_mesa_update_default_objects_texture(GLcontext *ctx)
{
GLuint i;
for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
_mesa_reference_texobj(&texUnit->Current1D, ctx->Shared->Default1D);
_mesa_reference_texobj(&texUnit->Current2D, ctx->Shared->Default2D);
_mesa_reference_texobj(&texUnit->Current3D, ctx->Shared->Default3D);
_mesa_reference_texobj(&texUnit->CurrentCubeMap, ctx->Shared->DefaultCubeMap);
_mesa_reference_texobj(&texUnit->CurrentRect, ctx->Shared->DefaultRect);
_mesa_reference_texobj(&texUnit->Current1DArray, ctx->Shared->Default1DArray);
_mesa_reference_texobj(&texUnit->Current2DArray, ctx->Shared->Default2DArray);
}
}
......@@ -148,6 +148,9 @@ _mesa_init_texture( GLcontext *ctx );
extern void
_mesa_free_texture_data( GLcontext *ctx );
extern void
_mesa_update_default_objects_texture(GLcontext *ctx);
/*@}*/
#endif
......@@ -118,6 +118,49 @@ _mesa_free_program_data(GLcontext *ctx)
}
/**
* Update the default program objects in the given context to reference those
* specified in the shared state and release those referencing the old
* shared state.
*/
void
_mesa_update_default_objects_program(GLcontext *ctx)
{
#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
if (ctx->VertexProgram.Current) {
ctx->VertexProgram.Current->Base.RefCount--;
if (ctx->VertexProgram.Current->Base.RefCount <= 0)
ctx->Driver.DeleteProgram(ctx, &(ctx->VertexProgram.Current->Base));
}
ctx->VertexProgram.Current = (struct gl_vertex_program *) ctx->Shared->DefaultVertexProgram;
assert(ctx->VertexProgram.Current);
ctx->VertexProgram.Current->Base.RefCount++;
#endif
#if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program
if (ctx->FragmentProgram.Current) {
ctx->FragmentProgram.Current->Base.RefCount--;
if (ctx->FragmentProgram.Current->Base.RefCount <= 0)
ctx->Driver.DeleteProgram(ctx, &(ctx->FragmentProgram.Current->Base));
}
ctx->FragmentProgram.Current = (struct gl_fragment_program *) ctx->Shared->DefaultFragmentProgram;
assert(ctx->FragmentProgram.Current);
ctx->FragmentProgram.Current->Base.RefCount++;
#endif
/* XXX probably move this stuff */
#if FEATURE_ATI_fragment_shader
if (ctx->ATIFragmentShader.Current) {
ctx->ATIFragmentShader.Current->RefCount--;
if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
_mesa_free(ctx->ATIFragmentShader.Current);
}
}
ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
assert(ctx->ATIFragmentShader.Current);
ctx->ATIFragmentShader.Current->RefCount++;
#endif
}
/**
......
......@@ -56,6 +56,9 @@ _mesa_init_program(GLcontext *ctx);
extern void
_mesa_free_program_data(GLcontext *ctx);
extern void
_mesa_update_default_objects_program(GLcontext *ctx);
extern void
_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment