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.c17
-rw-r--r--src/mesa/main/arrayobj.h6
-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.c8
-rw-r--r--src/mesa/main/enable.c8
-rw-r--r--src/mesa/main/fbobject.c5
-rw-r--r--src/mesa/main/image.c2
-rw-r--r--src/mesa/main/mipmap.c7
-rw-r--r--src/mesa/main/mtypes.h20
-rw-r--r--src/mesa/main/pixel.c12
-rw-r--r--src/mesa/main/pixelstore.c9
-rw-r--r--src/mesa/main/shared.c12
-rw-r--r--src/mesa/main/state.c123
-rw-r--r--src/mesa/main/texobj.c53
-rw-r--r--src/mesa/main/texobj.h3
-rw-r--r--src/mesa/main/texparam.c6
-rw-r--r--src/mesa/main/texstate.c15
-rw-r--r--src/mesa/main/varray.c15
-rw-r--r--src/mesa/main/version.h7
22 files changed, 286 insertions, 161 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 0fa5f0de55..8ec73b9526 100644
--- a/src/mesa/main/arrayobj.c
+++ b/src/mesa/main/arrayobj.c
@@ -198,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
}
@@ -242,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 */
@@ -256,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 */
@@ -311,7 +312,7 @@ _mesa_BindVertexArrayAPPLE( GLuint id )
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
return;
}
- _mesa_save_array_object(ctx, newObj);
+ save_array_object(ctx, newObj);
}
}
@@ -360,7 +361,7 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
}
/* The ID is immediately freed for re-use */
- _mesa_remove_array_object(ctx, obj);
+ remove_array_object(ctx, obj);
/* Unreference the array object.
* If refcount hits zero, the object will be deleted.
@@ -414,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 9c4036af5a..90c2aea155 100644
--- a/src/mesa/main/arrayobj.h
+++ b/src/mesa/main/arrayobj.h
@@ -56,12 +56,6 @@ extern void
_mesa_initialize_array_object( GLcontext *ctx,
struct gl_array_object *obj, GLuint name );
-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/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 ec0dc12a3e..5e0f2d7b1b 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -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);
}
@@ -1007,10 +1011,6 @@ _mesa_free_context_data( GLcontext *ctx )
_mesa_delete_array_object(ctx, ctx->Array.DefaultArrayObj);
-#if FEATURE_ARB_vertex_buffer_object
- _mesa_delete_buffer_object(ctx, ctx->Array.NullBufferObj);
-#endif
-
/* free dispatch tables */
_mesa_free(ctx->Exec);
_mesa_free(ctx->Save);
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/fbobject.c b/src/mesa/main/fbobject.c
index 9c5a5908a2..dbd4c5848c 100644
--- a/src/mesa/main/fbobject.c
+++ b/src/mesa/main/fbobject.c
@@ -368,6 +368,11 @@ test_attachment_completeness(const GLcontext *ctx, GLenum format,
att->Complete = GL_FALSE;
return;
}
+ if (texImage->TexFormat->TexelBytes == 0) {
+ att_incomplete("compressed internalformat");
+ att->Complete = GL_FALSE;
+ return;
+ }
}
else if (format == GL_DEPTH) {
if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
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/mipmap.c b/src/mesa/main/mipmap.c
index 7a719745fc..872982fa43 100644
--- a/src/mesa/main/mipmap.c
+++ b/src/mesa/main/mipmap.c
@@ -1481,9 +1481,12 @@ next_mipmap_level_size(GLenum target, GLint border,
/**
- * For GL_SGIX_generate_mipmap:
- * Generate a complete set of mipmaps from texObj's base-level image.
+ * Automatic mipmap generation.
+ * This is the fallback/default function for ctx->Driver.GenerateMipmap().
+ * Generate a complete set of mipmaps from texObj's BaseLevel image.
* Stop at texObj's MaxLevel or when we get to the 1x1 texture.
+ * For cube maps, target will be one of
+ * GL_TEXTURE_CUBE_MAP_POSITIVE/NEGATIVE_X/Y/Z; never GL_TEXTURE_CUBE_MAP.
*/
void
_mesa_generate_mipmap(GLcontext *ctx, GLenum target,
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 50dc2def87..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 */
};
@@ -1586,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 */
@@ -1596,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
@@ -2053,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.
@@ -2064,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
@@ -2619,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
/*@}*/
diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c
index 57ae9c721a..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);
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 ae8dd2a836..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 */
@@ -341,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/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 e60ab6aa12..2195a334d3 100644
--- a/src/mesa/main/texparam.c
+++ b/src/mesa/main/texparam.c
@@ -469,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 cef58d7a49..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 */
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
index 72b3e834b3..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;
}
diff --git a/src/mesa/main/version.h b/src/mesa/main/version.h
index e109f20df4..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-rc2"
+#define MESA_VERSION_STRING "7.6-devel"
/* To make version comparison easy */
#define MESA_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))