summaryrefslogtreecommitdiff
path: root/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/main')
-rw-r--r--src/mesa/main/api_validate.c85
-rw-r--r--src/mesa/main/arrayobj.c148
-rw-r--r--src/mesa/main/arrayobj.h20
-rw-r--r--src/mesa/main/bufferobj.c30
-rw-r--r--src/mesa/main/buffers.c2
-rw-r--r--src/mesa/main/config.h2
-rw-r--r--src/mesa/main/context.c34
-rw-r--r--src/mesa/main/context.h4
-rw-r--r--src/mesa/main/debug.c5
-rw-r--r--src/mesa/main/enable.c8
-rw-r--r--src/mesa/main/ffvertex_prog.c16
-rw-r--r--src/mesa/main/histogram.c7
-rw-r--r--src/mesa/main/image.c2
-rw-r--r--src/mesa/main/imports.c35
-rw-r--r--src/mesa/main/mtypes.h29
-rw-r--r--src/mesa/main/pixel.c14
-rw-r--r--src/mesa/main/pixelstore.c9
-rw-r--r--src/mesa/main/shared.c16
-rw-r--r--src/mesa/main/state.c123
-rw-r--r--src/mesa/main/teximage.c21
-rw-r--r--src/mesa/main/texobj.c53
-rw-r--r--src/mesa/main/texobj.h3
-rw-r--r--src/mesa/main/texparam.c22
-rw-r--r--src/mesa/main/texstate.c18
-rw-r--r--src/mesa/main/varray.c19
-rw-r--r--src/mesa/main/version.h7
26 files changed, 494 insertions, 238 deletions
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 42d1e579e0..d5c604c56a 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -30,6 +30,26 @@
#include "state.h"
+
+/**
+ * \return number of bytes in array [count] of type.
+ */
+static GLsizei
+index_bytes(GLenum type, GLsizei count)
+{
+ if (type == GL_UNSIGNED_INT) {
+ return count * sizeof(GLuint);
+ }
+ else if (type == GL_UNSIGNED_BYTE) {
+ return count * sizeof(GLubyte);
+ }
+ else {
+ ASSERT(type == GL_UNSIGNED_SHORT);
+ return count * sizeof(GLushort);
+ }
+}
+
+
/**
* Find the max index in the given element/index buffer
*/
@@ -44,10 +64,8 @@ max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
if (elementBuf->Name) {
/* elements are in a user-defined buffer object. need to map it */
- map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- elementBuf);
+ map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY, elementBuf);
/* Actual address is the sum of pointers */
indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices);
}
@@ -70,14 +88,16 @@ max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
}
if (map) {
- ctx->Driver.UnmapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- ctx->Array.ElementArrayBufferObj);
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, elementBuf);
}
return max;
}
+
+/**
+ * Check if OK to render by examining framebuffer status and vertex arrays.
+ */
static GLboolean
check_valid_to_render(GLcontext *ctx, char *function)
{
@@ -105,6 +125,12 @@ check_valid_to_render(GLcontext *ctx, char *function)
return GL_TRUE;
}
+
+/**
+ * Error checking for glDrawElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
GLboolean
_mesa_validate_DrawElements(GLcontext *ctx,
GLenum mode, GLsizei count, GLenum type,
@@ -140,27 +166,8 @@ _mesa_validate_DrawElements(GLcontext *ctx,
/* Vertex buffer object tests */
if (ctx->Array.ElementArrayBufferObj->Name) {
/* use indices in the buffer object */
- GLuint indexBytes;
-
- if (!ctx->Array.ElementArrayBufferObj->Size) {
- _mesa_warning(ctx,
- "glDrawElements called with empty array elements buffer");
- return GL_FALSE;
- }
-
- if (type == GL_UNSIGNED_INT) {
- indexBytes = count * sizeof(GLuint);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- indexBytes = count * sizeof(GLubyte);
- }
- else {
- ASSERT(type == GL_UNSIGNED_SHORT);
- indexBytes = count * sizeof(GLushort);
- }
-
/* make sure count doesn't go outside buffer bounds */
- if (indexBytes > (GLuint) ctx->Array.ElementArrayBufferObj->Size) {
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
_mesa_warning(ctx, "glDrawElements index out of buffer bounds");
return GL_FALSE;
}
@@ -177,6 +184,8 @@ _mesa_validate_DrawElements(GLcontext *ctx,
ctx->Array.ElementArrayBufferObj);
if (max >= ctx->Array._MaxElement) {
/* the max element is out of bounds of one or more enabled arrays */
+ _mesa_warning(ctx, "glDrawElements() index=%u is "
+ "out of bounds (max=%u)", max, ctx->Array._MaxElement);
return GL_FALSE;
}
}
@@ -184,6 +193,12 @@ _mesa_validate_DrawElements(GLcontext *ctx,
return GL_TRUE;
}
+
+/**
+ * Error checking for glDrawRangeElements(). Includes parameter checking
+ * and VBO bounds checking.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
+ */
GLboolean
_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
GLuint start, GLuint end,
@@ -224,21 +239,8 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
/* Vertex buffer object tests */
if (ctx->Array.ElementArrayBufferObj->Name) {
/* use indices in the buffer object */
- GLuint indexBytes;
-
- if (type == GL_UNSIGNED_INT) {
- indexBytes = count * sizeof(GLuint);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- indexBytes = count * sizeof(GLubyte);
- }
- else {
- ASSERT(type == GL_UNSIGNED_SHORT);
- indexBytes = count * sizeof(GLushort);
- }
-
/* make sure count doesn't go outside buffer bounds */
- if (indexBytes > ctx->Array.ElementArrayBufferObj->Size) {
+ if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) {
_mesa_warning(ctx, "glDrawRangeElements index out of buffer bounds");
return GL_FALSE;
}
@@ -265,6 +267,7 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
/**
* Called from the tnl module to error check the function parameters and
* verify that we really can draw something.
+ * \return GL_TRUE if OK to render, GL_FALSE if error found
*/
GLboolean
_mesa_validate_DrawArrays(GLcontext *ctx,
diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c
index b04095fd16..8ec73b9526 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -69,6 +69,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.
*
* This function is intended to be called via
@@ -94,10 +120,70 @@ 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);
}
+/**
+ * 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)
@@ -112,7 +198,8 @@ init_array(GLcontext *ctx,
array->Normalized = GL_FALSE;
#if FEATURE_ARB_vertex_buffer_object
/* Vertex array buffers */
- array->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &array->BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
}
@@ -129,6 +216,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);
@@ -153,8 +243,8 @@ _mesa_initialize_array_object( GLcontext *ctx,
/**
* Add the given array object to the array object pool.
*/
-void
-_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj )
+static void
+save_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
if (obj->Name > 0) {
/* insert into hash table */
@@ -167,8 +257,8 @@ _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj )
* Remove the given array object from the array object pool.
* Do not deallocate the array object though.
*/
-void
-_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
+static void
+remove_array_object( GLcontext *ctx, struct gl_array_object *obj )
{
if (obj->Name > 0) {
/* remove from hash table */
@@ -177,15 +267,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 */
/**********************************************************************/
@@ -212,7 +293,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
@@ -226,21 +307,18 @@ _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");
return;
}
- _mesa_save_array_object(ctx, newObj);
+ save_array_object(ctx, newObj);
}
}
-
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)
@@ -274,7 +352,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."
@@ -283,28 +360,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);
+ remove_array_object(ctx, obj);
+
+ /* Unreference the array object.
+ * If refcount hits zero, the object will be deleted.
+ */
+ _mesa_reference_array_object(ctx, &obj, NULL);
}
}
@@ -353,7 +415,7 @@ _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE");
return;
}
- _mesa_save_array_object(ctx, obj);
+ save_array_object(ctx, obj);
arrays[i] = first + i;
}
diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h
index c7d66ec166..9c2f340cfa 100644
--- a/src/mesa/main/arrayobj.h
+++ b/src/mesa/main/arrayobj.h
@@ -41,18 +41,20 @@
* 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 );
-
-void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj );
-
-void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj );
+extern void
+_mesa_reference_array_object(GLcontext *ctx,
+ struct gl_array_object **ptr,
+ struct gl_array_object *arrayObj);
+extern void
+_mesa_initialize_array_object( GLcontext *ctx,
+ struct gl_array_object *obj, GLuint name );
/*
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c
index c8d160baa9..1f2070ef47 100644
--- a/src/mesa/main/bufferobj.c
+++ b/src/mesa/main/bufferobj.c
@@ -194,7 +194,7 @@ _mesa_reference_buffer_object(GLcontext *ctx,
return;
if (*ptr) {
- /* Unreference the old texture */
+ /* Unreference the old buffer */
GLboolean deleteFlag = GL_FALSE;
struct gl_buffer_object *oldObj = *ptr;
@@ -227,7 +227,7 @@ _mesa_reference_buffer_object(GLcontext *ctx,
ASSERT(!*ptr);
if (bufObj) {
- /* reference new texture */
+ /* reference new buffer */
/*_glthread_LOCK_MUTEX(tex->Mutex);*/
if (bufObj->RefCount == 0) {
/* this buffer's being deleted (look just above) */
@@ -389,7 +389,6 @@ _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
(void) ctx;
(void) target;
(void) access;
- ASSERT(!bufObj->OnCard);
/* Just return a direct pointer to the data */
if (bufObj->Pointer) {
/* already mapped! */
@@ -413,7 +412,6 @@ _mesa_buffer_unmap( GLcontext *ctx, GLenum target,
{
(void) ctx;
(void) target;
- ASSERT(!bufObj->OnCard);
/* XXX we might assert here that bufObj->Pointer is non-null */
bufObj->Pointer = NULL;
return GL_TRUE;
@@ -426,16 +424,8 @@ _mesa_buffer_unmap( GLcontext *ctx, GLenum target,
void
_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)
- ctx->Array.NullBufferObj->RefCount = 1000;
-
- ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj;
- ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj;
+ ctx->Array.ArrayBufferObj = ctx->Shared->NullBufferObj;
+ ctx->Array.ElementArrayBufferObj = ctx->Shared->NullBufferObj;
}
@@ -479,7 +469,7 @@ bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer)
/* The spec says there's not a buffer object named 0, but we use
* one internally because it simplifies things.
*/
- newBufObj = ctx->Array.NullBufferObj;
+ newBufObj = ctx->Shared->NullBufferObj;
}
else {
/* non-default buffer object */
@@ -746,7 +736,7 @@ unbind(GLcontext *ctx,
struct gl_buffer_object *obj)
{
if (*ptr == obj) {
- _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj);
+ _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj);
}
}
@@ -958,8 +948,12 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
bufObj->Pointer = NULL;
}
+ FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+
ASSERT(ctx->Driver.BufferData);
+ bufObj->Written = GL_TRUE;
+
/* Give the buffer object to the driver! <data> may be null! */
ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj );
}
@@ -980,6 +974,8 @@ _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset,
return;
}
+ bufObj->Written = GL_TRUE;
+
ASSERT(ctx->Driver.BufferSubData);
ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj );
}
@@ -1044,6 +1040,8 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
}
bufObj->Access = access;
+ if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+ bufObj->Written = GL_TRUE;
return bufObj->Pointer;
}
diff --git a/src/mesa/main/buffers.c b/src/mesa/main/buffers.c
index c5f13345f0..d8b5f3b1f4 100644
--- a/src/mesa/main/buffers.c
+++ b/src/mesa/main/buffers.c
@@ -443,7 +443,7 @@ _mesa_readbuffer(GLcontext *ctx, GLenum buffer, GLint bufferIndex)
fb->ColorReadBuffer = buffer;
fb->_ColorReadBufferIndex = bufferIndex;
- ctx->NewState |= _NEW_PIXEL;
+ ctx->NewState |= _NEW_BUFFERS;
}
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
index 2a9fdf9ca0..888e08ff93 100644
--- a/src/mesa/main/config.h
+++ b/src/mesa/main/config.h
@@ -187,7 +187,7 @@
#define MAX_PROGRAM_TEMPS 256
#define MAX_PROGRAM_ADDRESS_REGS 2
#define MAX_UNIFORMS 1024 /**< number of vec4 uniforms */
-#define MAX_VARYING 8 /**< number of float[4] vectors */
+#define MAX_VARYING 16 /**< number of float[4] vectors */
#define MAX_SAMPLERS MAX_TEXTURE_IMAGE_UNITS
#define MAX_PROGRAM_INPUTS 32
#define MAX_PROGRAM_OUTPUTS 32
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 5726dbd983..5e0f2d7b1b 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -434,7 +434,7 @@ one_time_init( GLcontext *ctx )
}
#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
- _mesa_debug(ctx, "Mesa %s DEBUG build %s %s",
+ _mesa_debug(ctx, "Mesa %s DEBUG build %s %s\n",
MESA_VERSION_STRING, __DATE__, __TIME__);
#endif
@@ -602,6 +602,10 @@ _mesa_init_constants(GLcontext *ctx)
ASSERT(MAX_NV_VERTEX_PROGRAM_TEMPS <= MAX_PROGRAM_TEMPS);
ASSERT(MAX_NV_VERTEX_PROGRAM_INPUTS <= VERT_ATTRIB_MAX);
ASSERT(MAX_NV_VERTEX_PROGRAM_OUTPUTS <= VERT_RESULT_MAX);
+
+ /* check that we don't exceed various 32-bit bitfields */
+ ASSERT(VERT_RESULT_MAX <= 32);
+ ASSERT(FRAG_ATTRIB_MAX <= 32);
}
@@ -1005,9 +1009,6 @@ _mesa_free_context_data( GLcontext *ctx )
_mesa_free_query_data(ctx);
#endif
-#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 */
@@ -1397,14 +1398,21 @@ _mesa_share_state(GLcontext *ctx, GLcontext *ctxToShare)
{
if (ctx && ctxToShare && ctx->Shared && ctxToShare->Shared) {
struct gl_shared_state *oldSharedState = ctx->Shared;
+ GLint RefCount;
ctx->Shared = ctxToShare->Shared;
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
ctx->Shared->RefCount++;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
update_default_objects(ctx);
- oldSharedState->RefCount--;
- if (oldSharedState->RefCount == 0) {
+ _glthread_LOCK_MUTEX(oldSharedState->Mutex);
+ RefCount = --oldSharedState->RefCount;
+ _glthread_UNLOCK_MUTEX(oldSharedState->Mutex);
+
+ if (RefCount == 0) {
_mesa_free_shared_state(ctx, oldSharedState);
}
@@ -1497,6 +1505,7 @@ _mesa_Finish(void)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+ FLUSH_CURRENT( ctx, 0 );
if (ctx->Driver.Finish) {
ctx->Driver.Finish(ctx);
}
@@ -1521,4 +1530,17 @@ _mesa_Flush(void)
}
+/**
+ * Set mvp_with_dp4 flag. If a driver has a preference for DP4 over
+ * MUL/MAD, or vice versa, call this function to register that.
+ * Otherwise we default to MUL/MAD.
+ */
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag )
+{
+ ctx->mvp_with_dp4 = flag;
+}
+
+
/*@}*/
diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h
index ecc1cec779..5b57d88029 100644
--- a/src/mesa/main/context.h
+++ b/src/mesa/main/context.h
@@ -151,6 +151,10 @@ extern struct _glapi_table *
_mesa_get_dispatch(GLcontext *ctx);
+void
+_mesa_set_mvp_with_dp4( GLcontext *ctx,
+ GLboolean flag );
+
/** \name Miscellaneous */
/*@{*/
diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c
index fdd10dd307..2eabcdaf49 100644
--- a/src/mesa/main/debug.c
+++ b/src/mesa/main/debug.c
@@ -3,6 +3,7 @@
* Version: 6.5
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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"),
@@ -262,7 +263,7 @@ static void
write_texture_image(struct gl_texture_object *texObj)
{
const struct gl_texture_image *img = texObj->Image[0][0];
- if (img) {
+ if (img && img->Data) {
char s[100];
/* make filename */
@@ -338,5 +339,5 @@ _mesa_dump_textures(GLboolean dumpImages)
{
GET_CURRENT_CONTEXT(ctx);
DumpImages = dumpImages;
- _mesa_HashDeleteAll(ctx->Shared->TexObjects, dump_texture_cb, ctx);
+ _mesa_HashWalk(ctx->Shared->TexObjects, dump_texture_cb, ctx);
}
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
index f432be183c..2e7baa48ff 100644
--- a/src/mesa/main/enable.c
+++ b/src/mesa/main/enable.c
@@ -222,14 +222,16 @@ get_texcoord_unit(GLcontext *ctx)
/**
* Helper function to enable or disable a texture target.
+ * \param bit one of the TEXTURE_x_BIT values
+ * \return GL_TRUE if state is changing or GL_FALSE if no change
*/
static GLboolean
-enable_texture(GLcontext *ctx, GLboolean state, GLbitfield bit)
+enable_texture(GLcontext *ctx, GLboolean state, GLbitfield texBit)
{
const GLuint curr = ctx->Texture.CurrentUnit;
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
- const GLuint newenabled = (!state)
- ? (texUnit->Enabled & ~bit) : (texUnit->Enabled | bit);
+ const GLbitfield newenabled = state
+ ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
if (!ctx->DrawBuffer->Visual.rgbMode || texUnit->Enabled == newenabled)
return GL_FALSE;
diff --git a/src/mesa/main/ffvertex_prog.c b/src/mesa/main/ffvertex_prog.c
index 1ce5685af4..43325b1352 100644
--- a/src/mesa/main/ffvertex_prog.c
+++ b/src/mesa/main/ffvertex_prog.c
@@ -315,12 +315,6 @@ static void make_state_key( GLcontext *ctx, struct state_key *key )
*/
#define DISASSEM 0
-/* Should be tunable by the driver - do we want to do matrix
- * multiplications with DP4's or with MUL/MAD's? SSE works better
- * with the latter, drivers may differ.
- */
-#define PREFER_DP4 0
-
/* Use uregs to represent registers internally, translate to Mesa's
* expected formats on emit.
@@ -348,6 +342,7 @@ struct tnl_program {
const struct state_key *state;
struct gl_vertex_program *program;
GLint max_inst; /** number of instructions allocated for program */
+ GLboolean mvp_with_dp4;
GLuint temp_in_use;
GLuint temp_reserved;
@@ -775,7 +770,7 @@ static struct ureg get_eye_position( struct tnl_program *p )
p->eye_position = reserve_temp(p);
- if (PREFER_DP4) {
+ if (p->mvp_with_dp4) {
register_matrix_param5( p, STATE_MODELVIEW_MATRIX, 0, 0, 3,
0, modelview );
@@ -881,7 +876,7 @@ static void build_hpos( struct tnl_program *p )
struct ureg hpos = register_output( p, VERT_RESULT_HPOS );
struct ureg mvp[4];
- if (PREFER_DP4) {
+ if (p->mvp_with_dp4) {
register_matrix_param5( p, STATE_MVP_MATRIX, 0, 0, 3,
0, mvp );
emit_matrix_transform_vec4( p, hpos, mvp, pos );
@@ -1574,7 +1569,7 @@ static void build_texture_transform( struct tnl_program *p )
struct ureg in = (!is_undef(out_texgen) ?
out_texgen :
register_input(p, VERT_ATTRIB_TEX0+i));
- if (PREFER_DP4) {
+ if (p->mvp_with_dp4) {
register_matrix_param5( p, STATE_TEXTURE_MATRIX, i, 0, 3,
0, texmat );
emit_matrix_transform_vec4( p, out, texmat, in );
@@ -1708,6 +1703,7 @@ static void build_tnl_program( struct tnl_program *p )
static void
create_new_program( const struct state_key *key,
struct gl_vertex_program *program,
+ GLboolean mvp_with_dp4,
GLuint max_temps)
{
struct tnl_program p;
@@ -1721,6 +1717,7 @@ create_new_program( const struct state_key *key,
p.transformed_normal = undef;
p.identity = undef;
p.temp_in_use = 0;
+ p.mvp_with_dp4 = mvp_with_dp4;
if (max_temps >= sizeof(int) * 8)
p.temp_reserved = 0;
@@ -1776,6 +1773,7 @@ _mesa_get_fixed_func_vertex_program(GLcontext *ctx)
return NULL;
create_new_program( &key, prog,
+ ctx->mvp_with_dp4,
ctx->Const.VertexProgram.MaxTemps );
#if 0
diff --git a/src/mesa/main/histogram.c b/src/mesa/main/histogram.c
index 905c1ad830..5fee4fd0e3 100644
--- a/src/mesa/main/histogram.c
+++ b/src/mesa/main/histogram.c
@@ -975,6 +975,8 @@ _mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean s
}
}
+ FLUSH_VERTICES(ctx, _NEW_PIXEL);
+
/* reset histograms */
for (i = 0; i < HISTOGRAM_TABLE_SIZE; i++) {
ctx->Histogram.Count[i][0] = 0;
@@ -1002,8 +1004,6 @@ _mesa_Histogram(GLenum target, GLsizei width, GLenum internalFormat, GLboolean s
ctx->Histogram.AlphaSize = 8 * sizeof(GLuint);
ctx->Histogram.LuminanceSize = 8 * sizeof(GLuint);
}
-
- ctx->NewState |= _NEW_PIXEL;
}
@@ -1058,8 +1058,6 @@ _mesa_ResetHistogram(GLenum target)
ctx->Histogram.Count[i][2] = 0;
ctx->Histogram.Count[i][3] = 0;
}
-
- ctx->NewState |= _NEW_PIXEL;
}
@@ -1083,7 +1081,6 @@ _mesa_ResetMinmax(GLenum target)
ctx->MinMax.Min[GCOMP] = 1000; ctx->MinMax.Max[GCOMP] = -1000;
ctx->MinMax.Min[BCOMP] = 1000; ctx->MinMax.Max[BCOMP] = -1000;
ctx->MinMax.Min[ACOMP] = 1000; ctx->MinMax.Max[ACOMP] = -1000;
- ctx->NewState |= _NEW_PIXEL;
}
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
index ddae456fa1..ea76ed04e4 100644
--- a/src/mesa/main/image.c
+++ b/src/mesa/main/image.c
@@ -181,6 +181,8 @@ _mesa_sizeof_type( GLenum type )
return sizeof(GLint);
case GL_FLOAT:
return sizeof(GLfloat);
+ case GL_DOUBLE:
+ return sizeof(GLdouble);
case GL_HALF_FLOAT_ARB:
return sizeof(GLhalfARB);
default:
diff --git a/src/mesa/main/imports.c b/src/mesa/main/imports.c
index 2ac93a5237..615f7c9a6d 100644
--- a/src/mesa/main/imports.c
+++ b/src/mesa/main/imports.c
@@ -980,7 +980,8 @@ _mesa_vsprintf( char *str, const char *fmt, va_list args )
/*@{*/
static void
-output_if_debug(const char *prefixString, const char *outputString)
+output_if_debug(const char *prefixString, const char *outputString,
+ GLboolean newline)
{
static int debug = -1;
@@ -1004,16 +1005,19 @@ output_if_debug(const char *prefixString, const char *outputString)
/* Now only print the string if we're required to do so. */
if (debug) {
- fprintf(stderr, "%s: %s\n", prefixString, outputString);
+ fprintf(stderr, "%s: %s", prefixString, outputString);
+ if (newline)
+ fprintf(stderr, "\n");
}
}
+
/**
* Report a warning (a recoverable error condition) to stderr if
* either DEBUG is defined or the MESA_DEBUG env var is set.
*
* \param ctx GL context.
- * \param fmtString printf() alike format string.
+ * \param fmtString printf()-like format string.
*/
void
_mesa_warning( GLcontext *ctx, const char *fmtString, ... )
@@ -1025,11 +1029,12 @@ _mesa_warning( GLcontext *ctx, const char *fmtString, ... )
(void) vsnprintf( str, MAXSTRING, fmtString, args );
va_end( args );
- output_if_debug("Mesa warning", str);
+ output_if_debug("Mesa warning", str, GL_TRUE);
}
+
/**
- * Report an internla implementation problem.
+ * Report an internal implementation problem.
* Prints the message to stderr via fprintf().
*
* \param ctx GL context.
@@ -1050,8 +1055,9 @@ _mesa_problem( const GLcontext *ctx, const char *fmtString, ... )
fprintf(stderr, "Please report at bugzilla.freedesktop.org\n");
}
+
/**
- * Record an OpenGL state error. These usually occur when the users
+ * Record an OpenGL state error. These usually occur when the user
* passes invalid parameters to a GL function.
*
* If debugging is enabled (either at compile-time via the DEBUG macro, or
@@ -1123,11 +1129,22 @@ _mesa_error( GLcontext *ctx, GLenum error, const char *fmtString, ... )
errstr = "unknown";
break;
}
- _mesa_debug(ctx, "User error: %s in %s\n", errstr, where);
+
+ {
+ char s[MAXSTRING], s2[MAXSTRING];
+ va_list args;
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+
+ _mesa_snprintf(s2, MAXSTRING, "%s in %s", errstr, s);
+ output_if_debug("Mesa: User error", s2, GL_TRUE);
+ }
}
_mesa_record_error(ctx, error);
-}
+}
+
/**
* Report debug information. Print error message to stderr via fprintf().
@@ -1145,7 +1162,7 @@ _mesa_debug( const GLcontext *ctx, const char *fmtString, ... )
va_start(args, fmtString);
vsnprintf(s, MAXSTRING, fmtString, args);
va_end(args);
- output_if_debug("Mesa", s);
+ output_if_debug("Mesa", s, GL_FALSE);
#endif /* DEBUG */
(void) ctx;
(void) fmtString;
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 30c7cca3b5..d11df535f2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -1028,7 +1028,7 @@ struct gl_stencil_attrib
/**
* An index for each type of texture object. These correspond to the GL
- * target target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
+ * texture target enums, such as GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, etc.
* Note: the order is from highest priority to lowest priority.
*/
typedef enum
@@ -1505,7 +1505,7 @@ struct gl_buffer_object
GLsizeiptr Length; /**< mapped length */
GLsizeiptrARB Size; /**< Size of storage in bytes */
GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
- GLboolean OnCard; /**< Is buffer in VRAM? (hardware drivers) */
+ GLboolean Written; /**< Ever written to? (for debugging) */
};
@@ -1541,10 +1541,10 @@ struct gl_client_array
const GLubyte *Ptr; /**< Points to array data */
GLboolean Enabled; /**< Enabled flag is a boolean */
GLboolean Normalized; /**< GL_ARB_vertex_program */
+ GLuint _ElementSize; /**< size of each element in bytes */
- /**< GL_ARB_vertex_buffer_object */
- struct gl_buffer_object *BufferObj;
- GLuint _MaxElement;
+ struct gl_buffer_object *BufferObj;/**< GL_ARB_vertex_buffer_object */
+ GLuint _MaxElement; /**< max element index into array buffer */
};
@@ -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;
@@ -1583,7 +1586,10 @@ struct gl_array_object
*/
struct gl_array_attrib
{
+ /** Currently bound array object. See _mesa_BindVertexArrayAPPLE() */
struct gl_array_object *ArrayObj;
+
+ /** The default vertex array object */
struct gl_array_object *DefaultArrayObj;
GLint ActiveTexture; /**< Client Active Texture */
@@ -1593,7 +1599,6 @@ struct gl_array_attrib
GLbitfield NewState; /**< mask of _NEW_ARRAY_* values */
#if FEATURE_ARB_vertex_buffer_object
- struct gl_buffer_object *NullBufferObj;
struct gl_buffer_object *ArrayBufferObj;
struct gl_buffer_object *ElementArrayBufferObj;
#endif
@@ -2050,6 +2055,9 @@ struct gl_shared_state
/** Default texture objects (shared by all texture units) */
struct gl_texture_object *DefaultTex[NUM_TEXTURE_TARGETS];
+ /** Fallback texture used when a bound texture is incomplete */
+ struct gl_texture_object *FallbackTex;
+
/**
* \name Thread safety and statechange notification for texture
* objects.
@@ -2061,6 +2069,8 @@ struct gl_shared_state
GLuint TextureStateStamp; /**< state notification for shared tex */
/*@}*/
+ /** Default buffer object for vertex arrays that aren't in VBOs */
+ struct gl_buffer_object *NullBufferObj;
/**
* \name Vertex/fragment programs
@@ -2616,6 +2626,7 @@ struct gl_matrix_stack
#define _NEW_PROGRAM 0x8000000 /**< __GLcontextRec::VertexProgram */
#define _NEW_CURRENT_ATTRIB 0x10000000 /**< __GLcontextRec::Current */
#define _NEW_PROGRAM_CONSTANTS 0x20000000
+#define _NEW_BUFFER_OBJECT 0x40000000
#define _NEW_ALL ~0
/*@}*/
@@ -2977,6 +2988,12 @@ struct __GLcontextRec
/** software compression/decompression supported or not */
GLboolean Mesa_DXTn;
+ /**
+ * Use dp4 (rather than mul/mad) instructions for position
+ * transformation?
+ */
+ GLboolean mvp_with_dp4;
+
/** Core tnl module support */
struct gl_tnl_module TnlModule;
diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c
index 52781e048e..d9f3e476e8 100644
--- a/src/mesa/main/pixel.c
+++ b/src/mesa/main/pixel.c
@@ -170,7 +170,7 @@ _mesa_PixelMapfv( GLenum map, GLsizei mapsize, const GLfloat *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
GL_READ_ONLY_ARB,
ctx->Unpack.BufferObj);
@@ -229,7 +229,7 @@ _mesa_PixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
GL_READ_ONLY_ARB,
ctx->Unpack.BufferObj);
@@ -303,7 +303,7 @@ _mesa_PixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
GL_READ_ONLY_ARB,
ctx->Unpack.BufferObj);
@@ -371,7 +371,7 @@ _mesa_GetPixelMapfv( GLenum map, GLfloat *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
GL_WRITE_ONLY_ARB,
ctx->Pack.BufferObj);
@@ -432,7 +432,7 @@ _mesa_GetPixelMapuiv( GLenum map, GLuint *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
GL_WRITE_ONLY_ARB,
ctx->Pack.BufferObj);
@@ -494,7 +494,7 @@ _mesa_GetPixelMapusv( GLenum map, GLushort *values )
return;
}
/* restore */
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ ctx->DefaultPacking.BufferObj = ctx->Shared->NullBufferObj;
buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
GL_WRITE_ONLY_ARB,
ctx->Pack.BufferObj);
@@ -819,7 +819,7 @@ update_image_transfer_state(GLcontext *ctx)
/**
- * Update meas pixel transfer derived state.
+ * Update mesa pixel transfer derived state.
*/
void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
{
diff --git a/src/mesa/main/pixelstore.c b/src/mesa/main/pixelstore.c
index ff1a6344cc..6a641f83f2 100644
--- a/src/mesa/main/pixelstore.c
+++ b/src/mesa/main/pixelstore.c
@@ -245,7 +245,8 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->Pack.ClientStorage = GL_FALSE;
ctx->Pack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->Pack.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->Pack.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
ctx->Unpack.Alignment = 4;
ctx->Unpack.RowLength = 0;
@@ -258,7 +259,8 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->Unpack.ClientStorage = GL_FALSE;
ctx->Unpack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->Unpack.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
/*
@@ -278,6 +280,7 @@ _mesa_init_pixelstore( GLcontext *ctx )
ctx->DefaultPacking.ClientStorage = GL_FALSE;
ctx->DefaultPacking.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
- ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &ctx->DefaultPacking.BufferObj,
+ ctx->Shared->NullBufferObj);
#endif
}
diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c
index 193ac8970c..759883743d 100644
--- a/src/mesa/main/shared.c
+++ b/src/mesa/main/shared.c
@@ -33,6 +33,7 @@
#include "mtypes.h"
#include "hash.h"
#include "arrayobj.h"
+#include "bufferobj.h"
#include "shared.h"
#include "shader/program.h"
#include "shader/shader_api.h"
@@ -92,6 +93,13 @@ _mesa_alloc_shared_state(GLcontext *ctx)
shared->BufferObjects = _mesa_NewHashTable();
#endif
+ /* 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.
+ */
+ shared->NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0);
+ shared->NullBufferObj->RefCount = 1000;
+
shared->ArrayObjects = _mesa_NewHashTable();
/* Create default texture objects */
@@ -190,6 +198,10 @@ delete_bufferobj_cb(GLuint id, void *data, void *userData)
{
struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data;
GLcontext *ctx = (GLcontext *) userData;
+ if (bufObj->Pointer) {
+ ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
+ bufObj->Pointer = NULL;
+ }
ctx->Driver.DeleteBuffer(ctx, bufObj);
}
@@ -337,6 +349,10 @@ _mesa_free_shared_state(GLcontext *ctx, struct gl_shared_state *shared)
_mesa_DeleteHashTable(shared->RenderBuffers);
#endif
+#if FEATURE_ARB_vertex_buffer_object
+ _mesa_delete_buffer_object(ctx, shared->NullBufferObj);
+#endif
+
/*
* Free texture objects (after FBOs since some textures might have
* been bound to FBOs).
diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c
index f18fc8f683..a6411f7b62 100644
--- a/src/mesa/main/state.c
+++ b/src/mesa/main/state.c
@@ -64,110 +64,145 @@ update_separate_specular(GLcontext *ctx)
/**
- * Update state dependent on vertex arrays.
+ * Compute the index of the last array element that can be safely accessed
+ * in a vertex array. We can really only do this when the array lives in
+ * a VBO.
+ * The array->_MaxElement field will be updated.
+ * Later in glDrawArrays/Elements/etc we can do some bounds checking.
+ */
+static void
+compute_max_element(struct gl_client_array *array)
+{
+ assert(array->Enabled);
+ if (array->BufferObj->Name) {
+ /* Compute the max element we can access in the VBO without going
+ * out of bounds.
+ */
+ array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size
+ - (GLsizeiptrARB) array->Ptr + array->StrideB
+ - array->_ElementSize) / array->StrideB;
+ }
+ else {
+ /* user-space array, no idea how big it is */
+ array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
+ }
+}
+
+
+/**
+ * Helper for update_arrays().
+ * \return min(current min, array->_MaxElement).
+ */
+static GLuint
+update_min(GLuint min, struct gl_client_array *array)
+{
+ compute_max_element(array);
+ return MIN2(min, array->_MaxElement);
+}
+
+
+/**
+ * Update ctx->Array._MaxElement (the max legal index into all enabled arrays).
+ * Need to do this upon new array state or new buffer object state.
*/
static void
update_arrays( GLcontext *ctx )
{
- GLuint i, min;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint i, min = ~0;
/* find min of _MaxElement values for all enabled arrays */
/* 0 */
if (ctx->VertexProgram._Current
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
- min = ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS]._MaxElement;
+ && arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
}
- else if (ctx->Array.ArrayObj->Vertex.Enabled) {
- min = ctx->Array.ArrayObj->Vertex._MaxElement;
- }
- else {
- /* can't draw anything without vertex positions! */
- min = 0;
+ else if (arrayObj->Vertex.Enabled) {
+ min = update_min(min, &arrayObj->Vertex);
}
/* 1 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_WEIGHT]);
}
/* no conventional vertex weight array */
/* 2 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
}
- else if (ctx->Array.ArrayObj->Normal.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Normal._MaxElement);
+ else if (arrayObj->Normal.Enabled) {
+ min = update_min(min, &arrayObj->Normal);
}
/* 3 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
}
- else if (ctx->Array.ArrayObj->Color.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Color._MaxElement);
+ else if (arrayObj->Color.Enabled) {
+ min = update_min(min, &arrayObj->Color);
}
/* 4 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]);
}
- else if (ctx->Array.ArrayObj->SecondaryColor.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->SecondaryColor._MaxElement);
+ else if (arrayObj->SecondaryColor.Enabled) {
+ min = update_min(min, &arrayObj->SecondaryColor);
}
/* 5 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]);
}
- else if (ctx->Array.ArrayObj->FogCoord.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->FogCoord._MaxElement);
+ else if (arrayObj->FogCoord.Enabled) {
+ min = update_min(min, &arrayObj->FogCoord);
}
/* 6 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]);
}
- else if (ctx->Array.ArrayObj->Index.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->Index._MaxElement);
+ else if (arrayObj->Index.Enabled) {
+ min = update_min(min, &arrayObj->Index);
}
-
/* 7 */
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]._MaxElement);
+ && arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]);
}
/* 8..15 */
for (i = VERT_ATTRIB_TEX0; i <= VERT_ATTRIB_TEX7; i++) {
if (ctx->VertexProgram._Enabled
- && ctx->Array.ArrayObj->VertexAttrib[i].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement);
+ && arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
}
else if (i - VERT_ATTRIB_TEX0 < ctx->Const.MaxTextureCoordUnits
- && ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->TexCoord[i - VERT_ATTRIB_TEX0]._MaxElement);
+ && arrayObj->TexCoord[i - VERT_ATTRIB_TEX0].Enabled) {
+ min = update_min(min, &arrayObj->TexCoord[i - VERT_ATTRIB_TEX0]);
}
}
/* 16..31 */
if (ctx->VertexProgram._Current) {
for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
- if (ctx->Array.ArrayObj->VertexAttrib[i].Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->VertexAttrib[i]._MaxElement);
+ if (arrayObj->VertexAttrib[i].Enabled) {
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
}
}
}
- if (ctx->Array.ArrayObj->EdgeFlag.Enabled) {
- min = MIN2(min, ctx->Array.ArrayObj->EdgeFlag._MaxElement);
+ if (arrayObj->EdgeFlag.Enabled) {
+ min = update_min(min, &arrayObj->EdgeFlag);
}
/* _MaxElement is one past the last legal array element */
@@ -547,7 +582,7 @@ _mesa_update_state_locked( GLcontext *ctx )
if (new_state & _DD_NEW_SEPARATE_SPECULAR)
update_separate_specular( ctx );
- if (new_state & (_NEW_ARRAY | _NEW_PROGRAM))
+ if (new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT))
update_arrays( ctx );
if (new_state & (_NEW_BUFFERS | _NEW_VIEWPORT))
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
index 8c03c36c75..76b46d700b 100644
--- a/src/mesa/main/teximage.c
+++ b/src/mesa/main/teximage.c
@@ -52,6 +52,17 @@
/**
+ * State changes which we care about for glCopyTex[Sub]Image() calls.
+ * In particular, we care about pixel transfer state and buffer state
+ * (such as glReadBuffer to make sure we read from the right renderbuffer).
+ */
+#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
+ _NEW_BUFFERS | \
+ _NEW_PIXEL)
+
+
+
+/**
* We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
* elsewhere.
*/
@@ -3008,7 +3019,7 @@ _mesa_CopyTexImage1D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
#if FEATURE_convolve
@@ -3073,7 +3084,7 @@ _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
#if FEATURE_convolve
@@ -3141,7 +3152,7 @@ _mesa_CopyTexSubImage1D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 1, target, level))
@@ -3196,7 +3207,7 @@ _mesa_CopyTexSubImage2D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 2, target, level))
@@ -3251,7 +3262,7 @@ _mesa_CopyTexSubImage3D( GLenum target, GLint level,
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
- if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
+ if (ctx->NewState & NEW_COPY_TEX_STATE)
_mesa_update_state(ctx);
if (copytexsubimage_error_check1(ctx, 3, target, level))
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
index b63f747fe8..0024efc0e6 100644
--- a/src/mesa/main/texobj.c
+++ b/src/mesa/main/texobj.c
@@ -662,6 +662,59 @@ _mesa_test_texobj_completeness( const GLcontext *ctx,
}
}
+
+/**
+ * Return pointer to a default/fallback texture.
+ * The texture is a 2D 8x8 RGBA texture with all texels = (0,0,0,1).
+ * That's the value a sampler should get when sampling from an
+ * incomplete texture.
+ */
+struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx)
+{
+ if (!ctx->Shared->FallbackTex) {
+ /* create fallback texture now */
+ static GLubyte texels[8 * 8][4];
+ struct gl_texture_object *texObj;
+ struct gl_texture_image *texImage;
+ GLuint i;
+
+ for (i = 0; i < 8 * 8; i++) {
+ texels[i][0] =
+ texels[i][1] =
+ texels[i][2] = 0x0;
+ texels[i][3] = 0xff;
+ }
+
+ /* create texture object */
+ texObj = ctx->Driver.NewTextureObject(ctx, 0, GL_TEXTURE_2D);
+ assert(texObj->RefCount == 1);
+ texObj->MinFilter = GL_NEAREST;
+ texObj->MagFilter = GL_NEAREST;
+
+ /* create level[0] texture image */
+ texImage = _mesa_get_tex_image(ctx, texObj, GL_TEXTURE_2D, 0);
+
+ /* init the image fields */
+ _mesa_init_teximage_fields(ctx, GL_TEXTURE_2D, texImage,
+ 8, 8, 1, 0, GL_RGBA);
+
+ /* set image data */
+ ctx->Driver.TexImage2D(ctx, GL_TEXTURE_2D, 0, GL_RGBA,
+ 8, 8, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, texels,
+ &ctx->DefaultPacking, texObj, texImage);
+
+ _mesa_test_texobj_completeness(ctx, texObj);
+ assert(texObj->_Complete);
+
+ ctx->Shared->FallbackTex = texObj;
+ }
+ return ctx->Shared->FallbackTex;
+}
+
+
+
/*@}*/
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
index d5374c5d6c..2599c0816a 100644
--- a/src/mesa/main/texobj.h
+++ b/src/mesa/main/texobj.h
@@ -65,6 +65,9 @@ extern void
_mesa_test_texobj_completeness( const GLcontext *ctx,
struct gl_texture_object *obj );
+extern struct gl_texture_object *
+_mesa_get_fallback_texture(GLcontext *ctx);
+
extern void
_mesa_unlock_context_textures( GLcontext *ctx );
diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c
index 515a35cdfc..2195a334d3 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -69,7 +69,7 @@ validate_texture_wrap_mode(GLcontext * ctx, GLenum target, GLenum wrap)
return GL_TRUE;
}
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)", wrap );
return GL_FALSE;
}
@@ -209,7 +209,8 @@ set_tex_parameteri(GLcontext *ctx,
}
/* fall-through */
default:
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+ params[0] );
}
return GL_FALSE;
@@ -223,7 +224,8 @@ set_tex_parameteri(GLcontext *ctx,
texObj->MagFilter = params[0];
return GL_TRUE;
default:
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexParameter(param=0x%x)",
+ params[0]);
}
return GL_FALSE;
@@ -262,7 +264,8 @@ set_tex_parameteri(GLcontext *ctx,
return GL_FALSE;
if (params[0] < 0 ||
(texObj->Target == GL_TEXTURE_RECTANGLE_ARB && params[0] != 0)) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)");
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glTexParameter(param=%d)", params[0]);
return GL_FALSE;
}
flush(ctx, texObj);
@@ -273,7 +276,8 @@ set_tex_parameteri(GLcontext *ctx,
if (texObj->MaxLevel == params[0])
return GL_FALSE;
if (params[0] < 0 || texObj->Target == GL_TEXTURE_RECTANGLE_ARB) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glTexParameter(param)");
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glTexParameter(param=%d)", params[0]);
return GL_FALSE;
}
flush(ctx, texObj);
@@ -340,7 +344,7 @@ set_tex_parameteri(GLcontext *ctx,
}
}
else {
- _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(param)");
+ _mesa_error(ctx, GL_INVALID_ENUM, "glTexParameter(pname=0x%x)", pname);
}
return GL_FALSE;
@@ -465,8 +469,10 @@ set_tex_parameterf(GLcontext *ctx,
return GL_TRUE;
}
else {
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
+ static GLuint count = 0;
+ if (count++ < 10)
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glTexParameter(pname=GL_TEXTURE_MAX_ANISOTROPY_EXT)");
}
return GL_FALSE;
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
index 73f8a5339e..6e0c0c688a 100644
--- a/src/mesa/main/texstate.c
+++ b/src/mesa/main/texstate.c
@@ -561,8 +561,19 @@ update_texture_state( GLcontext *ctx )
}
if (!texUnit->_ReallyEnabled) {
- _mesa_reference_texobj(&texUnit->_Current, NULL);
- continue;
+ if (fprog) {
+ /* If we get here it means the shader is expecting a texture
+ * object, but there isn't one (or it's incomplete). Use the
+ * fallback texture.
+ */
+ struct gl_texture_object *texObj = _mesa_get_fallback_texture(ctx);
+ texUnit->_ReallyEnabled = 1 << TEXTURE_2D_INDEX;
+ _mesa_reference_texobj(&texUnit->_Current, texObj);
+ }
+ else {
+ /* fixed-function: texture unit is really disabled */
+ continue;
+ }
}
/* if we get here, we know this texture unit is enabled */
@@ -780,6 +791,9 @@ _mesa_free_texture_data(GLcontext *ctx)
/* unreference current textures */
for (u = 0; u < MAX_TEXTURE_IMAGE_UNITS; u++) {
+ /* The _Current texture could account for another reference */
+ _mesa_reference_texobj(&ctx->Texture.Unit[u]._Current, NULL);
+
for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) {
_mesa_reference_texobj(&ctx->Texture.Unit[u].CurrentTex[tgt], NULL);
}
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 106252e460..a9c9162be1 100644
--- a/src/mesa/main/varray.c
+++ b/src/mesa/main/varray.c
@@ -63,22 +63,11 @@ update_array(GLcontext *ctx, struct gl_client_array *array,
array->StrideB = stride ? stride : elementSize;
array->Normalized = normalized;
array->Ptr = (const GLubyte *) ptr;
-#if FEATURE_ARB_vertex_buffer_object
+ array->_ElementSize = elementSize;
+
_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.
- */
- if (ctx->Array.ArrayBufferObj->Name)
- array->_MaxElement = ((GLsizeiptrARB) ctx->Array.ArrayBufferObj->Size
- - (GLsizeiptrARB) array->Ptr + array->StrideB
- - elementSize) / array->StrideB;
- else
-#endif
- array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */
-
ctx->NewState |= _NEW_ARRAY;
ctx->Array.NewState |= dirtyBit;
}
@@ -1050,7 +1039,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 */
}
diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h
index f5bf6e2c85..d4d3dd1a94 100644
--- a/src/mesa/main/version.h
+++ b/src/mesa/main/version.h
@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
- * Version: 7.5
+ * Version: 7.6
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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"),
@@ -29,9 +30,9 @@
/* Mesa version */
#define MESA_MAJOR 7
-#define MESA_MINOR 5
+#define MESA_MINOR 6
#define MESA_PATCH 0
-#define MESA_VERSION_STRING "7.5-devel"
+#define MESA_VERSION_STRING "7.6-devel"
/* To make version comparison easy */
#define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))