From ffbd455a36f1d7600bd5b60e91768133d901d2f4 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 16 May 2008 15:34:22 -0600 Subject: fix an attr/src mix-up when setting-up/binding vertex arrays This fixes problems with incorrect material coefficients when glMaterial is called per-vertex. --- src/mesa/vbo/vbo_save_draw.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 3c6f0fccd9..bf5c6d4eef 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -131,10 +131,12 @@ static void vbo_bind_vertex_list( GLcontext *ctx, break; } - for (attr = 0; attr < VBO_ATTRIB_MAX; attr++) { - if (node->attrsz[attr]) { + for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { + GLuint src = map[attr]; + + if (node->attrsz[src]) { arrays[attr].Ptr = (const GLubyte *)data; - arrays[attr].Size = node->attrsz[attr]; + arrays[attr].Size = node->attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; @@ -144,7 +146,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx, assert(arrays[attr].BufferObj->Name); - data += node->attrsz[attr] * sizeof(GLfloat); + data += node->attrsz[src] * sizeof(GLfloat); } } } -- cgit v1.2.3 From a69fc5129bdf2f245c5bf2e0fe7b542caf7809a9 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 4 Sep 2008 15:25:45 -0600 Subject: mesa: improved gl_buffer_object reference counting Use new _mesa_reference_buffer_object() function wherever possible. Fixes buffer object/display list crash reported in ParaView. --- src/mesa/main/arrayobj.c | 31 ++++--- src/mesa/main/attrib.c | 87 +++++++++++--------- src/mesa/main/bufferobj.c | 188 +++++++++++++++++++++---------------------- src/mesa/main/bufferobj.h | 11 +-- src/mesa/main/varray.c | 15 ++-- src/mesa/vbo/vbo_exec_api.c | 8 +- src/mesa/vbo/vbo_exec_draw.c | 26 ++++-- src/mesa/vbo/vbo_save.c | 16 ++-- src/mesa/vbo/vbo_save_api.c | 17 +++- src/mesa/vbo/vbo_save_draw.c | 28 +++++-- 10 files changed, 241 insertions(+), 186 deletions(-) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index af2feb3553..1461239317 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.2 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * (C) Copyright IBM Corporation 2006 * * Permission is hereby granted, free of charge, to any person obtaining a @@ -219,6 +219,15 @@ _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ) } +static void +unbind_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) +{ + if (bufObj != ctx->Array.NullBufferObj) { + _mesa_reference_buffer_object(ctx, &bufObj, NULL); + } +} + + /**********************************************************************/ /* API Functions */ /**********************************************************************/ @@ -320,18 +329,18 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) /* Unbind any buffer objects that might be bound to arrays in * this array object. */ - _mesa_unbind_buffer_object( ctx, obj->Vertex.BufferObj ); - _mesa_unbind_buffer_object( ctx, obj->Normal.BufferObj ); - _mesa_unbind_buffer_object( ctx, obj->Color.BufferObj ); - _mesa_unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj ); - _mesa_unbind_buffer_object( ctx, obj->FogCoord.BufferObj ); - _mesa_unbind_buffer_object( ctx, obj->Index.BufferObj ); + unbind_buffer_object( ctx, obj->Vertex.BufferObj ); + unbind_buffer_object( ctx, obj->Normal.BufferObj ); + unbind_buffer_object( ctx, obj->Color.BufferObj ); + unbind_buffer_object( ctx, obj->SecondaryColor.BufferObj ); + unbind_buffer_object( ctx, obj->FogCoord.BufferObj ); + unbind_buffer_object( ctx, obj->Index.BufferObj ); for (i = 0; i < MAX_TEXTURE_UNITS; i++) { - _mesa_unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj ); + unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj ); } - _mesa_unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj ); + unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj ); for (i = 0; i < VERT_ATTRIB_MAX; i++) { - _mesa_unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj ); + unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj ); } #endif diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index b990369a9e..4cbb0273ab 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 7.1 + * Version: 7.2 * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 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"), @@ -1269,6 +1269,29 @@ adjust_buffer_object_ref_counts(struct gl_array_attrib *array, GLint step) } +/** + * Copy gl_pixelstore_attrib from src to dst, updating buffer + * object refcounts. + */ +static void +copy_pixelstore(GLcontext *ctx, + struct gl_pixelstore_attrib *dst, + const struct gl_pixelstore_attrib *src) +{ + dst->Alignment = src->Alignment; + dst->RowLength = src->RowLength; + dst->SkipPixels = src->SkipPixels; + dst->SkipRows = src->SkipRows; + dst->ImageHeight = src->ImageHeight; + dst->SkipImages = src->SkipImages; + dst->SwapBytes = src->SwapBytes; + dst->LsbFirst = src->LsbFirst; + dst->ClientStorage = src->ClientStorage; + dst->Invert = src->Invert; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); +} + + #define GL_CLIENT_PACK_BIT (1<<20) #define GL_CLIENT_UNPACK_BIT (1<<21) @@ -1287,31 +1310,29 @@ _mesa_PushClientAttrib(GLbitfield mask) return; } - /* Build linked list of attribute nodes which save all attribute */ - /* groups specified by the mask. */ + /* Build linked list of attribute nodes which save all attribute + * groups specified by the mask. + */ head = NULL; if (mask & GL_CLIENT_PIXEL_STORE_BIT) { struct gl_pixelstore_attrib *attr; -#if FEATURE_EXT_pixel_buffer_object - ctx->Pack.BufferObj->RefCount++; - ctx->Unpack.BufferObj->RefCount++; -#endif /* packing attribs */ - attr = MALLOC_STRUCT( gl_pixelstore_attrib ); - MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) ); + attr = CALLOC_STRUCT( gl_pixelstore_attrib ); + copy_pixelstore(ctx, attr, &ctx->Pack); newnode = new_attrib_node( GL_CLIENT_PACK_BIT ); newnode->data = attr; newnode->next = head; head = newnode; /* unpacking attribs */ attr = MALLOC_STRUCT( gl_pixelstore_attrib ); - MEMCPY( attr, &ctx->Unpack, sizeof(struct gl_pixelstore_attrib) ); + copy_pixelstore(ctx, attr, &ctx->Unpack); newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT ); newnode->data = attr; newnode->next = head; head = newnode; } + if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) { struct gl_array_attrib *attr; struct gl_array_object *obj; @@ -1348,7 +1369,7 @@ _mesa_PushClientAttrib(GLbitfield mask) void GLAPIENTRY _mesa_PopClientAttrib(void) { - struct gl_attrib_node *attr, *next; + struct gl_attrib_node *node, *next; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); @@ -1359,37 +1380,31 @@ _mesa_PopClientAttrib(void) } ctx->ClientAttribStackDepth--; - attr = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; + node = ctx->ClientAttribStack[ctx->ClientAttribStackDepth]; - while (attr) { - switch (attr->kind) { + while (node) { + switch (node->kind) { case GL_CLIENT_PACK_BIT: -#if FEATURE_EXT_pixel_buffer_object - ctx->Pack.BufferObj->RefCount--; - if (ctx->Pack.BufferObj->RefCount <= 0) { - _mesa_remove_buffer_object( ctx, ctx->Pack.BufferObj ); - (*ctx->Driver.DeleteBuffer)( ctx, ctx->Pack.BufferObj ); + { + struct gl_pixelstore_attrib *store = + (struct gl_pixelstore_attrib *) node->data; + copy_pixelstore(ctx, &ctx->Pack, store); + _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); } -#endif - MEMCPY( &ctx->Pack, attr->data, - sizeof(struct gl_pixelstore_attrib) ); ctx->NewState |= _NEW_PACKUNPACK; break; case GL_CLIENT_UNPACK_BIT: -#if FEATURE_EXT_pixel_buffer_object - ctx->Unpack.BufferObj->RefCount--; - if (ctx->Unpack.BufferObj->RefCount <= 0) { - _mesa_remove_buffer_object( ctx, ctx->Unpack.BufferObj ); - (*ctx->Driver.DeleteBuffer)( ctx, ctx->Unpack.BufferObj ); + { + struct gl_pixelstore_attrib *store = + (struct gl_pixelstore_attrib *) node->data; + copy_pixelstore(ctx, &ctx->Unpack, store); + _mesa_reference_buffer_object(ctx, &store->BufferObj, NULL); } -#endif - MEMCPY( &ctx->Unpack, attr->data, - sizeof(struct gl_pixelstore_attrib) ); ctx->NewState |= _NEW_PACKUNPACK; break; case GL_CLIENT_VERTEX_ARRAY_BIT: { struct gl_array_attrib * data = - (struct gl_array_attrib *) attr->data; + (struct gl_array_attrib *) node->data; adjust_buffer_object_ref_counts(&ctx->Array, -1); @@ -1424,10 +1439,10 @@ _mesa_PopClientAttrib(void) break; } - next = attr->next; - FREE( attr->data ); - FREE( attr ); - attr = next; + next = node->next; + FREE( node->data ); + FREE( node ); + node = next; } } diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index dc0307feb5..f1e0932b07 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 7.1 + * Version: 7.2 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * @@ -166,22 +166,75 @@ _mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) if (bufObj->Data) _mesa_free(bufObj->Data); + + /* assign strange values here to help w/ debugging */ + bufObj->RefCount = -1000; + bufObj->Name = ~0; + _mesa_free(bufObj); } + +/** + * Set ptr to bufObj w/ reference counting. + */ void -_mesa_unbind_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) +_mesa_reference_buffer_object(GLcontext *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *bufObj) { - if (bufObj != ctx->Array.NullBufferObj) { - bufObj->RefCount--; - if (bufObj->RefCount <= 0) { + if (*ptr == bufObj) + return; + + if (*ptr) { + /* Unreference the old texture */ + GLboolean deleteFlag = GL_FALSE; + struct gl_buffer_object *oldObj = *ptr; + + /*_glthread_LOCK_MUTEX(oldObj->Mutex);*/ + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; +#if 0 + printf("BufferObj %p %d DECR to %d\n", + (void *) oldObj, oldObj->Name, oldObj->RefCount); +#endif + deleteFlag = (oldObj->RefCount == 0); + /*_glthread_UNLOCK_MUTEX(oldObj->Mutex);*/ + + if (deleteFlag) { + + /* some sanity checking: don't delete a buffer still in use */ ASSERT(ctx->Array.ArrayBufferObj != bufObj); ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj); ASSERT(ctx->Driver.DeleteBuffer); - ctx->Driver.DeleteBuffer(ctx, bufObj); + + ctx->Driver.DeleteBuffer(ctx, oldObj); } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (bufObj) { + /* reference new texture */ + /*_glthread_LOCK_MUTEX(tex->Mutex);*/ + if (bufObj->RefCount == 0) { + /* this buffer's being deleted (look just above) */ + /* Not sure this can every really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted buffer object"); + *ptr = NULL; + } + else { + bufObj->RefCount++; +#if 0 + printf("BufferObj %p %d INCR to %d\n", + (void *) bufObj, bufObj->Name, bufObj->RefCount); +#endif + *ptr = bufObj; + } + /*_glthread_UNLOCK_MUTEX(tex->Mutex);*/ } } @@ -203,33 +256,6 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj, } -/** - * Add the given buffer object to the buffer object pool. - */ -void -_mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ) -{ - if (obj->Name > 0) { - /* insert into hash table */ - _mesa_HashInsert(ctx->Shared->BufferObjects, obj->Name, obj); - } -} - - -/** - * Remove the given buffer object from the buffer object pool. - * Do not deallocate the buffer object though. - */ -void -_mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) -{ - if (bufObj->Name > 0) { - /* remove from hash table */ - _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); - } -} - - /** * Allocate space for and store data in a buffer object. Any data that was * previously stored in the buffer object is lost. If \c data is \c NULL, @@ -400,6 +426,7 @@ _mesa_init_buffer_objects( GLcontext *ctx ) { /* Allocate the default buffer object and set refcount so high that * it never gets deleted. + * XXX with recent/improved refcounting this may not longer be needed. */ ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0); if (ctx->Array.NullBufferObj) @@ -621,6 +648,23 @@ _mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer) } +/** + * If *ptr points to obj, set ptr = the Null/default buffer object. + * This is a helper for buffer object deletion. + * The GL spec says that deleting a buffer object causes it to get + * unbound from all arrays in the current context. + */ +static void +unbind(GLcontext *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *obj) +{ + if (*ptr == obj) { + _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj); + } +} + + /**********************************************************************/ /* API Functions */ @@ -678,28 +722,16 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer) _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); return; } - _mesa_save_buffer_object(ctx, newBufObj); + _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj); } } - /* Make new binding */ - *bindTarget = newBufObj; - newBufObj->RefCount++; + /* bind new buffer */ + _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); /* 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 ); - } - } } @@ -731,54 +763,18 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) ASSERT(bufObj->Name == ids[i]); - if (ctx->Array.ArrayObj->Vertex.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->Vertex.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->Normal.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->Normal.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->Color.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->Color.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->SecondaryColor.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->SecondaryColor.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->FogCoord.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->FogCoord.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->Index.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->Index.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } - if (ctx->Array.ArrayObj->EdgeFlag.BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->EdgeFlag.BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } + unbind(ctx, &ctx->Array.ArrayObj->Vertex.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->Normal.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->Color.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->SecondaryColor.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->FogCoord.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->Index.BufferObj, bufObj); + unbind(ctx, &ctx->Array.ArrayObj->EdgeFlag.BufferObj, bufObj); for (j = 0; j < MAX_TEXTURE_UNITS; j++) { - if (ctx->Array.ArrayObj->TexCoord[j].BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->TexCoord[j].BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } + unbind(ctx, &ctx->Array.ArrayObj->TexCoord[j].BufferObj, bufObj); } for (j = 0; j < VERT_ATTRIB_MAX; j++) { - if (ctx->Array.ArrayObj->VertexAttrib[j].BufferObj == bufObj) { - bufObj->RefCount--; - ctx->Array.ArrayObj->VertexAttrib[j].BufferObj = ctx->Array.NullBufferObj; - ctx->Array.NullBufferObj->RefCount++; - } + unbind(ctx, &ctx->Array.ArrayObj->VertexAttrib[j].BufferObj, bufObj); } if (ctx->Array.ArrayBufferObj == bufObj) { @@ -796,8 +792,8 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) } /* The ID is immediately freed for re-use */ - _mesa_remove_buffer_object(ctx, bufObj); - _mesa_unbind_buffer_object(ctx, bufObj); + _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); + _mesa_reference_buffer_object(ctx, &bufObj, NULL); } } @@ -846,7 +842,7 @@ _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); return; } - _mesa_save_buffer_object(ctx, bufObj); + _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj); buffer[i] = first + i; } diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index 024e5a8c3c..2f908c5c35 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -1,6 +1,6 @@ /* * Mesa 3-D graphics library - * Version: 7.1 + * Version: 7.2 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * @@ -52,10 +52,9 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj, GLuint name, GLenum target ); extern void -_mesa_save_buffer_object( GLcontext *ctx, struct gl_buffer_object *obj ); - -extern void -_mesa_remove_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ); +_mesa_reference_buffer_object(GLcontext *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *bufObj); extern void _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, @@ -115,8 +114,6 @@ _mesa_unmap_readpix_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *pack); -extern void -_mesa_unbind_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ); /* * API functions diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index a6aa9c34b2..9f1fcd9d26 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.5.1 + * Version: 7.2 * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 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"), @@ -62,14 +62,9 @@ update_array(GLcontext *ctx, struct gl_client_array *array, array->Normalized = normalized; array->Ptr = (const GLubyte *) ptr; #if FEATURE_ARB_vertex_buffer_object - array->BufferObj->RefCount--; - if (array->BufferObj->RefCount <= 0) { - ASSERT(array->BufferObj->Name); - _mesa_remove_buffer_object( ctx, array->BufferObj ); - (*ctx->Driver.DeleteBuffer)( ctx, array->BufferObj ); - } - array->BufferObj = ctx->Array.ArrayBufferObj; - array->BufferObj->RefCount++; + _mesa_reference_buffer_object(ctx, &array->BufferObj, + ctx->Array.ArrayBufferObj); + /* Compute the index of the last array element that's inside the buffer. * Later in glDrawArrays we'll check if start + count > _MaxElement to * be sure we won't go out of bounds. diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index 579bbeb4f3..d70b4bb1a1 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -1,6 +1,6 @@ /************************************************************************** -Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. +Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas. All Rights Reserved. @@ -31,6 +31,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "main/glheader.h" +#include "main/bufferobj.h" #include "main/context.h" #include "main/macros.h" #include "main/vtxfmt.h" @@ -695,7 +696,10 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec ) * continuously, unless vbo_use_buffer_objects() is called to enable * use of real VBOs. */ - exec->vtx.bufferobj = ctx->Array.NullBufferObj; + _mesa_reference_buffer_object(ctx, + &exec->vtx.bufferobj, + ctx->Array.NullBufferObj); + exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64); vbo_exec_vtxfmt_init( exec ); diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index 3609a7452a..f497e9a5a5 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 5.1 + * Version: 7.2 * - * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 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"), @@ -26,6 +26,7 @@ */ #include "main/glheader.h" +#include "main/bufferobj.h" #include "main/context.h" #include "main/enums.h" #include "main/state.h" @@ -155,8 +156,12 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) */ switch (get_program_mode(exec->ctx)) { case VP_NONE: - memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); + for (attr = 0; attr < 16; attr++) { + exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; + } + for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { + exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr]; + } map = vbo->map_vp_none; break; case VP_NV: @@ -165,8 +170,10 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ - memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + for (attr = 0; attr < 16; attr++) { + exec->vtx.inputs[attr] = &vbo->legacy_currval[attr]; + exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr]; + } map = vbo->map_vp_arb; break; } @@ -178,6 +185,9 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) const GLuint src = map[attr]; if (exec->vtx.attrsz[src]) { + /* override the default array set above */ + exec->vtx.inputs[attr] = &arrays[attr]; + if (exec->vtx.bufferobj->Name) { /* a real buffer obj: Ptr is an offset, not a pointer*/ int offset; @@ -195,7 +205,9 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Enabled = 1; - arrays[attr].BufferObj = exec->vtx.bufferobj; + _mesa_reference_buffer_object(ctx, + &arrays[attr].BufferObj, + exec->vtx.bufferobj); arrays[attr]._MaxElement = count; /* ??? */ data += exec->vtx.attrsz[src] * sizeof(GLfloat); diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 8dd87141c0..9757c3d9f6 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.3 + * Version: 7.2 * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 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"), @@ -27,6 +27,7 @@ #include "main/mtypes.h" +#include "main/bufferobj.h" #include "main/dlist.h" #include "main/vtxfmt.h" #include "main/imports.h" @@ -71,19 +72,24 @@ void vbo_save_destroy( GLcontext *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; + GLuint i; + if (save->prim_store) { if ( --save->prim_store->refcount == 0 ) { FREE( save->prim_store ); save->prim_store = NULL; } if ( --save->vertex_store->refcount == 0 ) { - if (save->vertex_store->bufferobj) - ctx->Driver.DeleteBuffer( ctx, save->vertex_store->bufferobj ); - + _mesa_reference_buffer_object(ctx, + &save->vertex_store->bufferobj, NULL); FREE( save->vertex_store ); save->vertex_store = NULL; } } + + for (i = 0; i < VBO_ATTRIB_MAX; i++) { + _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL); + } } diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index f62be5c14c..88d573f128 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -1,6 +1,6 @@ /************************************************************************** -Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. +Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas. All Rights Reserved. @@ -68,6 +68,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/glheader.h" +#include "main/bufferobj.h" #include "main/context.h" #include "main/dlist.h" #include "main/enums.h" @@ -85,6 +86,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #endif +/* An interesting VBO number/name to help with debugging */ +#define VBO_BUF_ID 12345 + + /* * NOTE: Old 'parity' issue is gone, but copying can still be * wrong-footed on replay. @@ -170,7 +175,9 @@ static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx ) * user. Perhaps there could be a special number for internal * buffers: */ - vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); + vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, + VBO_BUF_ID, + GL_ARRAY_BUFFER_ARB); ctx->Driver.BufferData( ctx, GL_ARRAY_BUFFER_ARB, @@ -190,8 +197,9 @@ static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *ver { assert(!vertex_store->buffer); - if (vertex_store->bufferobj) - ctx->Driver.DeleteBuffer( ctx, vertex_store->bufferobj ); + if (vertex_store->bufferobj) { + _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL); + } FREE( vertex_store ); } @@ -1139,6 +1147,7 @@ void vbo_save_api_init( struct vbo_save_context *save ) _save_vtxfmt_init( ctx ); _save_current_init( ctx ); + /* These will actually get set again when binding/drawing */ for (i = 0; i < VBO_ATTRIB_MAX; i++) save->inputs[i] = &save->arrays[i]; diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index bf5c6d4eef..ed82f09958 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 6.1 + * Version: 7.2 * - * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 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"), @@ -27,6 +27,7 @@ */ #include "main/glheader.h" +#include "main/bufferobj.h" #include "main/context.h" #include "main/imports.h" #include "main/mtypes.h" @@ -115,8 +116,12 @@ static void vbo_bind_vertex_list( GLcontext *ctx, */ switch (get_program_mode(ctx)) { case VP_NONE: - memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->mat_currval, MAT_ATTRIB_MAX * sizeof(arrays[0])); + for (attr = 0; attr < 16; attr++) { + save->inputs[attr] = &vbo->legacy_currval[attr]; + } + for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) { + save->inputs[attr + 16] = &vbo->mat_currval[attr]; + } map = vbo->map_vp_none; break; case VP_NV: @@ -125,8 +130,10 @@ static void vbo_bind_vertex_list( GLcontext *ctx, * occurred. NV vertex programs cannot access material values, * nor attributes greater than VERT_ATTRIB_TEX7. */ - memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0])); - memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0])); + for (attr = 0; attr < 16; attr++) { + save->inputs[attr] = &vbo->legacy_currval[attr]; + save->inputs[attr + 16] = &vbo->generic_currval[attr]; + } map = vbo->map_vp_arb; break; } @@ -135,13 +142,18 @@ static void vbo_bind_vertex_list( GLcontext *ctx, GLuint src = map[attr]; if (node->attrsz[src]) { - arrays[attr].Ptr = (const GLubyte *)data; + /* override the default array set above */ + save->inputs[attr] = &arrays[attr]; + + arrays[attr].Ptr = (const GLubyte *) data; arrays[attr].Size = node->attrsz[src]; arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat); arrays[attr].Stride = node->vertex_size * sizeof(GLfloat); arrays[attr].Type = GL_FLOAT; arrays[attr].Enabled = 1; - arrays[attr].BufferObj = node->vertex_store->bufferobj; + _mesa_reference_buffer_object(ctx, + &arrays[attr].BufferObj, + node->vertex_store->bufferobj); arrays[attr]._MaxElement = node->count; /* ??? */ assert(arrays[attr].BufferObj->Name); -- cgit v1.2.3 From fa1b533012030cd67148b5bf1e018fd5e30c96f8 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 3 Oct 2008 13:55:40 +0100 Subject: mesa: add new internal state for tracking current vertex attribs --- src/mesa/main/mtypes.h | 1 + src/mesa/main/state.c | 4 ++++ src/mesa/shader/prog_statevars.c | 8 ++++++++ src/mesa/shader/prog_statevars.h | 1 + src/mesa/vbo/vbo_exec_api.c | 44 ++++++++++++++++++++++++---------------- src/mesa/vbo/vbo_save_draw.c | 24 ++++++++++++++-------- 6 files changed, 56 insertions(+), 26 deletions(-) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index a5e1cf6a27..bc099dabeb 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2744,6 +2744,7 @@ struct gl_matrix_stack #define _NEW_MULTISAMPLE 0x2000000 /**< __GLcontextRec::Multisample */ #define _NEW_TRACK_MATRIX 0x4000000 /**< __GLcontextRec::VertexProgram */ #define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */ +#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */ #define _NEW_ALL ~0 /*@}*/ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index d355f78a0e..eb8dc2a339 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -407,6 +407,9 @@ _mesa_update_state_locked( GLcontext *ctx ) GLbitfield new_state = ctx->NewState; GLbitfield prog_flags = _NEW_PROGRAM; + if (new_state == _NEW_CURRENT_ATTRIB) + goto out; + if (MESA_VERBOSE & VERBOSE_STATE) _mesa_print_state("_mesa_update_state", new_state); @@ -484,6 +487,7 @@ _mesa_update_state_locked( GLcontext *ctx ) * Set ctx->NewState to zero to avoid recursion if * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) */ + out: new_state = ctx->NewState; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c index 47c46f63ec..9cc33fa2c1 100644 --- a/src/mesa/shader/prog_statevars.c +++ b/src/mesa/shader/prog_statevars.c @@ -395,6 +395,12 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], case STATE_INTERNAL: switch (state[1]) { + case STATE_CURRENT_ATTRIB: { + const GLuint idx = (GLuint) state[2]; + COPY_4V(value, ctx->Current.Attrib[idx]); + return; + } + case STATE_NORMAL_SCALE: ASSIGN_4V(value, ctx->_ModelViewInvScale, @@ -565,6 +571,8 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) case STATE_INTERNAL: switch (state[1]) { + case STATE_CURRENT_ATTRIB: + return _NEW_CURRENT_ATTRIB; case STATE_NORMAL_SCALE: return _NEW_MODELVIEW; diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h index 7b490e3d63..1f728c64e8 100644 --- a/src/mesa/shader/prog_statevars.h +++ b/src/mesa/shader/prog_statevars.h @@ -104,6 +104,7 @@ typedef enum gl_state_index_ { STATE_LOCAL, STATE_INTERNAL, /* Mesa additions */ + STATE_CURRENT_ATTRIB, /* ctx->Current vertex attrib value */ STATE_NORMAL_SCALE, STATE_TEXRECT_SCALE, STATE_FOG_PARAMS_OPTIMIZED, /* for faster fog calc */ diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c index d70b4bb1a1..23f4f8331e 100644 --- a/src/mesa/vbo/vbo_exec_api.c +++ b/src/mesa/vbo/vbo_exec_api.c @@ -143,29 +143,37 @@ static void vbo_exec_copy_to_current( struct vbo_exec_context *exec ) for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { if (exec->vtx.attrsz[i]) { - GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; - /* Note: the exec->vtx.current[i] pointers point into the * ctx->Current.Attrib and ctx->Light.Material.Attrib arrays. */ - COPY_CLEAN_4V(current, - exec->vtx.attrsz[i], - exec->vtx.attrptr[i]); + GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + GLfloat tmp[4]; + + COPY_CLEAN_4V(tmp, + exec->vtx.attrsz[i], + exec->vtx.attrptr[i]); + + if (memcmp(current, tmp, sizeof(tmp)) != 0) + { + memcpy(current, tmp, sizeof(tmp)); - /* Given that we explicitly state size here, there is no need - * for the COPY_CLEAN above, could just copy 16 bytes and be - * done. The only problem is when Mesa accesses ctx->Current - * directly. - */ - vbo->currval[i].Size = exec->vtx.attrsz[i]; - - /* This triggers rather too much recalculation of Mesa state - * that doesn't get used (eg light positions). - */ - if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && - i <= VBO_ATTRIB_MAT_BACK_INDEXES) - ctx->NewState |= _NEW_LIGHT; + /* Given that we explicitly state size here, there is no need + * for the COPY_CLEAN above, could just copy 16 bytes and be + * done. The only problem is when Mesa accesses ctx->Current + * directly. + */ + vbo->currval[i].Size = exec->vtx.attrsz[i]; + + /* This triggers rather too much recalculation of Mesa state + * that doesn't get used (eg light positions). + */ + if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT && + i <= VBO_ATTRIB_MAT_BACK_INDEXES) + ctx->NewState |= _NEW_LIGHT; + + ctx->NewState |= _NEW_CURRENT_ATTRIB; + } } } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index ed82f09958..4c97acddb9 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -64,18 +64,26 @@ static void _playback_copy_to_current( GLcontext *ctx, for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) { if (node->attrsz[i]) { GLfloat *current = (GLfloat *)vbo->currval[i].Ptr; + GLfloat tmp[4]; - COPY_CLEAN_4V(current, - node->attrsz[i], - data); + COPY_CLEAN_4V(tmp, + node->attrsz[i], + data); + + if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) + { + memcpy(current, tmp, 4 * sizeof(GLfloat)); - vbo->currval[i].Size = node->attrsz[i]; + vbo->currval[i].Size = node->attrsz[i]; - data += node->attrsz[i]; + if (i >= VBO_ATTRIB_FIRST_MATERIAL && + i <= VBO_ATTRIB_LAST_MATERIAL) + ctx->NewState |= _NEW_LIGHT; + + ctx->NewState |= _NEW_CURRENT_ATTRIB; + } - if (i >= VBO_ATTRIB_FIRST_MATERIAL && - i <= VBO_ATTRIB_LAST_MATERIAL) - ctx->NewState |= _NEW_LIGHT; + data += node->attrsz[i]; } } -- cgit v1.2.3 From 1680ef869625dc1fe9cf481b180382a34e0738e7 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Fri, 3 Oct 2008 17:30:59 +0100 Subject: mesa: avoid generating constant vertex attributes in fixedfunc programs Keep track of enabled/active vertex attributes. Keep track of potential vertex program outputs. When generating fragment program, replace references to fragment attributes which are effectively non-varying and non-computed passthrough attributes with references to the new CURRENT_ATTRIB tracked state value. Only downside is slight ugliness in VBO code where we need to validate state twice in succession. --- src/mesa/main/mtypes.h | 2 + src/mesa/main/state.c | 38 ++++++++++++++++- src/mesa/main/state.h | 3 ++ src/mesa/main/texenvprogram.c | 94 ++++++++++++++++++++++++++++++++++++++++--- src/mesa/vbo/vbo_exec_array.c | 41 +++++++++++++++---- src/mesa/vbo/vbo_exec_draw.c | 8 ++++ src/mesa/vbo/vbo_save_draw.c | 4 ++ 7 files changed, 177 insertions(+), 13 deletions(-) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index bc099dabeb..ca1e369a35 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3073,6 +3073,8 @@ struct __GLcontextRec GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */ + GLuint varying_vp_inputs; + /** \name Derived state */ /*@{*/ GLbitfield _TriangleCaps; /**< bitwise-or of DD_* flags */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index eb8dc2a339..e0eb5f81e2 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -465,7 +465,8 @@ _mesa_update_state_locked( GLcontext *ctx ) _mesa_update_tnl_spaces( ctx, new_state ); if (ctx->FragmentProgram._MaintainTexEnvProgram) { - prog_flags |= (_NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR); + prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE_MATRIX | _NEW_LIGHT | + _NEW_TEXTURE | _NEW_FOG | _DD_NEW_SEPARATE_SPECULAR); } if (ctx->VertexProgram._MaintainTnlProgram) { prog_flags |= (_NEW_ARRAY | _NEW_TEXTURE | _NEW_TEXTURE_MATRIX | @@ -504,3 +505,38 @@ _mesa_update_state( GLcontext *ctx ) _mesa_update_state_locked(ctx); _mesa_unlock_context_textures(ctx); } + + + + +/* Want to figure out which fragment program inputs are actually + * constant/current values from ctx->Current. These should be + * referenced as a tracked state variable rather than a fragment + * program input, to save the overhead of putting a constant value in + * every submitted vertex, transferring it to hardware, interpolating + * it across the triangle, etc... + * + * When there is a VP bound, just use vp->outputs. But when we're + * generating vp from fixed function state, basically want to + * calculate: + * + * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) | + * potential_vp_outputs ) + * + * Where potential_vp_outputs is calculated by looking at enabled + * texgen, etc. + * + * The generated fragment program should then only declare inputs that + * may vary or otherwise differ from the ctx->Current values. + * Otherwise, the fp should track them as state values instead. + */ +void +_mesa_set_varying_vp_inputs( GLcontext *ctx, + unsigned varying_inputs ) +{ + if (ctx->varying_vp_inputs != varying_inputs) { + ctx->varying_vp_inputs = varying_inputs; + ctx->NewState |= _NEW_ARRAY; + //_mesa_printf("%s %x\n", __FUNCTION__, varying_inputs); + } +} diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h index bb7cb8f32a..dc08043a76 100644 --- a/src/mesa/main/state.h +++ b/src/mesa/main/state.h @@ -37,5 +37,8 @@ _mesa_update_state( GLcontext *ctx ); extern void _mesa_update_state_locked( GLcontext *ctx ); +void +_mesa_set_varying_vp_inputs( GLcontext *ctx, + unsigned varying_inputs ); #endif diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index ac49373604..7cd82f98b0 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -189,6 +189,63 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) } } +#define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0) +#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0) + +/* Identify all possible varying inputs. The fragment program will + * never reference non-varying inputs, but will track them via state + * constants instead. + * + * This function figures out all the inputs that the fragment program + * has access to. The bitmask is later reduced to just those which + * are actually referenced. + */ +static GLuint get_fp_input_mask( GLcontext *ctx ) +{ + GLuint fp_inputs = 0; + + if (1) { + GLuint varying_inputs = ctx->varying_vp_inputs; + + /* First look at what values may be computed by the generated + * vertex program: + */ + if (ctx->Light.Enabled) { + fp_inputs |= FRAG_BIT_COL0; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + fp_inputs |= FRAG_BIT_COL1; + } + + fp_inputs |= (ctx->Texture._TexGenEnabled | + ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0; + + /* Then look at what might be varying as a result of enabled + * arrays, etc: + */ + if (varying_inputs & VERT_BIT_COLOR0) fp_inputs |= FRAG_BIT_COL0; + if (varying_inputs & VERT_BIT_COLOR1) fp_inputs |= FRAG_BIT_COL1; + + fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0) + << FRAG_ATTRIB_TEX0); + + } + else { + /* calculate from vp->outputs */ + GLuint vp_outputs = 0; + + if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0; + if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1; + + fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) + << VERT_RESULT_TEX0) + >> FRAG_ATTRIB_TEX0); + } + + return fp_inputs; +} + + /** * Examine current texture environment state and generate a unique * key to identify it. @@ -196,17 +253,21 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) static void make_state_key( GLcontext *ctx, struct state_key *key ) { GLuint i, j; - + GLuint inputs_referenced = FRAG_BIT_COL0; + GLuint inputs_available = get_fp_input_mask( ctx ); + memset(key, 0, sizeof(*key)); for (i=0;iTexture.Unit[i]; - if (!texUnit->_ReallyEnabled) + if (!texUnit->_ReallyEnabled) continue; key->unit[i].enabled = 1; key->enabled_units |= (1<nr_enabled_units = i+1; + inputs_referenced |= FRAG_BIT_TEX(i); key->unit[i].source_index = translate_tex_src_bit(texUnit->_ReallyEnabled); @@ -234,13 +295,18 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) } } - if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { key->separate_specular = 1; + inputs_referenced |= FRAG_BIT_COL1; + } if (ctx->Fog.Enabled) { key->fog_enabled = 1; key->fog_mode = translate_fog_mode(ctx->Fog.Mode); + inputs_referenced |= FRAG_BIT_FOGC; /* maybe */ } + + key->inputs_available = (inputs_available & inputs_referenced); } /* Use uregs to represent registers internally, translate to Mesa's @@ -446,11 +512,29 @@ static struct ureg register_param5( struct texenv_fragment_program *p, #define register_param3(p,s0,s1,s2) register_param5(p,s0,s1,s2,0,0) #define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0) +static GLuint frag_to_vert_attrib( GLuint attrib ) +{ + switch (attrib) { + case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0; + case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1; + default: + assert(attrib >= FRAG_ATTRIB_TEX0); + assert(attrib <= FRAG_ATTRIB_TEX7); + return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0; + } +} + static struct ureg register_input( struct texenv_fragment_program *p, GLuint input ) { - p->program->Base.InputsRead |= (1 << input); - return make_ureg(PROGRAM_INPUT, input); + if (p->state->inputs_available & (1<program->Base.InputsRead |= (1 << input); + return make_ureg(PROGRAM_INPUT, input); + } + else { + GLuint idx = frag_to_vert_attrib( input ); + return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx ); + } } diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 0f9d8da356..3d74f9f431 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -127,6 +127,7 @@ static void recalculate_input_bindings( GLcontext *ctx ) struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; const struct gl_client_array **inputs = &exec->array.inputs[0]; + GLuint const_inputs = 0; GLuint i; exec->array.program_mode = get_program_mode(ctx); @@ -141,19 +142,24 @@ static void recalculate_input_bindings( GLcontext *ctx ) for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; - else + else { inputs[i] = &vbo->legacy_currval[i]; + const_inputs |= 1 << i; + } } for (i = 0; i < MAT_ATTRIB_MAX; i++) { inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; + const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); } /* Could use just about anything, just to fill in the empty * slots: */ - for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) + for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) { inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; + const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); + } break; case VP_NV: @@ -166,15 +172,19 @@ static void recalculate_input_bindings( GLcontext *ctx ) inputs[i] = exec->array.generic_array[i]; else if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; - else + else { inputs[i] = &vbo->legacy_currval[i]; + const_inputs |= 1 << i; + } } /* Could use just about anything, just to fill in the empty * slots: */ - for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) + for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) { inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; + const_inputs |= 1 << i; + } break; case VP_ARB: @@ -189,25 +199,34 @@ static void recalculate_input_bindings( GLcontext *ctx ) inputs[0] = exec->array.generic_array[0]; else if (exec->array.legacy_array[0]->Enabled) inputs[0] = exec->array.legacy_array[0]; - else + else { inputs[0] = &vbo->legacy_currval[0]; + const_inputs |= 1 << 0; + } for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { if (exec->array.legacy_array[i]->Enabled) inputs[i] = exec->array.legacy_array[i]; - else + else { inputs[i] = &vbo->legacy_currval[i]; + const_inputs |= 1 << i; + } } for (i = 0; i < 16; i++) { if (exec->array.generic_array[i]->Enabled) inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; - else + else { inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; + const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i); + } + } break; } + + _mesa_set_varying_vp_inputs( ctx, ~const_inputs ); } static void bind_arrays( GLcontext *ctx ) @@ -257,6 +276,11 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) bind_arrays( ctx ); + /* Again... + */ + if (ctx->NewState) + _mesa_update_state( ctx ); + prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; @@ -297,6 +321,9 @@ vbo_exec_DrawRangeElements(GLenum mode, bind_arrays( ctx ); + if (ctx->NewState) + _mesa_update_state( ctx ); + ib.count = count; ib.type = type; ib.obj = ctx->Array.ElementArrayBufferObj; diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index f497e9a5a5..ad60c9b05f 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -150,6 +150,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) GLubyte *data = exec->vtx.buffer_map; const GLuint *map; GLuint attr; + GLuint varying_inputs = 0; /* Install the default (ie Current) attributes first, then overlay * all active ones. @@ -211,8 +212,11 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) arrays[attr]._MaxElement = count; /* ??? */ data += exec->vtx.attrsz[src] * sizeof(GLfloat); + varying_inputs |= 1<NewState) + _mesa_update_state( ctx ); + + ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj); exec->vtx.buffer_map = NULL; diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 4c97acddb9..b015bf2786 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -118,6 +118,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx, GLuint data = node->buffer_offset; const GLuint *map; GLuint attr; + GLuint varying_inputs = 0; /* Install the default (ie Current) attributes first, then overlay * all active ones. @@ -167,8 +168,11 @@ static void vbo_bind_vertex_list( GLcontext *ctx, assert(arrays[attr].BufferObj->Name); data += node->attrsz[src] * sizeof(GLfloat); + varying_inputs |= 1< Date: Tue, 7 Oct 2008 16:33:17 +0100 Subject: mesa: update state after binding vertex list in dlist path --- src/mesa/vbo/vbo_save_draw.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index b015bf2786..68f3a965a5 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -241,6 +241,11 @@ void vbo_save_playback_vertex_list( GLcontext *ctx, void *data ) vbo_bind_vertex_list( ctx, node ); + /* Again... + */ + if (ctx->NewState) + _mesa_update_state( ctx ); + vbo_context(ctx)->draw_prims( ctx, save->inputs, node->prim, -- cgit v1.2.3 From 239617fbe22d4dd7b2794510a6665f09602b5adf Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 7 Oct 2008 11:22:47 -0600 Subject: mesa: replace GLuint with GLbitfield to be clearer about usage Also, fix up some comments to be doxygen style. --- src/mesa/main/mtypes.h | 2 +- src/mesa/main/state.c | 2 +- src/mesa/main/state.h | 2 +- src/mesa/main/texenvprogram.c | 30 ++++++++++++++++-------------- src/mesa/vbo/vbo_exec_array.c | 2 +- src/mesa/vbo/vbo_exec_draw.c | 2 +- src/mesa/vbo/vbo_save_draw.c | 2 +- 7 files changed, 22 insertions(+), 20 deletions(-) (limited to 'src/mesa/vbo/vbo_save_draw.c') diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index ca1e369a35..dff474d6d0 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -3073,7 +3073,7 @@ struct __GLcontextRec GLenum RenderMode; /**< either GL_RENDER, GL_SELECT, GL_FEEDBACK */ GLbitfield NewState; /**< bitwise-or of _NEW_* flags */ - GLuint varying_vp_inputs; + GLbitfield varying_vp_inputs; /**< mask of VERT_BIT_* flags */ /** \name Derived state */ /*@{*/ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index e0eb5f81e2..b124d48269 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -532,7 +532,7 @@ _mesa_update_state( GLcontext *ctx ) */ void _mesa_set_varying_vp_inputs( GLcontext *ctx, - unsigned varying_inputs ) + GLbitfield varying_inputs ) { if (ctx->varying_vp_inputs != varying_inputs) { ctx->varying_vp_inputs = varying_inputs; diff --git a/src/mesa/main/state.h b/src/mesa/main/state.h index dc08043a76..79f2f6beb0 100644 --- a/src/mesa/main/state.h +++ b/src/mesa/main/state.h @@ -39,6 +39,6 @@ _mesa_update_state_locked( GLcontext *ctx ); void _mesa_set_varying_vp_inputs( GLcontext *ctx, - unsigned varying_inputs ); + GLbitfield varying_inputs ); #endif diff --git a/src/mesa/main/texenvprogram.c b/src/mesa/main/texenvprogram.c index 7049467c22..638d6be5ad 100644 --- a/src/mesa/main/texenvprogram.c +++ b/src/mesa/main/texenvprogram.c @@ -192,7 +192,8 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) #define VERT_BIT_TEX_ANY (0xff << VERT_ATTRIB_TEX0) #define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0) -/* Identify all possible varying inputs. The fragment program will +/** + * Identify all possible varying inputs. The fragment program will * never reference non-varying inputs, but will track them via state * constants instead. * @@ -200,15 +201,15 @@ static GLuint translate_tex_src_bit( GLbitfield bit ) * has access to. The bitmask is later reduced to just those which * are actually referenced. */ -static GLuint get_fp_input_mask( GLcontext *ctx ) +static GLbitfield get_fp_input_mask( GLcontext *ctx ) { - GLuint fp_inputs = 0; + GLbitfield fp_inputs = 0x0; if (!ctx->VertexProgram._Enabled || !ctx->VertexProgram._Current) { /* Fixed function logic */ - GLuint varying_inputs = ctx->varying_vp_inputs; + GLbitfield varying_inputs = ctx->varying_vp_inputs; /* First look at what values may be computed by the generated * vertex program: @@ -235,7 +236,7 @@ static GLuint get_fp_input_mask( GLcontext *ctx ) } else { /* calculate from vp->outputs */ - GLuint vp_outputs = ctx->VertexProgram._Current->Base.OutputsWritten; + GLbitfield vp_outputs = ctx->VertexProgram._Current->Base.OutputsWritten; if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0; if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1; @@ -255,8 +256,8 @@ static GLuint get_fp_input_mask( GLcontext *ctx ) static void make_state_key( GLcontext *ctx, struct state_key *key ) { GLuint i, j; - GLuint inputs_referenced = FRAG_BIT_COL0; - GLuint inputs_available = get_fp_input_mask( ctx ); + GLbitfield inputs_referenced = FRAG_BIT_COL0; + GLbitfield inputs_available = get_fp_input_mask( ctx ); memset(key, 0, sizeof(*key)); @@ -311,7 +312,8 @@ static void make_state_key( GLcontext *ctx, struct state_key *key ) key->inputs_available = (inputs_available & inputs_referenced); } -/* Use uregs to represent registers internally, translate to Mesa's +/** + * Use uregs to represent registers internally, translate to Mesa's * expected formats on emit. * * NOTE: These are passed by value extensively in this file rather @@ -344,16 +346,16 @@ static const struct ureg undef = { }; -/* State used to build the fragment program: +/** State used to build the fragment program: */ struct texenv_fragment_program { struct gl_fragment_program *program; GLcontext *ctx; struct state_key *state; - GLbitfield alu_temps; /* Track texture indirections, see spec. */ - GLbitfield temps_output; /* Track texture indirections, see spec. */ - GLbitfield temp_in_use; /* Tracks temporary regs which are in use. */ + GLbitfield alu_temps; /**< Track texture indirections, see spec. */ + GLbitfield temps_output; /**< Track texture indirections, see spec. */ + GLbitfield temp_in_use; /**< Tracks temporary regs which are in use. */ GLboolean error; struct ureg src_texture[MAX_TEXTURE_UNITS]; @@ -361,11 +363,11 @@ struct texenv_fragment_program { * else undef. */ - struct ureg src_previous; /* Reg containing color from previous + struct ureg src_previous; /**< Reg containing color from previous * stage. May need to be decl'd. */ - GLuint last_tex_stage; /* Number of last enabled texture unit */ + GLuint last_tex_stage; /**< Number of last enabled texture unit */ struct ureg half; struct ureg one; diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 3d74f9f431..8871e10cf6 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -127,7 +127,7 @@ static void recalculate_input_bindings( GLcontext *ctx ) struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; const struct gl_client_array **inputs = &exec->array.inputs[0]; - GLuint const_inputs = 0; + GLbitfield const_inputs = 0x0; GLuint i; exec->array.program_mode = get_program_mode(ctx); diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index ad60c9b05f..ae43857c8a 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -150,7 +150,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx ) GLubyte *data = exec->vtx.buffer_map; const GLuint *map; GLuint attr; - GLuint varying_inputs = 0; + GLbitfield varying_inputs = 0x0; /* Install the default (ie Current) attributes first, then overlay * all active ones. diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 68f3a965a5..0488c5d718 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -118,7 +118,7 @@ static void vbo_bind_vertex_list( GLcontext *ctx, GLuint data = node->buffer_offset; const GLuint *map; GLuint attr; - GLuint varying_inputs = 0; + GLbitfield varying_inputs = 0x0; /* Install the default (ie Current) attributes first, then overlay * all active ones. -- cgit v1.2.3