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,
|
WINGDIAPI BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,
|
||||||
HGLRC hglrc2)
|
HGLRC hglrc2)
|
||||||
{
|
{
|
||||||
(void) hglrc1; (void) hglrc2;
|
WMesaShareLists(hglrc1, hglrc2);
|
||||||
return(TRUE);
|
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
|
/* This is hopefully a temporary hack to define some needed dispatch
|
||||||
* table entries. Hopefully, I'll find a better solution. The
|
* table entries. Hopefully, I'll find a better solution. The
|
||||||
* dispatch table generation scripts ought to be making these dummy
|
* 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;
|
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,
|
* 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)
|
_mesa_BindBufferARB(GLenum target, GLuint buffer)
|
||||||
{
|
{
|
||||||
GET_CURRENT_CONTEXT(ctx);
|
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);
|
ASSERT_OUTSIDE_BEGIN_END(ctx);
|
||||||
|
|
||||||
switch (target) {
|
bind_buffer_object(ctx, target, buffer);
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -38,6 +38,9 @@
|
|||||||
extern void
|
extern void
|
||||||
_mesa_init_buffer_objects( GLcontext *ctx );
|
_mesa_init_buffer_objects( GLcontext *ctx );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_mesa_update_default_objects_buffer_objects(GLcontext *ctx);
|
||||||
|
|
||||||
extern struct gl_buffer_object *
|
extern struct gl_buffer_object *
|
||||||
_mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target );
|
_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 is the default function we plug into all dispatch table slots
|
||||||
* This helps prevents a segfault when someone calls a GL function without
|
* This helps prevents a segfault when someone calls a GL function without
|
||||||
@@ -1605,12 +1627,18 @@ GLboolean
|
|||||||
_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
|
_mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
|
||||||
{
|
{
|
||||||
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
|
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
|
||||||
ctx->Shared->RefCount--;
|
struct gl_shared_state *oldSharedState = ctx->Shared;
|
||||||
if (ctx->Shared->RefCount == 0) {
|
|
||||||
free_shared_state(ctx, ctx->Shared);
|
|
||||||
}
|
|
||||||
ctx->Shared = ctxToShare->Shared;
|
ctx->Shared = ctxToShare->Shared;
|
||||||
ctx->Shared->RefCount++;
|
ctx->Shared->RefCount++;
|
||||||
|
|
||||||
|
update_default_objects(ctx);
|
||||||
|
|
||||||
|
oldSharedState->RefCount--;
|
||||||
|
if (oldSharedState->RefCount == 0) {
|
||||||
|
free_shared_state(ctx, oldSharedState);
|
||||||
|
}
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -3202,3 +3202,27 @@ _mesa_free_texture_data(GLcontext *ctx)
|
|||||||
|
|
||||||
_mesa_TexEnvProgramCacheDestroy( 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
|
extern void
|
||||||
_mesa_free_texture_data( GLcontext *ctx );
|
_mesa_free_texture_data( GLcontext *ctx );
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_mesa_update_default_objects_texture(GLcontext *ctx);
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#endif
|
#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
|
extern void
|
||||||
_mesa_free_program_data(GLcontext *ctx);
|
_mesa_free_program_data(GLcontext *ctx);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_mesa_update_default_objects_program(GLcontext *ctx);
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
|
_mesa_set_program_error(GLcontext *ctx, GLint pos, const char *string);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user