From 64f36ff9fbe7e12c79cd72ceb68ed5967979445f Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 28 Apr 2009 10:08:57 -0700 Subject: Test either GL_FRONT_LEFT or GL_FRONT for front-buffer rendering For non-stereo visuals, which is all we support, we treat GL_FRONT_LEFT as GL_FRONT. However, they are technically different, and they have different enum values. Test for either one to determine if we're in front-buffer rendering mode. This fix was suggested by Pierre Willenbrock. Signed-off-by: Ian Romanick (cherry picked from commit 2085cf24628be7cd297ab0f9ef5ce02bd5a006e2) --- src/mesa/drivers/dri/intel/intel_buffers.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa') diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c index ecac5bf020..b86cafea24 100644 --- a/src/mesa/drivers/dri/intel/intel_buffers.c +++ b/src/mesa/drivers/dri/intel/intel_buffers.c @@ -326,7 +326,8 @@ intelDrawBuffer(GLcontext * ctx, GLenum mode) const GLboolean was_front_buffer_rendering = intel->is_front_buffer_rendering; - intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT); + intel->is_front_buffer_rendering = (mode == GL_FRONT_LEFT) + || (mode == GL_FRONT); /* If we weren't front-buffer rendering before but we are now, make sure * that the front-buffer has actually been allocated. -- cgit v1.2.3 From 5568f2f601fbd974af402da92548904f6fafc6dc Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 May 2009 09:27:31 -0600 Subject: mesa: reference counting for gl_array_object Every kind of object that can be shared by multiple contexts should be refcounted. (cherry picked from commit 1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a) --- src/mesa/main/arrayobj.c | 67 +++++++++++++++++++++++++++++++++++++++++++++--- src/mesa/main/arrayobj.h | 23 ++++++++++++----- src/mesa/main/mtypes.h | 3 +++ src/mesa/main/varray.c | 4 +-- 4 files changed, 84 insertions(+), 13 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index b04095fd16..ccb5b8e157 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -94,10 +94,69 @@ void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ) { (void) ctx; + _glthread_DESTROY_MUTEX(obj->Mutex); _mesa_free(obj); } +/** + * Set ptr to arrayObj w/ reference counting. + */ +void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj) +{ + if (*ptr == arrayObj) + return; + + if (*ptr) { + /* Unreference the old array object */ + GLboolean deleteFlag = GL_FALSE; + struct gl_array_object *oldObj = *ptr; + + _glthread_LOCK_MUTEX(oldObj->Mutex); + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; +#if 0 + printf("ArrayObj %p %d DECR to %d\n", + (void *) oldObj, oldObj->Name, oldObj->RefCount); +#endif + deleteFlag = (oldObj->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldObj->Mutex); + + if (deleteFlag) { + ASSERT(ctx->Driver.DeleteArrayObject); + ctx->Driver.DeleteArrayObject(ctx, oldObj); + } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (arrayObj) { + /* reference new array object */ + _glthread_LOCK_MUTEX(arrayObj->Mutex); + if (arrayObj->RefCount == 0) { + /* this array's being deleted (look just above) */ + /* Not sure this can every really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted array object"); + *ptr = NULL; + } + else { + arrayObj->RefCount++; +#if 0 + printf("ArrayObj %p %d INCR to %d\n", + (void *) arrayObj, arrayObj->Name, arrayObj->RefCount); +#endif + *ptr = arrayObj; + } + _glthread_UNLOCK_MUTEX(arrayObj->Mutex); + } +} + + + static void init_array(GLcontext *ctx, struct gl_client_array *array, GLint size, GLint type) @@ -129,6 +188,9 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->Name = name; + _glthread_INIT_MUTEX(obj->Mutex); + obj->RefCount = 1; + /* Init the individual arrays */ init_array(ctx, &obj->Vertex, 4, GL_FLOAT); init_array(ctx, &obj->Normal, 3, GL_FLOAT); @@ -226,7 +288,6 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) if (!newObj) { /* If this is a new array object id, allocate an array object now. */ - newObj = (*ctx->Driver.NewArrayObject)(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); @@ -236,11 +297,9 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) } } - ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= _NEW_ARRAY_ALL; - ctx->Array.ArrayObj = newObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj); /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index c7d66ec166..9c4036af5a 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -41,17 +41,26 @@ * Internal functions */ -struct gl_array_object * _mesa_new_array_object( GLcontext *ctx, - GLuint name ); +extern struct gl_array_object * +_mesa_new_array_object( GLcontext *ctx, GLuint name ); -void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); -void _mesa_initialize_array_object( GLcontext *ctx, - struct gl_array_object *obj, GLuint name ); +extern void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj); -void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_initialize_array_object( GLcontext *ctx, + struct gl_array_object *obj, GLuint name ); -void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); + +extern void +_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index ed6b1062bd..50dc2def87 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1557,6 +1557,9 @@ struct gl_array_object /** Name of the array object as received from glGenVertexArrayAPPLE. */ GLuint Name; + GLint RefCount; + _glthread_Mutex Mutex; + /** Conventional vertex arrays */ /*@{*/ struct gl_client_array Vertex; diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 106252e460..72b3e834b3 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -1050,7 +1050,7 @@ void _mesa_init_varray(GLcontext *ctx) { ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0); - ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, + ctx->Array.DefaultArrayObj); ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ } -- cgit v1.2.3 From 7ae4ce9e22e39d78e2d31164c05a3b267fb48e3c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 May 2009 09:32:53 -0600 Subject: mesa: clean-up vertex array object VBO unbinding and delete/refcounting Don't really delete vertex array objects until the refcount hits zero. At that time, unbind any pointers to VBOs. (cherry picked from commit 32b851c80792623195069d7a41a5808cff3b2f6f) --- src/mesa/main/arrayobj.c | 64 +++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 31 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index ccb5b8e157..0fa5f0de55 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -68,6 +68,32 @@ lookup_arrayobj(GLcontext *ctx, GLuint id) } +/** + * For all the vertex arrays in the array object, unbind any pointers + * to any buffer objects (VBOs). + * This is done just prior to array object destruction. + */ +static void +unbind_array_object_vbos(GLcontext *ctx, struct gl_array_object *obj) +{ + GLuint i; + + _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->Normal.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->Color.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->SecondaryColor.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->FogCoord.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->Index.BufferObj, NULL); + _mesa_reference_buffer_object(ctx, &obj->EdgeFlag.BufferObj, NULL); + + for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) + _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL); + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL); +} + + /** * Allocate and initialize a new vertex array object. * @@ -94,6 +120,7 @@ void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ) { (void) ctx; + unbind_array_object_vbos(ctx, obj); _glthread_DESTROY_MUTEX(obj->Mutex); _mesa_free(obj); } @@ -239,15 +266,6 @@ _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 */ /**********************************************************************/ @@ -274,7 +292,7 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) return; /* rebinding the same array object- no change */ /* - * Get pointer to new array object (newBufObj) + * Get pointer to new array object (newObj) */ if (id == 0) { /* The spec says there is no array object named 0, but we use @@ -333,7 +351,6 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) if ( obj != NULL ) { ASSERT( obj->Name == ids[i] ); - /* If the array object is currently bound, the spec says "the binding * for that object reverts to zero and the default vertex array * becomes current." @@ -342,28 +359,13 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) CALL_BindVertexArrayAPPLE( ctx->Exec, (0) ); } -#if FEATURE_ARB_vertex_buffer_object - /* Unbind any buffer objects that might be bound to arrays in - * this array object. - */ - 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_COORD_UNITS; i++) { - unbind_buffer_object( ctx, obj->TexCoord[i].BufferObj ); - } - unbind_buffer_object( ctx, obj->EdgeFlag.BufferObj ); - for (i = 0; i < VERT_ATTRIB_MAX; i++) { - unbind_buffer_object( ctx, obj->VertexAttrib[i].BufferObj ); - } -#endif - /* The ID is immediately freed for re-use */ _mesa_remove_array_object(ctx, obj); - ctx->Driver.DeleteArrayObject(ctx, obj); + + /* Unreference the array object. + * If refcount hits zero, the object will be deleted. + */ + _mesa_reference_array_object(ctx, &obj, NULL); } } -- cgit v1.2.3 From 3e74faa02948624cfbaf1f03854f27e0c9130759 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 May 2009 09:47:13 -0600 Subject: mesa: delete array objects before buffer objects during context tear-down The former may point to the later. --- src/mesa/main/context.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/mesa') diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c index 60c48289e4..ec0dc12a3e 100644 --- a/src/mesa/main/context.c +++ b/src/mesa/main/context.c @@ -1005,10 +1005,11 @@ _mesa_free_context_data( GLcontext *ctx ) _mesa_free_query_data(ctx); #endif + _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); + #if FEATURE_ARB_vertex_buffer_object _mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj); #endif - _mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj); /* free dispatch tables */ _mesa_free(ctx->Exec); -- cgit v1.2.3 From 2e4e34689022ecfcc7dc107427db90cc52a94d63 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 May 2009 10:28:00 -0600 Subject: intel: create a private gl_array_object for intel_clear_tris(), fix bug 21638 gl_array_object encapsulates a set of vertex arrays (see the GL_APPLE_vertex_array_object extension). Create a private gl_array_object for drawing the quad for intel_clear_tris() so we don't have to worry about the user's vertex array state. This fixes the no-op glClear bug #21638 and removes the need to call _mesa_PushClientAttrib() and _mesa_PopClientAttrib(). --- src/mesa/drivers/dri/intel/intel_clear.c | 93 ++++++++++++++++++++---------- src/mesa/drivers/dri/intel/intel_context.c | 3 + src/mesa/drivers/dri/intel/intel_context.h | 8 +++ 3 files changed, 75 insertions(+), 29 deletions(-) (limited to 'src/mesa') diff --git a/src/mesa/drivers/dri/intel/intel_clear.c b/src/mesa/drivers/dri/intel/intel_clear.c index aed95c7c56..eb0d890f47 100644 --- a/src/mesa/drivers/dri/intel/intel_clear.c +++ b/src/mesa/drivers/dri/intel/intel_clear.c @@ -30,6 +30,7 @@ #include "main/enums.h" #include "main/image.h" #include "main/mtypes.h" +#include "main/arrayobj.h" #include "main/attrib.h" #include "main/blend.h" #include "main/bufferobj.h" @@ -66,6 +67,45 @@ BUFFER_BIT_COLOR6 | \ BUFFER_BIT_COLOR7) + +/** + * Per-context one-time init of things for intl_clear_tris(). + * Basically set up a private array object for vertex/color arrays. + */ +static void +init_clear(GLcontext *ctx) +{ + struct intel_context *intel = intel_context(ctx); + struct gl_array_object *arraySave = NULL; + const GLuint arrayBuffer = ctx->Array.ArrayBufferObj->Name; + const GLuint elementBuffer = ctx->Array.ElementArrayBufferObj->Name; + + /* create new array object */ + intel->clear.arrayObj = _mesa_new_array_object(ctx, ~0); + + /* save current array object, bind new one */ + _mesa_reference_array_object(ctx, &arraySave, ctx->Array.ArrayObj); + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, intel->clear.arrayObj); + + /* one-time setup of vertex arrays (pos, color) */ + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + _mesa_ColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), intel->clear.color); + _mesa_VertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), intel->clear.vertices); + _mesa_Enable(GL_COLOR_ARRAY); + _mesa_Enable(GL_VERTEX_ARRAY); + + /* restore original array object */ + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, arraySave); + _mesa_reference_array_object(ctx, &arraySave, NULL); + + /* restore original buffer objects */ + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, arrayBuffer); + _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, elementBuffer); +} + + + /** * Perform glClear where mask contains only color, depth, and/or stencil. * @@ -78,14 +118,16 @@ void intel_clear_tris(GLcontext *ctx, GLbitfield mask) { struct intel_context *intel = intel_context(ctx); - GLfloat vertices[4][3]; - GLfloat color[4][4]; GLfloat dst_z; struct gl_framebuffer *fb = ctx->DrawBuffer; int i; GLboolean saved_fp_enable = GL_FALSE, saved_vp_enable = GL_FALSE; GLuint saved_shader_program = 0; unsigned int saved_active_texture; + struct gl_array_object *arraySave = NULL; + + if (!intel->clear.arrayObj) + init_clear(ctx); assert((mask & ~(TRI_CLEAR_COLOR_BITS | BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL)) == 0); @@ -98,7 +140,6 @@ intel_clear_tris(GLcontext *ctx, GLbitfield mask) GL_STENCIL_BUFFER_BIT | GL_TRANSFORM_BIT | GL_CURRENT_BIT); - _mesa_PushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT); saved_active_texture = ctx->Texture.CurrentUnit; /* Disable existing GL state we don't want to apply to a clear. */ @@ -149,18 +190,14 @@ intel_clear_tris(GLcontext *ctx, GLbitfield mask) } } -#if FEATURE_ARB_vertex_buffer_object - _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - _mesa_BindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); -#endif + /* save current array object, bind our private one */ + _mesa_reference_array_object(ctx, &arraySave, ctx->Array.ArrayObj); + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, intel->clear.arrayObj); intel_meta_set_passthrough_transform(intel); for (i = 0; i < 4; i++) { - color[i][0] = ctx->Color.ClearColor[0]; - color[i][1] = ctx->Color.ClearColor[1]; - color[i][2] = ctx->Color.ClearColor[2]; - color[i][3] = ctx->Color.ClearColor[3]; + COPY_4FV(intel->clear.color[i], ctx->Color.ClearColor); } /* convert clear Z from [0,1] to NDC coord in [-1,1] */ @@ -169,23 +206,18 @@ intel_clear_tris(GLcontext *ctx, GLbitfield mask) /* Prepare the vertices, which are the same regardless of which buffer we're * drawing to. */ - vertices[0][0] = fb->_Xmin; - vertices[0][1] = fb->_Ymin; - vertices[0][2] = dst_z; - vertices[1][0] = fb->_Xmax; - vertices[1][1] = fb->_Ymin; - vertices[1][2] = dst_z; - vertices[2][0] = fb->_Xmax; - vertices[2][1] = fb->_Ymax; - vertices[2][2] = dst_z; - vertices[3][0] = fb->_Xmin; - vertices[3][1] = fb->_Ymax; - vertices[3][2] = dst_z; - - _mesa_ColorPointer(4, GL_FLOAT, 4 * sizeof(GLfloat), &color); - _mesa_VertexPointer(3, GL_FLOAT, 3 * sizeof(GLfloat), &vertices); - _mesa_Enable(GL_COLOR_ARRAY); - _mesa_Enable(GL_VERTEX_ARRAY); + intel->clear.vertices[0][0] = fb->_Xmin; + intel->clear.vertices[0][1] = fb->_Ymin; + intel->clear.vertices[0][2] = dst_z; + intel->clear.vertices[1][0] = fb->_Xmax; + intel->clear.vertices[1][1] = fb->_Ymin; + intel->clear.vertices[1][2] = dst_z; + intel->clear.vertices[2][0] = fb->_Xmax; + intel->clear.vertices[2][1] = fb->_Ymax; + intel->clear.vertices[2][2] = dst_z; + intel->clear.vertices[3][0] = fb->_Xmin; + intel->clear.vertices[3][1] = fb->_Ymax; + intel->clear.vertices[3][2] = dst_z; while (mask != 0) { GLuint this_mask = 0; @@ -246,8 +278,11 @@ intel_clear_tris(GLcontext *ctx, GLbitfield mask) if (saved_shader_program) _mesa_UseProgramObjectARB(saved_shader_program); - _mesa_PopClientAttrib(); _mesa_PopAttrib(); + + /* restore current array object */ + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, arraySave); + _mesa_reference_array_object(ctx, &arraySave, NULL); } static const char *buffer_names[] = { diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index a6d8729d8f..07d53aad23 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -28,6 +28,7 @@ #include "main/glheader.h" #include "main/context.h" +#include "main/arrayobj.h" #include "main/extensions.h" #include "main/framebuffer.h" #include "main/imports.h" @@ -755,6 +756,8 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv) INTEL_FIREVERTICES(intel); + _mesa_delete_array_object(&intel->ctx, intel->clear.arrayObj); + intel->vtbl.destroy(intel); release_texture_heaps = (intel->ctx.Shared->RefCount == 1); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index d798225ddd..f45e24ca3a 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -215,6 +215,14 @@ struct intel_context GLuint ClearColor565; GLuint ClearColor8888; + /* info for intel_clear_tris() */ + struct + { + struct gl_array_object *arrayObj; + GLfloat vertices[4][3]; + GLfloat color[4][4]; + } clear; + /* Offsets of fields within the current vertex: */ GLuint coloroffset; -- cgit v1.2.3