For _mesa_share_state(), update the context's references to the new share group's objects (Shane Blackett)
This commit is contained in:
@@ -601,7 +601,7 @@ WINGDIAPI HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,
|
||||
WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,
|
||||
HGLRC hglrc2)
|
||||
{
|
||||
(void) hglrc1; (void) hglrc2;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user