mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 13:28:06 +02:00
Rewrite quite a bit of the code for glPush/PopAttrib() for texture state.
Remove the Saved1D/2D/etc fields from gl_texture_attrib in mtypes.h Use a new texture_state struct in attrib.c that has the extra information for restoring texture object state and saving references to the texture objects (so they can't accidentally get deleted while referenced by the attribute stack). All the texobj refcounting is mutex-protected now.
This commit is contained in:
parent
21594921b1
commit
00ccff03a5
2 changed files with 137 additions and 132 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 6.5.3
|
||||
* Version: 7.0.2
|
||||
*
|
||||
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
|
||||
*
|
||||
|
|
@ -51,6 +51,32 @@
|
|||
#include "math/m_xform.h"
|
||||
|
||||
|
||||
/**
|
||||
* Special struct for saving/restoring texture state (GL_TEXTURE_BIT)
|
||||
*/
|
||||
struct texture_state
|
||||
{
|
||||
struct gl_texture_attrib Texture; /**< The usual context state */
|
||||
|
||||
/** to save per texture object state (wrap modes, filters, etc): */
|
||||
struct gl_texture_object Saved1D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object Saved2D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object Saved3D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object SavedCube[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object SavedRect[MAX_TEXTURE_UNITS];
|
||||
|
||||
/**
|
||||
* To save references to texture objects (so they don't get accidentally
|
||||
* deleted while saved in the attribute stack).
|
||||
*/
|
||||
struct gl_texture_object *SavedRef1D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object *SavedRef2D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object *SavedRef3D[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object *SavedRefCube[MAX_TEXTURE_UNITS];
|
||||
struct gl_texture_object *SavedRefRect[MAX_TEXTURE_UNITS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Allocate a new attribute state node. These nodes have a
|
||||
* "kind" value and a pointer to a struct of state data.
|
||||
|
|
@ -335,47 +361,57 @@ _mesa_PushAttrib(GLbitfield mask)
|
|||
}
|
||||
|
||||
if (mask & GL_TEXTURE_BIT) {
|
||||
struct gl_texture_attrib *attr;
|
||||
struct texture_state *texstate = CALLOC_STRUCT( texture_state );
|
||||
GLuint u;
|
||||
|
||||
_mesa_lock_context_textures(ctx);
|
||||
/* Bump the texture object reference counts so that they don't
|
||||
* inadvertantly get deleted.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA PUSH TEX ATTRIB, INCR REF COUNT BY %d\n",
|
||||
_glthread_GetID(),
|
||||
ctx->Const.MaxTextureUnits);
|
||||
#endif
|
||||
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
ctx->Texture.Unit[u].Current1D->RefCount++;
|
||||
ctx->Texture.Unit[u].Current2D->RefCount++;
|
||||
ctx->Texture.Unit[u].Current3D->RefCount++;
|
||||
ctx->Texture.Unit[u].CurrentCubeMap->RefCount++;
|
||||
ctx->Texture.Unit[u].CurrentRect->RefCount++;
|
||||
if (!texstate) {
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glPushAttrib(GL_TEXTURE_BIT)");
|
||||
goto end;
|
||||
}
|
||||
|
||||
attr = MALLOC_STRUCT( gl_texture_attrib );
|
||||
MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) );
|
||||
/* copy state of the currently bound texture objects */
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA BEGIN PUSH TEX ATTRIB\n",
|
||||
_glthread_GetID());
|
||||
#endif
|
||||
|
||||
_mesa_lock_context_textures(ctx);
|
||||
|
||||
/* copy/save the bulk of texture state here */
|
||||
_mesa_memcpy(&texstate->Texture, &ctx->Texture, sizeof(ctx->Texture));
|
||||
|
||||
/* Save references to the currently bound texture objects so they don't
|
||||
* accidentally get deleted while referenced in the attribute stack.
|
||||
*/
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
_mesa_copy_texture_object(&attr->Unit[u].Saved1D,
|
||||
attr->Unit[u].Current1D);
|
||||
_mesa_copy_texture_object(&attr->Unit[u].Saved2D,
|
||||
attr->Unit[u].Current2D);
|
||||
_mesa_copy_texture_object(&attr->Unit[u].Saved3D,
|
||||
attr->Unit[u].Current3D);
|
||||
_mesa_copy_texture_object(&attr->Unit[u].SavedCubeMap,
|
||||
attr->Unit[u].CurrentCubeMap);
|
||||
_mesa_copy_texture_object(&attr->Unit[u].SavedRect,
|
||||
attr->Unit[u].CurrentRect);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef1D[u], ctx->Texture.Unit[u].Current1D);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef2D[u], ctx->Texture.Unit[u].Current2D);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef3D[u], ctx->Texture.Unit[u].Current3D);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefCube[u], ctx->Texture.Unit[u].CurrentCubeMap);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefRect[u], ctx->Texture.Unit[u].CurrentRect);
|
||||
}
|
||||
|
||||
/* copy state/contents of the currently bound texture objects */
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
_mesa_copy_texture_object(&texstate->Saved1D[u],
|
||||
ctx->Texture.Unit[u].Current1D);
|
||||
_mesa_copy_texture_object(&texstate->Saved2D[u],
|
||||
ctx->Texture.Unit[u].Current2D);
|
||||
_mesa_copy_texture_object(&texstate->Saved3D[u],
|
||||
ctx->Texture.Unit[u].Current3D);
|
||||
_mesa_copy_texture_object(&texstate->SavedCube[u],
|
||||
ctx->Texture.Unit[u].CurrentCubeMap);
|
||||
_mesa_copy_texture_object(&texstate->SavedRect[u],
|
||||
ctx->Texture.Unit[u].CurrentRect);
|
||||
}
|
||||
|
||||
_mesa_unlock_context_textures(ctx);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA END PUSH TEX ATTRIB\n",
|
||||
_glthread_GetID());
|
||||
#endif
|
||||
newnode = new_attrib_node( GL_TEXTURE_BIT );
|
||||
newnode->data = attr;
|
||||
newnode->data = texstate;
|
||||
newnode->next = head;
|
||||
head = newnode;
|
||||
}
|
||||
|
|
@ -411,6 +447,7 @@ _mesa_PushAttrib(GLbitfield mask)
|
|||
head = newnode;
|
||||
}
|
||||
|
||||
end:
|
||||
ctx->AttribStack[ctx->AttribStackDepth] = head;
|
||||
ctx->AttribStackDepth++;
|
||||
}
|
||||
|
|
@ -620,14 +657,24 @@ pop_enable_group(GLcontext *ctx, const struct gl_enable_attrib *enable)
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Pop/restore texture attribute/group state.
|
||||
*/
|
||||
static void
|
||||
pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
|
||||
pop_texture_group(GLcontext *ctx, struct texture_state *texstate)
|
||||
{
|
||||
GLuint u;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA BEGIN POP TEX ATTRIB\n",
|
||||
_glthread_GetID());
|
||||
#endif
|
||||
|
||||
_mesa_lock_context_textures(ctx);
|
||||
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
const struct gl_texture_unit *unit = &texAttrib->Unit[u];
|
||||
GLuint i;
|
||||
const struct gl_texture_unit *unit = &texstate->Texture.Unit[u];
|
||||
GLuint tgt;
|
||||
|
||||
_mesa_ActiveTextureARB(GL_TEXTURE0_ARB + u);
|
||||
_mesa_set_enable(ctx, GL_TEXTURE_1D,
|
||||
|
|
@ -720,41 +767,44 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
|
|||
1 << unit->Combine.ScaleShiftA);
|
||||
}
|
||||
|
||||
/* Restore texture object state */
|
||||
for (i = 0; i < NUM_TEXTURE_TARGETS; i++) {
|
||||
GLenum target = 0;
|
||||
/* Restore texture object state for each target */
|
||||
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
|
||||
const struct gl_texture_object *obj = NULL;
|
||||
GLfloat bordColor[4];
|
||||
GLenum target;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
target = GL_TEXTURE_1D;
|
||||
obj = &unit->Saved1D;
|
||||
switch (tgt) {
|
||||
case TEXTURE_1D_INDEX:
|
||||
obj = &texstate->Saved1D[u];
|
||||
ASSERT(obj->Target == GL_TEXTURE_1D);
|
||||
break;
|
||||
case 1:
|
||||
target = GL_TEXTURE_2D;
|
||||
obj = &unit->Saved2D;
|
||||
case TEXTURE_2D_INDEX:
|
||||
obj = &texstate->Saved2D[u];
|
||||
ASSERT(obj->Target == GL_TEXTURE_2D);
|
||||
break;
|
||||
case 2:
|
||||
target = GL_TEXTURE_3D;
|
||||
obj = &unit->Saved3D;
|
||||
case TEXTURE_3D_INDEX:
|
||||
obj = &texstate->Saved3D[u];
|
||||
ASSERT(obj->Target == GL_TEXTURE_3D);
|
||||
break;
|
||||
case 3:
|
||||
case TEXTURE_CUBE_INDEX:
|
||||
if (!ctx->Extensions.ARB_texture_cube_map)
|
||||
continue;
|
||||
target = GL_TEXTURE_CUBE_MAP_ARB;
|
||||
obj = &unit->SavedCubeMap;
|
||||
obj = &texstate->SavedCube[u];
|
||||
ASSERT(obj->Target == GL_TEXTURE_CUBE_MAP_ARB);
|
||||
break;
|
||||
case 4:
|
||||
case TEXTURE_RECT_INDEX:
|
||||
if (!ctx->Extensions.NV_texture_rectangle)
|
||||
continue;
|
||||
target = GL_TEXTURE_RECTANGLE_NV;
|
||||
obj = &unit->SavedRect;
|
||||
obj = &texstate->SavedRect[u];
|
||||
ASSERT(obj->Target == GL_TEXTURE_RECTANGLE_NV);
|
||||
break;
|
||||
default:
|
||||
; /* silence warnings */
|
||||
_mesa_problem(ctx, "bad texture index in pop_texture_group");
|
||||
continue;
|
||||
}
|
||||
|
||||
target = obj->Target;
|
||||
|
||||
_mesa_BindTexture(target, obj->Name);
|
||||
|
||||
bordColor[0] = CHAN_TO_FLOAT(obj->BorderColor[0]);
|
||||
|
|
@ -789,28 +839,24 @@ pop_texture_group(GLcontext *ctx, const struct gl_texture_attrib *texAttrib)
|
|||
_mesa_TexParameterf(target, GL_SHADOW_AMBIENT_SGIX,
|
||||
obj->ShadowAmbient);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_mesa_ActiveTextureARB(GL_TEXTURE0_ARB
|
||||
+ texAttrib->CurrentUnit);
|
||||
|
||||
/* "un-bump" the texture object reference counts. We did that so they
|
||||
* wouldn't inadvertantly get deleted while they were still referenced
|
||||
* inside the attribute state stack.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA POP TEX ATTRIB, DECR REF COUNT BY %d\n",
|
||||
_glthread_GetID(),
|
||||
ctx->Const.MaxTextureUnits);
|
||||
#endif
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
ctx->Texture.Unit[u].Current1D->RefCount--;
|
||||
ctx->Texture.Unit[u].Current2D->RefCount--;
|
||||
ctx->Texture.Unit[u].Current3D->RefCount--;
|
||||
ctx->Texture.Unit[u].CurrentCubeMap->RefCount--;
|
||||
ctx->Texture.Unit[u].CurrentRect->RefCount--;
|
||||
/* remove saved references to the texture objects */
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef1D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef2D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef3D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefCube[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefRect[u], NULL);
|
||||
}
|
||||
|
||||
_mesa_ActiveTextureARB(GL_TEXTURE0_ARB + texstate->Texture.CurrentUnit);
|
||||
|
||||
_mesa_unlock_context_textures(ctx);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("%lu: MESA END POP TEX ATTRIB\n",
|
||||
_glthread_GetID());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1189,9 +1235,9 @@ _mesa_PopAttrib(void)
|
|||
case GL_TEXTURE_BIT:
|
||||
/* Take care of texture object reference counters */
|
||||
{
|
||||
const struct gl_texture_attrib *texture;
|
||||
texture = (const struct gl_texture_attrib *) attr->data;
|
||||
pop_texture_group(ctx, texture);
|
||||
struct texture_state *texstate
|
||||
= (struct texture_state *) attr->data;
|
||||
pop_texture_group(ctx, texstate);
|
||||
ctx->NewState |= _NEW_TEXTURE;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1413,38 +1459,6 @@ _mesa_PopClientAttrib(void)
|
|||
}
|
||||
|
||||
|
||||
static struct gl_texture_object *
|
||||
get_texobj(GLcontext *ctx, GLenum target, GLuint name)
|
||||
{
|
||||
struct gl_texture_object *texObj;
|
||||
if (name) {
|
||||
texObj = _mesa_lookup_texture(ctx, name);
|
||||
}
|
||||
else {
|
||||
switch (target) {
|
||||
case GL_TEXTURE_1D:
|
||||
texObj = ctx->Shared->Default1D;
|
||||
break;
|
||||
case GL_TEXTURE_2D:
|
||||
texObj = ctx->Shared->Default2D;
|
||||
break;
|
||||
case GL_TEXTURE_3D:
|
||||
texObj = ctx->Shared->Default3D;
|
||||
break;
|
||||
case GL_TEXTURE_CUBE_MAP_ARB:
|
||||
texObj = ctx->Shared->DefaultCubeMap;
|
||||
break;
|
||||
case GL_TEXTURE_RECTANGLE_NV:
|
||||
texObj = ctx->Shared->DefaultRect;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return texObj;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_mesa_free_attrib_data(GLcontext *ctx)
|
||||
{
|
||||
|
|
@ -1459,23 +1473,20 @@ _mesa_free_attrib_data(GLcontext *ctx)
|
|||
attr = ctx->AttribStack[ctx->AttribStackDepth];
|
||||
|
||||
while (attr) {
|
||||
struct gl_texture_attrib *texAttrib
|
||||
= (struct gl_texture_attrib *) attr->data;
|
||||
GLuint u;
|
||||
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
struct gl_texture_unit *unit = &texAttrib->Unit[u];
|
||||
struct gl_texture_object *texObj;
|
||||
texObj = get_texobj(ctx, GL_TEXTURE_1D, unit->Saved1D.Name);
|
||||
MESA_REF_TEXOBJ(&texObj, NULL);
|
||||
texObj = get_texobj(ctx, GL_TEXTURE_2D, unit->Saved2D.Name);
|
||||
MESA_REF_TEXOBJ(&texObj, NULL);
|
||||
texObj = get_texobj(ctx, GL_TEXTURE_3D, unit->Saved3D.Name);
|
||||
MESA_REF_TEXOBJ(&texObj, NULL);
|
||||
texObj = get_texobj(ctx, GL_TEXTURE_CUBE_MAP, unit->SavedCubeMap.Name);
|
||||
MESA_REF_TEXOBJ(&texObj, NULL);
|
||||
texObj = get_texobj(ctx, GL_TEXTURE_RECTANGLE_NV, unit->SavedRect.Name);
|
||||
MESA_REF_TEXOBJ(&texObj, NULL);
|
||||
if (attr->kind == GL_TEXTURE_BIT) {
|
||||
struct texture_state *texstate = (struct texture_state*)attr->data;
|
||||
GLuint u;
|
||||
/* clear references to the saved texture objects */
|
||||
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef1D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef2D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRef3D[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefCube[u], NULL);
|
||||
MESA_REF_TEXOBJ(&texstate->SavedRefRect[u], NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* any other chunks of state that requires special handling? */
|
||||
}
|
||||
|
||||
next = attr->next;
|
||||
|
|
|
|||
|
|
@ -1523,12 +1523,6 @@ struct gl_texture_unit
|
|||
|
||||
struct gl_texture_object *_Current; /**< Points to really enabled tex obj */
|
||||
|
||||
struct gl_texture_object Saved1D; /**< only used by glPush/PopAttrib */
|
||||
struct gl_texture_object Saved2D;
|
||||
struct gl_texture_object Saved3D;
|
||||
struct gl_texture_object SavedCubeMap;
|
||||
struct gl_texture_object SavedRect;
|
||||
|
||||
/* GL_SGI_texture_color_table */
|
||||
struct gl_color_table ColorTable;
|
||||
struct gl_color_table ProxyColorTable;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue