diff options
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r-- | mesalib/src/mesa/main/arrayobj.c | 1157 | ||||
-rw-r--r-- | mesalib/src/mesa/main/bufferobj.c | 70 | ||||
-rw-r--r-- | mesalib/src/mesa/main/clip.c | 28 | ||||
-rw-r--r-- | mesalib/src/mesa/main/clip.h | 5 | ||||
-rw-r--r-- | mesalib/src/mesa/main/dd.h | 9 | ||||
-rw-r--r-- | mesalib/src/mesa/main/enable.c | 2912 | ||||
-rw-r--r-- | mesalib/src/mesa/main/fog.c | 21 | ||||
-rw-r--r-- | mesalib/src/mesa/main/imports.c | 2062 | ||||
-rw-r--r-- | mesalib/src/mesa/main/matrix.c | 39 | ||||
-rw-r--r-- | mesalib/src/mesa/main/readpix.c | 488 | ||||
-rw-r--r-- | mesalib/src/mesa/main/shaderobj.c | 1 | ||||
-rw-r--r-- | mesalib/src/mesa/main/texenv.c | 33 |
12 files changed, 3384 insertions, 3441 deletions
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 460102233..1033ce639 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -1,578 +1,579 @@ -/* - * Mesa 3-D graphics library - * Version: 7.6 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * (C) Copyright IBM Corporation 2006 - * 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"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL OR IBM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF - * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - -/** - * \file arrayobj.c - * Functions for the GL_APPLE_vertex_array_object extension. - * - * \todo - * The code in this file borrows a lot from bufferobj.c. There's a certain - * amount of cruft left over from that origin that may be unnecessary. - * - * \author Ian Romanick <idr@us.ibm.com> - * \author Brian Paul - */ - - -#include "glheader.h" -#include "hash.h" -#include "imports.h" -#include "context.h" -#include "mfeatures.h" -#if FEATURE_ARB_vertex_buffer_object -#include "bufferobj.h" -#endif -#include "arrayobj.h" -#include "macros.h" -#include "mtypes.h" -#include "main/dispatch.h" - - -/** - * Look up the array object for the given ID. - * - * \returns - * Either a pointer to the array object with the specified ID or \c NULL for - * a non-existent ID. The spec defines ID 0 as being technically - * non-existent. - */ - -static INLINE struct gl_array_object * -lookup_arrayobj(struct gl_context *ctx, GLuint id) -{ - if (id == 0) - return NULL; - else - return (struct gl_array_object *) - _mesa_HashLookup(ctx->Array.Objects, 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(struct gl_context *ctx, struct gl_array_object *obj) -{ - GLuint i; - - _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL); - _mesa_reference_buffer_object(ctx, &obj->Weight.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 < Elements(obj->TexCoord); i++) - _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL); - - for (i = 0; i < Elements(obj->VertexAttrib); i++) - _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL); - -#if FEATURE_point_size_array - _mesa_reference_buffer_object(ctx, &obj->PointSize.BufferObj, NULL); -#endif -} - - -/** - * Allocate and initialize a new vertex array object. - * - * This function is intended to be called via - * \c dd_function_table::NewArrayObject. - */ -struct gl_array_object * -_mesa_new_array_object( struct gl_context *ctx, GLuint name ) -{ - struct gl_array_object *obj = CALLOC_STRUCT(gl_array_object); - if (obj) - _mesa_initialize_array_object(ctx, obj, name); - return obj; -} - - -/** - * Delete an array object. - * - * This function is intended to be called via - * \c dd_function_table::DeleteArrayObject. - */ -void -_mesa_delete_array_object( struct gl_context *ctx, struct gl_array_object *obj ) -{ - (void) ctx; - unbind_array_object_vbos(ctx, obj); - _glthread_DESTROY_MUTEX(obj->Mutex); - free(obj); -} - - -/** - * Set ptr to arrayObj w/ reference counting. - */ -void -_mesa_reference_array_object(struct gl_context *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(struct gl_context *ctx, - struct gl_client_array *array, GLint size, GLint type) -{ - array->Size = size; - array->Type = type; - array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ - array->Stride = 0; - array->StrideB = 0; - array->Ptr = NULL; - array->Enabled = GL_FALSE; - array->Normalized = GL_FALSE; -#if FEATURE_ARB_vertex_buffer_object - /* Vertex array buffers */ - _mesa_reference_buffer_object(ctx, &array->BufferObj, - ctx->Shared->NullBufferObj); -#endif -} - - -/** - * Initialize a gl_array_object's arrays. - */ -void -_mesa_initialize_array_object( struct gl_context *ctx, - struct gl_array_object *obj, - GLuint name ) -{ - GLuint i; - - 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->Weight, 1, GL_FLOAT); - init_array(ctx, &obj->Normal, 3, GL_FLOAT); - init_array(ctx, &obj->Color, 4, GL_FLOAT); - init_array(ctx, &obj->SecondaryColor, 3, GL_FLOAT); - init_array(ctx, &obj->FogCoord, 1, GL_FLOAT); - init_array(ctx, &obj->Index, 1, GL_FLOAT); - for (i = 0; i < Elements(obj->TexCoord); i++) { - init_array(ctx, &obj->TexCoord[i], 4, GL_FLOAT); - } - init_array(ctx, &obj->EdgeFlag, 1, GL_BOOL); - for (i = 0; i < Elements(obj->VertexAttrib); i++) { - init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT); - } - -#if FEATURE_point_size_array - init_array(ctx, &obj->PointSize, 1, GL_FLOAT); -#endif -} - - -/** - * Add the given array object to the array object pool. - */ -static void -save_array_object( struct gl_context *ctx, struct gl_array_object *obj ) -{ - if (obj->Name > 0) { - /* insert into hash table */ - _mesa_HashInsert(ctx->Array.Objects, obj->Name, obj); - } -} - - -/** - * Remove the given array object from the array object pool. - * Do not deallocate the array object though. - */ -static void -remove_array_object( struct gl_context *ctx, struct gl_array_object *obj ) -{ - if (obj->Name > 0) { - /* remove from hash table */ - _mesa_HashRemove(ctx->Array.Objects, obj->Name); - } -} - - - -/** - * 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) -{ - 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; - if (0) - printf("%s Object %u Size %u MaxElement %u\n", - __FUNCTION__, - array->BufferObj->Name, - (GLuint) array->BufferObj->Size, - array->_MaxElement); - } - 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); - if (array->Enabled) - return MIN2(min, array->_MaxElement); - else - return min; -} - - -/** - * Examine vertex arrays to update the gl_array_object::_MaxElement field. - */ -void -_mesa_update_array_object_max_element(struct gl_context *ctx, - struct gl_array_object *arrayObj) -{ - GLuint i, min = ~0; - - min = update_min(min, &arrayObj->Vertex); - min = update_min(min, &arrayObj->Weight); - min = update_min(min, &arrayObj->Normal); - min = update_min(min, &arrayObj->Color); - min = update_min(min, &arrayObj->SecondaryColor); - min = update_min(min, &arrayObj->FogCoord); - min = update_min(min, &arrayObj->Index); - min = update_min(min, &arrayObj->EdgeFlag); -#if FEATURE_point_size_array - min = update_min(min, &arrayObj->PointSize); -#endif - for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) - min = update_min(min, &arrayObj->TexCoord[i]); - for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) - min = update_min(min, &arrayObj->VertexAttrib[i]); - - /* _MaxElement is one past the last legal array element */ - arrayObj->_MaxElement = min; -} - - -/**********************************************************************/ -/* API Functions */ -/**********************************************************************/ - - -/** - * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE(). - * \param genRequired specifies behavour when id was not generated with - * glGenVertexArrays(). - */ -static void -bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired) -{ - struct gl_array_object * const oldObj = ctx->Array.ArrayObj; - struct gl_array_object *newObj = NULL; - ASSERT_OUTSIDE_BEGIN_END(ctx); - - ASSERT(oldObj != NULL); - - if ( oldObj->Name == id ) - return; /* rebinding the same array object- no change */ - - /* - * Get pointer to new array object (newObj) - */ - if (id == 0) { - /* The spec says there is no array object named 0, but we use - * one internally because it simplifies things. - */ - newObj = ctx->Array.DefaultArrayObj; - } - else { - /* non-default array object */ - newObj = lookup_arrayobj(ctx, id); - if (!newObj) { - if (genRequired) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)"); - return; - } - - /* For APPLE version, generate a new array object now */ - newObj = (*ctx->Driver.NewArrayObject)(ctx, id); - if (!newObj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); - return; - } - save_array_object(ctx, newObj); - } - } - - ctx->NewState |= _NEW_ARRAY; - ctx->Array.NewState |= _NEW_ARRAY_ALL; - _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj); - - /* Pass BindVertexArray call to device driver */ - if (ctx->Driver.BindArrayObject && newObj) - ctx->Driver.BindArrayObject(ctx, newObj); -} - - -/** - * ARB version of glBindVertexArray() - * This function behaves differently from glBindVertexArrayAPPLE() in - * that this function requires all ids to have been previously generated - * by glGenVertexArrays[APPLE](). - */ -void GLAPIENTRY -_mesa_BindVertexArray( GLuint id ) -{ - GET_CURRENT_CONTEXT(ctx); - bind_vertex_array(ctx, id, GL_TRUE); -} - - -/** - * Bind a new array. - * - * \todo - * The binding could be done more efficiently by comparing the non-NULL - * pointers in the old and new objects. The only arrays that are "dirty" are - * the ones that are non-NULL in either object. - */ -void GLAPIENTRY -_mesa_BindVertexArrayAPPLE( GLuint id ) -{ - GET_CURRENT_CONTEXT(ctx); - bind_vertex_array(ctx, id, GL_FALSE); -} - - -/** - * Delete a set of array objects. - * - * \param n Number of array objects to delete. - * \param ids Array of \c n array object IDs. - */ -void GLAPIENTRY -_mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) -{ - GET_CURRENT_CONTEXT(ctx); - GLsizei i; - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArrayAPPLE(n)"); - return; - } - - for (i = 0; i < n; i++) { - struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]); - - 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." - */ - if ( obj == ctx->Array.ArrayObj ) { - CALL_BindVertexArrayAPPLE( ctx->Exec, (0) ); - } - - /* The ID is immediately freed for re-use */ - 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); - } - } -} - - -/** - * Generate a set of unique array object IDs and store them in \c arrays. - * Helper for _mesa_GenVertexArrays[APPLE]() functions below. - * \param n Number of IDs to generate. - * \param arrays Array of \c n locations to store the IDs. - * \param vboOnly Will arrays have to reside in VBOs? - */ -static void -gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays, GLboolean vboOnly) -{ - GLuint first; - GLint i; - ASSERT_OUTSIDE_BEGIN_END(ctx); - - if (n < 0) { - _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE"); - return; - } - - if (!arrays) { - return; - } - - first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n); - - /* Allocate new, empty array objects and return identifiers */ - for (i = 0; i < n; i++) { - struct gl_array_object *obj; - GLuint name = first + i; - - obj = (*ctx->Driver.NewArrayObject)( ctx, name ); - if (!obj) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); - return; - } - obj->VBOonly = vboOnly; - save_array_object(ctx, obj); - arrays[i] = first + i; - } -} - - -/** - * ARB version of glGenVertexArrays() - * All arrays will be required to live in VBOs. - */ -void GLAPIENTRY -_mesa_GenVertexArrays(GLsizei n, GLuint *arrays) -{ - GET_CURRENT_CONTEXT(ctx); - gen_vertex_arrays(ctx, n, arrays, GL_TRUE); -} - - -/** - * APPLE version of glGenVertexArraysAPPLE() - * Arrays may live in VBOs or ordinary memory. - */ -void GLAPIENTRY -_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) -{ - GET_CURRENT_CONTEXT(ctx); - gen_vertex_arrays(ctx, n, arrays, GL_FALSE); -} - - -/** - * Determine if ID is the name of an array object. - * - * \param id ID of the potential array object. - * \return \c GL_TRUE if \c id is the name of a array object, - * \c GL_FALSE otherwise. - */ -GLboolean GLAPIENTRY -_mesa_IsVertexArrayAPPLE( GLuint id ) -{ - struct gl_array_object * obj; - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - - if (id == 0) - return GL_FALSE; - - obj = lookup_arrayobj(ctx, id); - - return (obj != NULL) ? GL_TRUE : GL_FALSE; -} +/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * (C) Copyright IBM Corporation 2006
+ * 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"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL OR IBM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+/**
+ * \file arrayobj.c
+ * Functions for the GL_APPLE_vertex_array_object extension.
+ *
+ * \todo
+ * The code in this file borrows a lot from bufferobj.c. There's a certain
+ * amount of cruft left over from that origin that may be unnecessary.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ * \author Brian Paul
+ */
+
+
+#include "glheader.h"
+#include "hash.h"
+#include "imports.h"
+#include "context.h"
+#include "mfeatures.h"
+#if FEATURE_ARB_vertex_buffer_object
+#include "bufferobj.h"
+#endif
+#include "arrayobj.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "main/dispatch.h"
+
+
+/**
+ * Look up the array object for the given ID.
+ *
+ * \returns
+ * Either a pointer to the array object with the specified ID or \c NULL for
+ * a non-existent ID. The spec defines ID 0 as being technically
+ * non-existent.
+ */
+
+static INLINE struct gl_array_object *
+lookup_arrayobj(struct gl_context *ctx, GLuint id)
+{
+ if (id == 0)
+ return NULL;
+ else
+ return (struct gl_array_object *)
+ _mesa_HashLookup(ctx->Array.Objects, 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(struct gl_context *ctx, struct gl_array_object *obj)
+{
+ GLuint i;
+
+ _mesa_reference_buffer_object(ctx, &obj->Vertex.BufferObj, NULL);
+ _mesa_reference_buffer_object(ctx, &obj->Weight.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 < Elements(obj->TexCoord); i++)
+ _mesa_reference_buffer_object(ctx, &obj->TexCoord[i].BufferObj, NULL);
+
+ for (i = 0; i < Elements(obj->VertexAttrib); i++)
+ _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj,NULL);
+
+#if FEATURE_point_size_array
+ _mesa_reference_buffer_object(ctx, &obj->PointSize.BufferObj, NULL);
+#endif
+}
+
+
+/**
+ * Allocate and initialize a new vertex array object.
+ *
+ * This function is intended to be called via
+ * \c dd_function_table::NewArrayObject.
+ */
+struct gl_array_object *
+_mesa_new_array_object( struct gl_context *ctx, GLuint name )
+{
+ struct gl_array_object *obj = CALLOC_STRUCT(gl_array_object);
+ if (obj)
+ _mesa_initialize_array_object(ctx, obj, name);
+ return obj;
+}
+
+
+/**
+ * Delete an array object.
+ *
+ * This function is intended to be called via
+ * \c dd_function_table::DeleteArrayObject.
+ */
+void
+_mesa_delete_array_object( struct gl_context *ctx, struct gl_array_object *obj )
+{
+ (void) ctx;
+ unbind_array_object_vbos(ctx, obj);
+ _glthread_DESTROY_MUTEX(obj->Mutex);
+ free(obj);
+}
+
+
+/**
+ * Set ptr to arrayObj w/ reference counting.
+ */
+void
+_mesa_reference_array_object(struct gl_context *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(struct gl_context *ctx,
+ struct gl_client_array *array, GLint size, GLint type)
+{
+ array->Size = size;
+ array->Type = type;
+ array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
+ array->Stride = 0;
+ array->StrideB = 0;
+ array->Ptr = NULL;
+ array->Enabled = GL_FALSE;
+ array->Normalized = GL_FALSE;
+#if FEATURE_ARB_vertex_buffer_object
+ /* Vertex array buffers */
+ _mesa_reference_buffer_object(ctx, &array->BufferObj,
+ ctx->Shared->NullBufferObj);
+#endif
+}
+
+
+/**
+ * Initialize a gl_array_object's arrays.
+ */
+void
+_mesa_initialize_array_object( struct gl_context *ctx,
+ struct gl_array_object *obj,
+ GLuint name )
+{
+ GLuint i;
+
+ 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->Weight, 1, GL_FLOAT);
+ init_array(ctx, &obj->Normal, 3, GL_FLOAT);
+ init_array(ctx, &obj->Color, 4, GL_FLOAT);
+ init_array(ctx, &obj->SecondaryColor, 3, GL_FLOAT);
+ init_array(ctx, &obj->FogCoord, 1, GL_FLOAT);
+ init_array(ctx, &obj->Index, 1, GL_FLOAT);
+ for (i = 0; i < Elements(obj->TexCoord); i++) {
+ init_array(ctx, &obj->TexCoord[i], 4, GL_FLOAT);
+ }
+ init_array(ctx, &obj->EdgeFlag, 1, GL_BOOL);
+ for (i = 0; i < Elements(obj->VertexAttrib); i++) {
+ init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT);
+ }
+
+#if FEATURE_point_size_array
+ init_array(ctx, &obj->PointSize, 1, GL_FLOAT);
+#endif
+}
+
+
+/**
+ * Add the given array object to the array object pool.
+ */
+static void
+save_array_object( struct gl_context *ctx, struct gl_array_object *obj )
+{
+ if (obj->Name > 0) {
+ /* insert into hash table */
+ _mesa_HashInsert(ctx->Array.Objects, obj->Name, obj);
+ }
+}
+
+
+/**
+ * Remove the given array object from the array object pool.
+ * Do not deallocate the array object though.
+ */
+static void
+remove_array_object( struct gl_context *ctx, struct gl_array_object *obj )
+{
+ if (obj->Name > 0) {
+ /* remove from hash table */
+ _mesa_HashRemove(ctx->Array.Objects, obj->Name);
+ }
+}
+
+
+
+/**
+ * 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)
+{
+ 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;
+ if (0)
+ printf("%s Object %u Size %u MaxElement %u\n",
+ __FUNCTION__,
+ array->BufferObj->Name,
+ (GLuint) array->BufferObj->Size,
+ array->_MaxElement);
+ }
+ 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);
+ if (array->Enabled)
+ return MIN2(min, array->_MaxElement);
+ else
+ return min;
+}
+
+
+/**
+ * Examine vertex arrays to update the gl_array_object::_MaxElement field.
+ */
+void
+_mesa_update_array_object_max_element(struct gl_context *ctx,
+ struct gl_array_object *arrayObj)
+{
+ GLuint i, min = ~0;
+
+ min = update_min(min, &arrayObj->Vertex);
+ min = update_min(min, &arrayObj->Weight);
+ min = update_min(min, &arrayObj->Normal);
+ min = update_min(min, &arrayObj->Color);
+ min = update_min(min, &arrayObj->SecondaryColor);
+ min = update_min(min, &arrayObj->FogCoord);
+ min = update_min(min, &arrayObj->Index);
+ min = update_min(min, &arrayObj->EdgeFlag);
+#if FEATURE_point_size_array
+ min = update_min(min, &arrayObj->PointSize);
+#endif
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
+ min = update_min(min, &arrayObj->TexCoord[i]);
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++)
+ min = update_min(min, &arrayObj->VertexAttrib[i]);
+
+ /* _MaxElement is one past the last legal array element */
+ arrayObj->_MaxElement = min;
+}
+
+
+/**********************************************************************/
+/* API Functions */
+/**********************************************************************/
+
+
+/**
+ * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE().
+ * \param genRequired specifies behavour when id was not generated with
+ * glGenVertexArrays().
+ */
+static void
+bind_vertex_array(struct gl_context *ctx, GLuint id, GLboolean genRequired)
+{
+ struct gl_array_object * const oldObj = ctx->Array.ArrayObj;
+ struct gl_array_object *newObj = NULL;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ ASSERT(oldObj != NULL);
+
+ if ( oldObj->Name == id )
+ return; /* rebinding the same array object- no change */
+
+ /*
+ * Get pointer to new array object (newObj)
+ */
+ if (id == 0) {
+ /* The spec says there is no array object named 0, but we use
+ * one internally because it simplifies things.
+ */
+ newObj = ctx->Array.DefaultArrayObj;
+ }
+ else {
+ /* non-default array object */
+ newObj = lookup_arrayobj(ctx, id);
+ if (!newObj) {
+ if (genRequired) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)");
+ return;
+ }
+
+ /* For APPLE version, generate a new array object now */
+ newObj = (*ctx->Driver.NewArrayObject)(ctx, id);
+ if (!newObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE");
+ return;
+ }
+ save_array_object(ctx, newObj);
+ }
+ }
+
+ ctx->NewState |= _NEW_ARRAY;
+ ctx->Array.NewState |= _NEW_ARRAY_ALL;
+ _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj);
+
+ /* Pass BindVertexArray call to device driver */
+ if (ctx->Driver.BindArrayObject && newObj)
+ ctx->Driver.BindArrayObject(ctx, newObj);
+}
+
+
+/**
+ * ARB version of glBindVertexArray()
+ * This function behaves differently from glBindVertexArrayAPPLE() in
+ * that this function requires all ids to have been previously generated
+ * by glGenVertexArrays[APPLE]().
+ */
+void GLAPIENTRY
+_mesa_BindVertexArray( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_TRUE);
+}
+
+
+/**
+ * Bind a new array.
+ *
+ * \todo
+ * The binding could be done more efficiently by comparing the non-NULL
+ * pointers in the old and new objects. The only arrays that are "dirty" are
+ * the ones that are non-NULL in either object.
+ */
+void GLAPIENTRY
+_mesa_BindVertexArrayAPPLE( GLuint id )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ bind_vertex_array(ctx, id, GL_FALSE);
+}
+
+
+/**
+ * Delete a set of array objects.
+ *
+ * \param n Number of array objects to delete.
+ * \param ids Array of \c n array object IDs.
+ */
+void GLAPIENTRY
+_mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteVertexArrayAPPLE(n)");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ struct gl_array_object *obj = lookup_arrayobj(ctx, ids[i]);
+
+ 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."
+ */
+ if ( obj == ctx->Array.ArrayObj ) {
+ CALL_BindVertexArrayAPPLE( ctx->Exec, (0) );
+ }
+
+ /* The ID is immediately freed for re-use */
+ 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);
+ }
+ }
+}
+
+
+/**
+ * Generate a set of unique array object IDs and store them in \c arrays.
+ * Helper for _mesa_GenVertexArrays[APPLE]() functions below.
+ * \param n Number of IDs to generate.
+ * \param arrays Array of \c n locations to store the IDs.
+ * \param vboOnly Will arrays have to reside in VBOs?
+ */
+static void
+gen_vertex_arrays(struct gl_context *ctx, GLsizei n, GLuint *arrays,
+ GLboolean vboOnly)
+{
+ GLuint first;
+ GLint i;
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGenVertexArraysAPPLE");
+ return;
+ }
+
+ if (!arrays) {
+ return;
+ }
+
+ first = _mesa_HashFindFreeKeyBlock(ctx->Array.Objects, n);
+
+ /* Allocate new, empty array objects and return identifiers */
+ for (i = 0; i < n; i++) {
+ struct gl_array_object *obj;
+ GLuint name = first + i;
+
+ obj = (*ctx->Driver.NewArrayObject)( ctx, name );
+ if (!obj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE");
+ return;
+ }
+ obj->VBOonly = vboOnly;
+ save_array_object(ctx, obj);
+ arrays[i] = first + i;
+ }
+}
+
+
+/**
+ * ARB version of glGenVertexArrays()
+ * All arrays will be required to live in VBOs.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArrays(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_TRUE);
+}
+
+
+/**
+ * APPLE version of glGenVertexArraysAPPLE()
+ * Arrays may live in VBOs or ordinary memory.
+ */
+void GLAPIENTRY
+_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ gen_vertex_arrays(ctx, n, arrays, GL_FALSE);
+}
+
+
+/**
+ * Determine if ID is the name of an array object.
+ *
+ * \param id ID of the potential array object.
+ * \return \c GL_TRUE if \c id is the name of a array object,
+ * \c GL_FALSE otherwise.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsVertexArrayAPPLE( GLuint id )
+{
+ struct gl_array_object * obj;
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE);
+
+ if (id == 0)
+ return GL_FALSE;
+
+ obj = lookup_arrayobj(ctx, id);
+
+ return (obj != NULL) ? GL_TRUE : GL_FALSE;
+}
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index d5d0c9072..f67c04f7a 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -216,7 +216,8 @@ _mesa_new_buffer_object( struct gl_context *ctx, GLuint name, GLenum target ) * Default callback for the \c dd_function_table::DeleteBuffer() hook.
*/
static void
-_mesa_delete_buffer_object( struct gl_context *ctx, struct gl_buffer_object *bufObj )
+_mesa_delete_buffer_object(struct gl_context *ctx,
+ struct gl_buffer_object *bufObj)
{
(void) ctx;
@@ -414,7 +415,8 @@ _mesa_buffer_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset, * \sa glBufferGetSubDataARB, dd_function_table::GetBufferSubData.
*/
static void
-_mesa_buffer_get_subdata( struct gl_context *ctx, GLenum target, GLintptrARB offset,
+_mesa_buffer_get_subdata( struct gl_context *ctx,
+ GLenum target, GLintptrARB offset,
GLsizeiptrARB size, GLvoid * data,
struct gl_buffer_object * bufObj )
{
@@ -1536,7 +1538,7 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) #if FEATURE_APPLE_object_purgeable
static GLenum
-_mesa_BufferObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+buffer_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_buffer_object *bufObj;
GLenum retval;
@@ -1569,7 +1571,7 @@ _mesa_BufferObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option) static GLenum
-_mesa_RenderObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+renderbuffer_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_renderbuffer *bufObj;
GLenum retval;
@@ -1598,7 +1600,7 @@ _mesa_RenderObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option) static GLenum
-_mesa_TextureObjectPurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+texture_object_purgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_texture_object *bufObj;
GLenum retval;
@@ -1654,13 +1656,13 @@ _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) switch (objectType) {
case GL_TEXTURE:
- retval = _mesa_TextureObjectPurgeable (ctx, name, option);
+ retval = texture_object_purgeable(ctx, name, option);
break;
case GL_RENDERBUFFER_EXT:
- retval = _mesa_RenderObjectPurgeable (ctx, name, option);
+ retval = renderbuffer_purgeable(ctx, name, option);
break;
case GL_BUFFER_OBJECT_APPLE:
- retval = _mesa_BufferObjectPurgeable (ctx, name, option);
+ retval = buffer_object_purgeable(ctx, name, option);
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
@@ -1679,7 +1681,7 @@ _mesa_ObjectPurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) static GLenum
-_mesa_BufferObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+buffer_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_buffer_object *bufObj;
GLenum retval;
@@ -1709,7 +1711,7 @@ _mesa_BufferObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option static GLenum
-_mesa_RenderObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+renderbuffer_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_renderbuffer *bufObj;
GLenum retval;
@@ -1739,7 +1741,7 @@ _mesa_RenderObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option static GLenum
-_mesa_TextureObjectUnpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
+texture_object_unpurgeable(struct gl_context *ctx, GLuint name, GLenum option)
{
struct gl_texture_object *bufObj;
GLenum retval;
@@ -1794,11 +1796,11 @@ _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) switch (objectType) {
case GL_BUFFER_OBJECT_APPLE:
- return _mesa_BufferObjectUnpurgeable(ctx, name, option);
+ return buffer_object_unpurgeable(ctx, name, option);
case GL_TEXTURE:
- return _mesa_TextureObjectUnpurgeable(ctx, name, option);
+ return texture_object_unpurgeable(ctx, name, option);
case GL_RENDERBUFFER_EXT:
- return _mesa_RenderObjectUnpurgeable(ctx, name, option);
+ return renderbuffer_unpurgeable(ctx, name, option);
default:
_mesa_error(ctx, GL_INVALID_ENUM,
"glObjectUnpurgeable(name = 0x%x) invalid type: %d",
@@ -1809,12 +1811,10 @@ _mesa_ObjectUnpurgeableAPPLE(GLenum objectType, GLuint name, GLenum option) static void
-_mesa_GetBufferObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
- GLenum pname, GLint* params)
+get_buffer_object_parameteriv(struct gl_context *ctx, GLuint name,
+ GLenum pname, GLint *params)
{
- struct gl_buffer_object *bufObj;
-
- bufObj = _mesa_lookup_bufferobj(ctx, name);
+ struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, name);
if (!bufObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glGetObjectParameteriv(name = 0x%x) invalid object", name);
@@ -1835,13 +1835,11 @@ _mesa_GetBufferObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, static void
-_mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
- GLenum pname, GLint* params)
+get_renderbuffer_parameteriv(struct gl_context *ctx, GLuint name,
+ GLenum pname, GLint *params)
{
- struct gl_renderbuffer *bufObj;
-
- bufObj = _mesa_lookup_renderbuffer(ctx, name);
- if (!bufObj) {
+ struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, name);
+ if (!rb) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glObjectUnpurgeable(name = 0x%x)", name);
return;
@@ -1849,7 +1847,7 @@ _mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, switch (pname) {
case GL_PURGEABLE_APPLE:
- *params = bufObj->Purgeable;
+ *params = rb->Purgeable;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
@@ -1861,13 +1859,11 @@ _mesa_GetRenderObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, static void
-_mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name,
- GLenum pname, GLint* params)
+get_texture_object_parameteriv(struct gl_context *ctx, GLuint name,
+ GLenum pname, GLint *params)
{
- struct gl_texture_object *bufObj;
-
- bufObj = _mesa_lookup_texture(ctx, name);
- if (!bufObj) {
+ struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, name);
+ if (!texObj) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glObjectUnpurgeable(name = 0x%x)", name);
return;
@@ -1875,7 +1871,7 @@ _mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, switch (pname) {
case GL_PURGEABLE_APPLE:
- *params = bufObj->Purgeable;
+ *params = texObj->Purgeable;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
@@ -1888,7 +1884,7 @@ _mesa_GetTextureObjectParameterivAPPLE(struct gl_context *ctx, GLuint name, void GLAPIENTRY
_mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname,
- GLint* params)
+ GLint *params)
{
GET_CURRENT_CONTEXT(ctx);
@@ -1900,13 +1896,13 @@ _mesa_GetObjectParameterivAPPLE(GLenum objectType, GLuint name, GLenum pname, switch (objectType) {
case GL_TEXTURE:
- _mesa_GetTextureObjectParameterivAPPLE (ctx, name, pname, params);
+ get_texture_object_parameteriv(ctx, name, pname, params);
break;
case GL_BUFFER_OBJECT_APPLE:
- _mesa_GetBufferObjectParameterivAPPLE (ctx, name, pname, params);
+ get_buffer_object_parameteriv(ctx, name, pname, params);
break;
case GL_RENDERBUFFER_EXT:
- _mesa_GetRenderObjectParameterivAPPLE (ctx, name, pname, params);
+ get_renderbuffer_parameteriv(ctx, name, pname, params);
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
diff --git a/mesalib/src/mesa/main/clip.c b/mesalib/src/mesa/main/clip.c index bec04de72..6b9b3b58c 100644 --- a/mesalib/src/mesa/main/clip.c +++ b/mesalib/src/mesa/main/clip.c @@ -32,11 +32,20 @@ #include "math/m_matrix.h"
+/**
+ * Update derived clip plane state.
+ */
+void
+_mesa_update_clip_plane(struct gl_context *ctx, GLuint plane)
+{
+ if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
+ _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
-/**********************************************************************/
-/* Get/Set User clip-planes. */
-/**********************************************************************/
-
+ /* Clip-Space Plane = Eye-Space Plane * Projection Matrix */
+ _mesa_transform_vector(ctx->Transform._ClipUserPlane[plane],
+ ctx->Transform.EyeUserPlane[plane],
+ ctx->ProjectionMatrixStack.Top->inv);
+}
void GLAPIENTRY
@@ -78,17 +87,8 @@ _mesa_ClipPlane( GLenum plane, const GLdouble *eq ) FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
COPY_4FV(ctx->Transform.EyeUserPlane[p], equation);
- /* Update derived state. This state also depends on the projection
- * matrix, and is recalculated on changes to the projection matrix by
- * code in _mesa_update_state().
- */
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
- if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top))
- _math_matrix_analyse( ctx->ProjectionMatrixStack.Top );
-
- _mesa_transform_vector( ctx->Transform._ClipUserPlane[p],
- ctx->Transform.EyeUserPlane[p],
- ctx->ProjectionMatrixStack.Top->inv );
+ _mesa_update_clip_plane(ctx, p);
}
if (ctx->Driver.ClipPlane)
diff --git a/mesalib/src/mesa/main/clip.h b/mesalib/src/mesa/main/clip.h index bba16e11c..9a94542ec 100644 --- a/mesalib/src/mesa/main/clip.h +++ b/mesalib/src/mesa/main/clip.h @@ -33,6 +33,11 @@ #include "glheader.h"
+struct gl_context;
+
+extern void
+_mesa_update_clip_plane(struct gl_context *ctx, GLuint plane);
+
extern void GLAPIENTRY
_mesa_ClipPlane( GLenum plane, const GLdouble *equation );
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index c39e72048..972a90279 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -602,15 +602,6 @@ struct dd_function_table { */
/*@{*/
/**
- * Called when a shader is compiled.
- *
- * Note that not all shader objects get ShaderCompile called on
- * them. Notably, the shaders containing builtin functions do not
- * have CompileShader() called, so if lowering passes are done they
- * need to also be performed in LinkShader().
- */
- GLboolean (*CompileShader)(struct gl_context *ctx, struct gl_shader *shader);
- /**
* Called when a shader program is linked.
*
* This gives drivers an opportunity to clone the IR and make their
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index f24709241..8df3ac1f6 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -1,1487 +1,1425 @@ -/** - * \file enable.c - * Enable/disable/query GL capabilities. - */ - -/* - * Mesa 3-D graphics library - * Version: 7.0.3 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - -#include "glheader.h" -#include "context.h" -#include "enable.h" -#include "light.h" -#include "simple_list.h" -#include "mfeatures.h" -#include "mtypes.h" -#include "enums.h" -#include "api_arrayelt.h" -#include "texstate.h" - - - -#define CHECK_EXTENSION(EXTNAME, CAP) \ - if (!ctx->Extensions.EXTNAME) { \ - goto invalid_enum_error; \ - } - - -/** - * Helper to enable/disable client-side state. - */ -static void -client_state(struct gl_context *ctx, GLenum cap, GLboolean state) -{ - struct gl_array_object *arrayObj = ctx->Array.ArrayObj; - GLuint flag; - GLboolean *var; - - switch (cap) { - case GL_VERTEX_ARRAY: - var = &arrayObj->Vertex.Enabled; - flag = _NEW_ARRAY_VERTEX; - break; - case GL_NORMAL_ARRAY: - var = &arrayObj->Normal.Enabled; - flag = _NEW_ARRAY_NORMAL; - break; - case GL_COLOR_ARRAY: - var = &arrayObj->Color.Enabled; - flag = _NEW_ARRAY_COLOR0; - break; - case GL_INDEX_ARRAY: - var = &arrayObj->Index.Enabled; - flag = _NEW_ARRAY_INDEX; - break; - case GL_TEXTURE_COORD_ARRAY: - var = &arrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled; - flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture); - break; - case GL_EDGE_FLAG_ARRAY: - var = &arrayObj->EdgeFlag.Enabled; - flag = _NEW_ARRAY_EDGEFLAG; - break; - case GL_FOG_COORDINATE_ARRAY_EXT: - var = &arrayObj->FogCoord.Enabled; - flag = _NEW_ARRAY_FOGCOORD; - break; - case GL_SECONDARY_COLOR_ARRAY_EXT: - var = &arrayObj->SecondaryColor.Enabled; - flag = _NEW_ARRAY_COLOR1; - break; - -#if FEATURE_point_size_array - case GL_POINT_SIZE_ARRAY_OES: - var = &arrayObj->PointSize.Enabled; - flag = _NEW_ARRAY_POINT_SIZE; - break; -#endif - -#if FEATURE_NV_vertex_program - case GL_VERTEX_ATTRIB_ARRAY0_NV: - case GL_VERTEX_ATTRIB_ARRAY1_NV: - case GL_VERTEX_ATTRIB_ARRAY2_NV: - case GL_VERTEX_ATTRIB_ARRAY3_NV: - case GL_VERTEX_ATTRIB_ARRAY4_NV: - case GL_VERTEX_ATTRIB_ARRAY5_NV: - case GL_VERTEX_ATTRIB_ARRAY6_NV: - case GL_VERTEX_ATTRIB_ARRAY7_NV: - case GL_VERTEX_ATTRIB_ARRAY8_NV: - case GL_VERTEX_ATTRIB_ARRAY9_NV: - case GL_VERTEX_ATTRIB_ARRAY10_NV: - case GL_VERTEX_ATTRIB_ARRAY11_NV: - case GL_VERTEX_ATTRIB_ARRAY12_NV: - case GL_VERTEX_ATTRIB_ARRAY13_NV: - case GL_VERTEX_ATTRIB_ARRAY14_NV: - case GL_VERTEX_ATTRIB_ARRAY15_NV: - CHECK_EXTENSION(NV_vertex_program, cap); - { - GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV; - ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib)); - var = &arrayObj->VertexAttrib[n].Enabled; - flag = _NEW_ARRAY_ATTRIB(n); - } - break; -#endif /* FEATURE_NV_vertex_program */ - - /* GL_NV_primitive_restart */ - case GL_PRIMITIVE_RESTART_NV: - if (!ctx->Extensions.NV_primitive_restart) { - goto invalid_enum_error; - } - var = &ctx->Array.PrimitiveRestart; - flag = 0; - break; - - default: - goto invalid_enum_error; - } - - if (*var == state) - return; - - FLUSH_VERTICES(ctx, _NEW_ARRAY); - ctx->Array.NewState |= flag; - - _ae_invalidate_state(ctx, _NEW_ARRAY); - - *var = state; - - if (state) - ctx->Array.ArrayObj->_Enabled |= flag; - else - ctx->Array.ArrayObj->_Enabled &= ~flag; - - if (ctx->Driver.Enable) { - ctx->Driver.Enable( ctx, cap, state ); - } - - return; - -invalid_enum_error: - _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)", - state ? "Enable" : "Disable", cap); -} - - -/** - * Enable GL capability. - * \param cap state to enable/disable. - * - * Get's the current context, assures that we're outside glBegin()/glEnd() and - * calls client_state(). - */ -void GLAPIENTRY -_mesa_EnableClientState( GLenum cap ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - client_state( ctx, cap, GL_TRUE ); -} - - -/** - * Disable GL capability. - * \param cap state to enable/disable. - * - * Get's the current context, assures that we're outside glBegin()/glEnd() and - * calls client_state(). - */ -void GLAPIENTRY -_mesa_DisableClientState( GLenum cap ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - client_state( ctx, cap, GL_FALSE ); -} - - -#undef CHECK_EXTENSION -#define CHECK_EXTENSION(EXTNAME, CAP) \ - if (!ctx->Extensions.EXTNAME) { \ - goto invalid_enum_error; \ - } - -#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \ - if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \ - goto invalid_enum_error; \ - } - - - -/** - * Return pointer to current texture unit for setting/getting coordinate - * state. - * Note that we'll set GL_INVALID_OPERATION if the active texture unit is - * higher than the number of supported coordinate units. And we'll return NULL. - */ -static struct gl_texture_unit * -get_texcoord_unit(struct gl_context *ctx) -{ - if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)"); - return NULL; - } - else { - return &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - } -} - - -/** - * 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(struct gl_context *ctx, GLboolean state, GLbitfield texBit) -{ - struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); - const GLbitfield newenabled = state - ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit); - - if (texUnit->Enabled == newenabled) - return GL_FALSE; - - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->Enabled = newenabled; - return GL_TRUE; -} - - -/** - * Helper function to enable or disable state. - * - * \param ctx GL context. - * \param cap the state to enable/disable - * \param state whether to enable or disable the specified capability. - * - * Updates the current context and flushes the vertices as needed. For - * capabilities associated with extensions it verifies that those extensions - * are effectivly present before updating. Notifies the driver via - * dd_function_table::Enable. - */ -void -_mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) -{ - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "%s %s (newstate is %x)\n", - state ? "glEnable" : "glDisable", - _mesa_lookup_enum_by_nr(cap), - ctx->NewState); - - switch (cap) { - case GL_ALPHA_TEST: - if (ctx->Color.AlphaEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.AlphaEnabled = state; - break; - case GL_AUTO_NORMAL: - if (ctx->Eval.AutoNormal == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.AutoNormal = state; - break; - case GL_BLEND: - { - GLbitfield newEnabled = state * ((1 << ctx->Const.MaxDrawBuffers) - 1); - if (newEnabled != ctx->Color.BlendEnabled) { - FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.BlendEnabled = newEnabled; - } - } - break; -#if FEATURE_userclip - case GL_CLIP_PLANE0: - case GL_CLIP_PLANE1: - case GL_CLIP_PLANE2: - case GL_CLIP_PLANE3: - case GL_CLIP_PLANE4: - case GL_CLIP_PLANE5: - { - const GLuint p = cap - GL_CLIP_PLANE0; - - if ((ctx->Transform.ClipPlanesEnabled & (1 << p)) == ((GLuint) state << p)) - return; - - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - - if (state) { - ctx->Transform.ClipPlanesEnabled |= (1 << p); - - if (_math_matrix_is_dirty(ctx->ProjectionMatrixStack.Top)) - _math_matrix_analyse( ctx->ProjectionMatrixStack.Top ); - - /* This derived state also calculated in clip.c and - * from _mesa_update_state() on changes to EyeUserPlane - * and ctx->ProjectionMatrix respectively. - */ - _mesa_transform_vector( ctx->Transform._ClipUserPlane[p], - ctx->Transform.EyeUserPlane[p], - ctx->ProjectionMatrixStack.Top->inv ); - } - else { - ctx->Transform.ClipPlanesEnabled &= ~(1 << p); - } - } - break; -#endif - case GL_COLOR_MATERIAL: - if (ctx->Light.ColorMaterialEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_LIGHT); - FLUSH_CURRENT(ctx, 0); - ctx->Light.ColorMaterialEnabled = state; - if (state) { - _mesa_update_color_material( ctx, - ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); - } - break; - case GL_CULL_FACE: - if (ctx->Polygon.CullFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.CullFlag = state; - break; - case GL_DEPTH_TEST: - if (ctx->Depth.Test == state) - return; - FLUSH_VERTICES(ctx, _NEW_DEPTH); - ctx->Depth.Test = state; - break; - case GL_DITHER: - if (ctx->Color.DitherFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.DitherFlag = state; - break; - case GL_FOG: - if (ctx->Fog.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_FOG); - ctx->Fog.Enabled = state; - break; - case GL_LIGHT0: - case GL_LIGHT1: - case GL_LIGHT2: - case GL_LIGHT3: - case GL_LIGHT4: - case GL_LIGHT5: - case GL_LIGHT6: - case GL_LIGHT7: - if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_LIGHT); - ctx->Light.Light[cap-GL_LIGHT0].Enabled = state; - if (state) { - insert_at_tail(&ctx->Light.EnabledList, - &ctx->Light.Light[cap-GL_LIGHT0]); - } - else { - remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]); - } - break; - case GL_LIGHTING: - if (ctx->Light.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_LIGHT); - ctx->Light.Enabled = state; - if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) - ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE; - else - ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE; - break; - case GL_LINE_SMOOTH: - if (ctx->Line.SmoothFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_LINE); - ctx->Line.SmoothFlag = state; - ctx->_TriangleCaps ^= DD_LINE_SMOOTH; - break; - case GL_LINE_STIPPLE: - if (ctx->Line.StippleFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_LINE); - ctx->Line.StippleFlag = state; - ctx->_TriangleCaps ^= DD_LINE_STIPPLE; - break; - case GL_INDEX_LOGIC_OP: - if (ctx->Color.IndexLogicOpEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.IndexLogicOpEnabled = state; - break; - case GL_COLOR_LOGIC_OP: - if (ctx->Color.ColorLogicOpEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_COLOR); - ctx->Color.ColorLogicOpEnabled = state; - break; - case GL_MAP1_COLOR_4: - if (ctx->Eval.Map1Color4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Color4 = state; - break; - case GL_MAP1_INDEX: - if (ctx->Eval.Map1Index == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Index = state; - break; - case GL_MAP1_NORMAL: - if (ctx->Eval.Map1Normal == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Normal = state; - break; - case GL_MAP1_TEXTURE_COORD_1: - if (ctx->Eval.Map1TextureCoord1 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1TextureCoord1 = state; - break; - case GL_MAP1_TEXTURE_COORD_2: - if (ctx->Eval.Map1TextureCoord2 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1TextureCoord2 = state; - break; - case GL_MAP1_TEXTURE_COORD_3: - if (ctx->Eval.Map1TextureCoord3 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1TextureCoord3 = state; - break; - case GL_MAP1_TEXTURE_COORD_4: - if (ctx->Eval.Map1TextureCoord4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1TextureCoord4 = state; - break; - case GL_MAP1_VERTEX_3: - if (ctx->Eval.Map1Vertex3 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Vertex3 = state; - break; - case GL_MAP1_VERTEX_4: - if (ctx->Eval.Map1Vertex4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Vertex4 = state; - break; - case GL_MAP2_COLOR_4: - if (ctx->Eval.Map2Color4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Color4 = state; - break; - case GL_MAP2_INDEX: - if (ctx->Eval.Map2Index == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Index = state; - break; - case GL_MAP2_NORMAL: - if (ctx->Eval.Map2Normal == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Normal = state; - break; - case GL_MAP2_TEXTURE_COORD_1: - if (ctx->Eval.Map2TextureCoord1 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2TextureCoord1 = state; - break; - case GL_MAP2_TEXTURE_COORD_2: - if (ctx->Eval.Map2TextureCoord2 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2TextureCoord2 = state; - break; - case GL_MAP2_TEXTURE_COORD_3: - if (ctx->Eval.Map2TextureCoord3 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2TextureCoord3 = state; - break; - case GL_MAP2_TEXTURE_COORD_4: - if (ctx->Eval.Map2TextureCoord4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2TextureCoord4 = state; - break; - case GL_MAP2_VERTEX_3: - if (ctx->Eval.Map2Vertex3 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Vertex3 = state; - break; - case GL_MAP2_VERTEX_4: - if (ctx->Eval.Map2Vertex4 == state) - return; - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Vertex4 = state; - break; - case GL_NORMALIZE: - if (ctx->Transform.Normalize == state) - return; - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - ctx->Transform.Normalize = state; - break; - case GL_POINT_SMOOTH: - if (ctx->Point.SmoothFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_POINT); - ctx->Point.SmoothFlag = state; - ctx->_TriangleCaps ^= DD_POINT_SMOOTH; - break; - case GL_POLYGON_SMOOTH: - if (ctx->Polygon.SmoothFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.SmoothFlag = state; - ctx->_TriangleCaps ^= DD_TRI_SMOOTH; - break; - case GL_POLYGON_STIPPLE: - if (ctx->Polygon.StippleFlag == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.StippleFlag = state; - ctx->_TriangleCaps ^= DD_TRI_STIPPLE; - break; - case GL_POLYGON_OFFSET_POINT: - if (ctx->Polygon.OffsetPoint == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.OffsetPoint = state; - break; - case GL_POLYGON_OFFSET_LINE: - if (ctx->Polygon.OffsetLine == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.OffsetLine = state; - break; - case GL_POLYGON_OFFSET_FILL: - /*case GL_POLYGON_OFFSET_EXT:*/ - if (ctx->Polygon.OffsetFill == state) - return; - FLUSH_VERTICES(ctx, _NEW_POLYGON); - ctx->Polygon.OffsetFill = state; - break; - case GL_RESCALE_NORMAL_EXT: - if (ctx->Transform.RescaleNormals == state) - return; - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - ctx->Transform.RescaleNormals = state; - break; - case GL_SCISSOR_TEST: - if (ctx->Scissor.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_SCISSOR); - ctx->Scissor.Enabled = state; - break; - case GL_SHARED_TEXTURE_PALETTE_EXT: - if (ctx->Texture.SharedPalette == state) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - ctx->Texture.SharedPalette = state; - break; - case GL_STENCIL_TEST: - if (ctx->Stencil.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_STENCIL); - ctx->Stencil.Enabled = state; - break; - case GL_TEXTURE_1D: - if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) { - return; - } - break; - case GL_TEXTURE_2D: - if (!enable_texture(ctx, state, TEXTURE_2D_BIT)) { - return; - } - break; - case GL_TEXTURE_3D: - if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) { - return; - } - break; - case GL_TEXTURE_GEN_Q: - { - struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - GLuint newenabled = texUnit->TexGenEnabled & ~Q_BIT; - if (state) - newenabled |= Q_BIT; - if (texUnit->TexGenEnabled == newenabled) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->TexGenEnabled = newenabled; - } - } - break; - case GL_TEXTURE_GEN_R: - { - struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - GLuint newenabled = texUnit->TexGenEnabled & ~R_BIT; - if (state) - newenabled |= R_BIT; - if (texUnit->TexGenEnabled == newenabled) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->TexGenEnabled = newenabled; - } - } - break; - case GL_TEXTURE_GEN_S: - { - struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - GLuint newenabled = texUnit->TexGenEnabled & ~S_BIT; - if (state) - newenabled |= S_BIT; - if (texUnit->TexGenEnabled == newenabled) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->TexGenEnabled = newenabled; - } - } - break; - case GL_TEXTURE_GEN_T: - { - struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - GLuint newenabled = texUnit->TexGenEnabled & ~T_BIT; - if (state) - newenabled |= T_BIT; - if (texUnit->TexGenEnabled == newenabled) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->TexGenEnabled = newenabled; - } - } - break; - -#if FEATURE_ES1 - case GL_TEXTURE_GEN_STR_OES: - /* disable S, T, and R at the same time */ - { - struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - GLuint newenabled = - texUnit->TexGenEnabled & ~STR_BITS; - if (state) - newenabled |= STR_BITS; - if (texUnit->TexGenEnabled == newenabled) - return; - FLUSH_VERTICES(ctx, _NEW_TEXTURE); - texUnit->TexGenEnabled = newenabled; - } - } - break; -#endif - - /* - * CLIENT STATE!!! - */ - case GL_VERTEX_ARRAY: - case GL_NORMAL_ARRAY: - case GL_COLOR_ARRAY: - case GL_INDEX_ARRAY: - case GL_TEXTURE_COORD_ARRAY: - case GL_EDGE_FLAG_ARRAY: - case GL_FOG_COORDINATE_ARRAY_EXT: - case GL_SECONDARY_COLOR_ARRAY_EXT: - case GL_POINT_SIZE_ARRAY_OES: - client_state( ctx, cap, state ); - return; - - /* GL_ARB_texture_cube_map */ - case GL_TEXTURE_CUBE_MAP_ARB: - CHECK_EXTENSION(ARB_texture_cube_map, cap); - if (!enable_texture(ctx, state, TEXTURE_CUBE_BIT)) { - return; - } - break; - - /* GL_EXT_secondary_color */ - case GL_COLOR_SUM_EXT: - CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program, cap); - if (ctx->Fog.ColorSumEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_FOG); - ctx->Fog.ColorSumEnabled = state; - break; - - /* GL_ARB_multisample */ - case GL_MULTISAMPLE_ARB: - if (ctx->Multisample.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); - ctx->Multisample.Enabled = state; - break; - case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: - if (ctx->Multisample.SampleAlphaToCoverage == state) - return; - FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); - ctx->Multisample.SampleAlphaToCoverage = state; - break; - case GL_SAMPLE_ALPHA_TO_ONE_ARB: - if (ctx->Multisample.SampleAlphaToOne == state) - return; - FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); - ctx->Multisample.SampleAlphaToOne = state; - break; - case GL_SAMPLE_COVERAGE_ARB: - if (ctx->Multisample.SampleCoverage == state) - return; - FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); - ctx->Multisample.SampleCoverage = state; - break; - case GL_SAMPLE_COVERAGE_INVERT_ARB: - if (ctx->Multisample.SampleCoverageInvert == state) - return; - FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); - ctx->Multisample.SampleCoverageInvert = state; - break; - - /* GL_IBM_rasterpos_clip */ - case GL_RASTER_POSITION_UNCLIPPED_IBM: - CHECK_EXTENSION(IBM_rasterpos_clip, cap); - if (ctx->Transform.RasterPositionUnclipped == state) - return; - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - ctx->Transform.RasterPositionUnclipped = state; - break; - - /* GL_NV_point_sprite */ - case GL_POINT_SPRITE_NV: - CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap); - if (ctx->Point.PointSprite == state) - return; - FLUSH_VERTICES(ctx, _NEW_POINT); - ctx->Point.PointSprite = state; - break; - -#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program - case GL_VERTEX_PROGRAM_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap); - if (ctx->VertexProgram.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->VertexProgram.Enabled = state; - break; - case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap); - if (ctx->VertexProgram.PointSizeEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->VertexProgram.PointSizeEnabled = state; - break; - case GL_VERTEX_PROGRAM_TWO_SIDE_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap); - if (ctx->VertexProgram.TwoSideEnabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->VertexProgram.TwoSideEnabled = state; - break; -#endif -#if FEATURE_NV_vertex_program - case GL_MAP1_VERTEX_ATTRIB0_4_NV: - case GL_MAP1_VERTEX_ATTRIB1_4_NV: - case GL_MAP1_VERTEX_ATTRIB2_4_NV: - case GL_MAP1_VERTEX_ATTRIB3_4_NV: - case GL_MAP1_VERTEX_ATTRIB4_4_NV: - case GL_MAP1_VERTEX_ATTRIB5_4_NV: - case GL_MAP1_VERTEX_ATTRIB6_4_NV: - case GL_MAP1_VERTEX_ATTRIB7_4_NV: - case GL_MAP1_VERTEX_ATTRIB8_4_NV: - case GL_MAP1_VERTEX_ATTRIB9_4_NV: - case GL_MAP1_VERTEX_ATTRIB10_4_NV: - case GL_MAP1_VERTEX_ATTRIB11_4_NV: - case GL_MAP1_VERTEX_ATTRIB12_4_NV: - case GL_MAP1_VERTEX_ATTRIB13_4_NV: - case GL_MAP1_VERTEX_ATTRIB14_4_NV: - case GL_MAP1_VERTEX_ATTRIB15_4_NV: - CHECK_EXTENSION(NV_vertex_program, cap); - { - const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV); - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map1Attrib[map] = state; - } - break; - case GL_MAP2_VERTEX_ATTRIB0_4_NV: - case GL_MAP2_VERTEX_ATTRIB1_4_NV: - case GL_MAP2_VERTEX_ATTRIB2_4_NV: - case GL_MAP2_VERTEX_ATTRIB3_4_NV: - case GL_MAP2_VERTEX_ATTRIB4_4_NV: - case GL_MAP2_VERTEX_ATTRIB5_4_NV: - case GL_MAP2_VERTEX_ATTRIB6_4_NV: - case GL_MAP2_VERTEX_ATTRIB7_4_NV: - case GL_MAP2_VERTEX_ATTRIB8_4_NV: - case GL_MAP2_VERTEX_ATTRIB9_4_NV: - case GL_MAP2_VERTEX_ATTRIB10_4_NV: - case GL_MAP2_VERTEX_ATTRIB11_4_NV: - case GL_MAP2_VERTEX_ATTRIB12_4_NV: - case GL_MAP2_VERTEX_ATTRIB13_4_NV: - case GL_MAP2_VERTEX_ATTRIB14_4_NV: - case GL_MAP2_VERTEX_ATTRIB15_4_NV: - CHECK_EXTENSION(NV_vertex_program, cap); - { - const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV); - FLUSH_VERTICES(ctx, _NEW_EVAL); - ctx->Eval.Map2Attrib[map] = state; - } - break; -#endif /* FEATURE_NV_vertex_program */ - -#if FEATURE_NV_fragment_program - case GL_FRAGMENT_PROGRAM_NV: - CHECK_EXTENSION(NV_fragment_program, cap); - if (ctx->FragmentProgram.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->FragmentProgram.Enabled = state; - break; -#endif /* FEATURE_NV_fragment_program */ - - /* GL_NV_texture_rectangle */ - case GL_TEXTURE_RECTANGLE_NV: - CHECK_EXTENSION(NV_texture_rectangle, cap); - if (!enable_texture(ctx, state, TEXTURE_RECT_BIT)) { - return; - } - break; - - /* GL_EXT_stencil_two_side */ - case GL_STENCIL_TEST_TWO_SIDE_EXT: - CHECK_EXTENSION(EXT_stencil_two_side, cap); - if (ctx->Stencil.TestTwoSide == state) - return; - FLUSH_VERTICES(ctx, _NEW_STENCIL); - ctx->Stencil.TestTwoSide = state; - if (state) { - ctx->Stencil._BackFace = 2; - ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL; - } else { - ctx->Stencil._BackFace = 1; - ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL; - } - break; - -#if FEATURE_ARB_fragment_program - case GL_FRAGMENT_PROGRAM_ARB: - CHECK_EXTENSION(ARB_fragment_program, cap); - if (ctx->FragmentProgram.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->FragmentProgram.Enabled = state; - break; -#endif /* FEATURE_ARB_fragment_program */ - - /* GL_EXT_depth_bounds_test */ - case GL_DEPTH_BOUNDS_TEST_EXT: - CHECK_EXTENSION(EXT_depth_bounds_test, cap); - if (ctx->Depth.BoundsTest == state) - return; - FLUSH_VERTICES(ctx, _NEW_DEPTH); - ctx->Depth.BoundsTest = state; - break; - - case GL_DEPTH_CLAMP: - if (ctx->Transform.DepthClamp == state) - return; - CHECK_EXTENSION(ARB_depth_clamp, cap); - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - ctx->Transform.DepthClamp = state; - break; - -#if FEATURE_ATI_fragment_shader - case GL_FRAGMENT_SHADER_ATI: - CHECK_EXTENSION(ATI_fragment_shader, cap); - if (ctx->ATIFragmentShader.Enabled == state) - return; - FLUSH_VERTICES(ctx, _NEW_PROGRAM); - ctx->ATIFragmentShader.Enabled = state; - break; -#endif - - /* GL_MESA_texture_array */ - case GL_TEXTURE_1D_ARRAY_EXT: - CHECK_EXTENSION(MESA_texture_array, cap); - if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) { - return; - } - break; - - case GL_TEXTURE_2D_ARRAY_EXT: - CHECK_EXTENSION(MESA_texture_array, cap); - if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) { - return; - } - break; - - case GL_TEXTURE_CUBE_MAP_SEAMLESS: - CHECK_EXTENSION(ARB_seamless_cube_map, cap); - ctx->Texture.CubeMapSeamless = state; - break; - -#if FEATURE_EXT_transform_feedback - case GL_RASTERIZER_DISCARD: - CHECK_EXTENSION(EXT_transform_feedback, cap); - if (ctx->TransformFeedback.RasterDiscard != state) { - ctx->TransformFeedback.RasterDiscard = state; - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - } - break; -#endif - - /* GL 3.1 primitive restart. Note: this enum is different from - * GL_PRIMITIVE_RESTART_NV (which is client state). - */ - case GL_PRIMITIVE_RESTART: - if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) { - goto invalid_enum_error; - } - if (ctx->Array.PrimitiveRestart != state) { - FLUSH_VERTICES(ctx, _NEW_TRANSFORM); - ctx->Array.PrimitiveRestart = state; - } - break; - - /* GL3.0 - GL_framebuffer_sRGB */ - case GL_FRAMEBUFFER_SRGB_EXT: - CHECK_EXTENSION(EXT_framebuffer_sRGB, cap); - FLUSH_VERTICES(ctx, _NEW_BUFFERS); - ctx->Color.sRGBEnabled = state; - break; - - default: - goto invalid_enum_error; - } - - if (ctx->Driver.Enable) { - ctx->Driver.Enable( ctx, cap, state ); - } - - return; - -invalid_enum_error: - _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)", - state ? "Enable" : "Disable", cap); -} - - -/** - * Enable GL capability. Called by glEnable() - * \param cap state to enable. - */ -void GLAPIENTRY -_mesa_Enable( GLenum cap ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - _mesa_set_enable( ctx, cap, GL_TRUE ); -} - - -/** - * Disable GL capability. Called by glDisable() - * \param cap state to disable. - */ -void GLAPIENTRY -_mesa_Disable( GLenum cap ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - - _mesa_set_enable( ctx, cap, GL_FALSE ); -} - - - -/** - * Enable/disable an indexed state var. - */ -void -_mesa_set_enablei(struct gl_context *ctx, GLenum cap, GLuint index, GLboolean state) -{ - ASSERT(state == 0 || state == 1); - switch (cap) { - case GL_BLEND: - if (!ctx->Extensions.EXT_draw_buffers2) { - goto invalid_enum_error; - } - if (index >= ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", - state ? "glEnableIndexed" : "glDisableIndexed", index); - return; - } - if (((ctx->Color.BlendEnabled >> index) & 1) != state) { - FLUSH_VERTICES(ctx, _NEW_COLOR); - if (state) - ctx->Color.BlendEnabled |= (1 << index); - else - ctx->Color.BlendEnabled &= ~(1 << index); - } - break; - default: - goto invalid_enum_error; - } - return; - -invalid_enum_error: - _mesa_error(ctx, GL_INVALID_ENUM, "%s(cap=%s)", - state ? "glEnablei" : "glDisablei", - _mesa_lookup_enum_by_nr(cap)); -} - - -void GLAPIENTRY -_mesa_DisableIndexed( GLenum cap, GLuint index ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - _mesa_set_enablei(ctx, cap, index, GL_FALSE); -} - - -void GLAPIENTRY -_mesa_EnableIndexed( GLenum cap, GLuint index ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END(ctx); - _mesa_set_enablei(ctx, cap, index, GL_TRUE); -} - - -GLboolean GLAPIENTRY -_mesa_IsEnabledIndexed( GLenum cap, GLuint index ) -{ - GET_CURRENT_CONTEXT(ctx); - switch (cap) { - case GL_BLEND: - if (index >= ctx->Const.MaxDrawBuffers) { - _mesa_error(ctx, GL_INVALID_VALUE, "glIsEnabledIndexed(index=%u)", - index); - return GL_FALSE; - } - return (ctx->Color.BlendEnabled >> index) & 1; - default: - _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)", - _mesa_lookup_enum_by_nr(cap)); - return GL_FALSE; - } -} - - - - -#undef CHECK_EXTENSION -#define CHECK_EXTENSION(EXTNAME) \ - if (!ctx->Extensions.EXTNAME) { \ - goto invalid_enum_error; \ - } - -#undef CHECK_EXTENSION2 -#define CHECK_EXTENSION2(EXT1, EXT2) \ - if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \ - goto invalid_enum_error; \ - } - - -/** - * Helper function to determine whether a texture target is enabled. - */ -static GLboolean -is_texture_enabled(struct gl_context *ctx, GLbitfield bit) -{ - const struct gl_texture_unit *const texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE; -} - - -/** - * Return simple enable/disable state. - * - * \param cap state variable to query. - * - * Returns the state of the specified capability from the current GL context. - * For the capabilities associated with extensions verifies that those - * extensions are effectively present before reporting. - */ -GLboolean GLAPIENTRY -_mesa_IsEnabled( GLenum cap ) -{ - GET_CURRENT_CONTEXT(ctx); - switch (cap) { - case GL_ALPHA_TEST: - return ctx->Color.AlphaEnabled; - case GL_AUTO_NORMAL: - return ctx->Eval.AutoNormal; - case GL_BLEND: - return ctx->Color.BlendEnabled & 1; /* return state for buffer[0] */ - case GL_CLIP_PLANE0: - case GL_CLIP_PLANE1: - case GL_CLIP_PLANE2: - case GL_CLIP_PLANE3: - case GL_CLIP_PLANE4: - case GL_CLIP_PLANE5: - return (ctx->Transform.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1; - case GL_COLOR_MATERIAL: - return ctx->Light.ColorMaterialEnabled; - case GL_CULL_FACE: - return ctx->Polygon.CullFlag; - case GL_DEPTH_TEST: - return ctx->Depth.Test; - case GL_DITHER: - return ctx->Color.DitherFlag; - case GL_FOG: - return ctx->Fog.Enabled; - case GL_LIGHTING: - return ctx->Light.Enabled; - case GL_LIGHT0: - case GL_LIGHT1: - case GL_LIGHT2: - case GL_LIGHT3: - case GL_LIGHT4: - case GL_LIGHT5: - case GL_LIGHT6: - case GL_LIGHT7: - return ctx->Light.Light[cap-GL_LIGHT0].Enabled; - case GL_LINE_SMOOTH: - return ctx->Line.SmoothFlag; - case GL_LINE_STIPPLE: - return ctx->Line.StippleFlag; - case GL_INDEX_LOGIC_OP: - return ctx->Color.IndexLogicOpEnabled; - case GL_COLOR_LOGIC_OP: - return ctx->Color.ColorLogicOpEnabled; - case GL_MAP1_COLOR_4: - return ctx->Eval.Map1Color4; - case GL_MAP1_INDEX: - return ctx->Eval.Map1Index; - case GL_MAP1_NORMAL: - return ctx->Eval.Map1Normal; - case GL_MAP1_TEXTURE_COORD_1: - return ctx->Eval.Map1TextureCoord1; - case GL_MAP1_TEXTURE_COORD_2: - return ctx->Eval.Map1TextureCoord2; - case GL_MAP1_TEXTURE_COORD_3: - return ctx->Eval.Map1TextureCoord3; - case GL_MAP1_TEXTURE_COORD_4: - return ctx->Eval.Map1TextureCoord4; - case GL_MAP1_VERTEX_3: - return ctx->Eval.Map1Vertex3; - case GL_MAP1_VERTEX_4: - return ctx->Eval.Map1Vertex4; - case GL_MAP2_COLOR_4: - return ctx->Eval.Map2Color4; - case GL_MAP2_INDEX: - return ctx->Eval.Map2Index; - case GL_MAP2_NORMAL: - return ctx->Eval.Map2Normal; - case GL_MAP2_TEXTURE_COORD_1: - return ctx->Eval.Map2TextureCoord1; - case GL_MAP2_TEXTURE_COORD_2: - return ctx->Eval.Map2TextureCoord2; - case GL_MAP2_TEXTURE_COORD_3: - return ctx->Eval.Map2TextureCoord3; - case GL_MAP2_TEXTURE_COORD_4: - return ctx->Eval.Map2TextureCoord4; - case GL_MAP2_VERTEX_3: - return ctx->Eval.Map2Vertex3; - case GL_MAP2_VERTEX_4: - return ctx->Eval.Map2Vertex4; - case GL_NORMALIZE: - return ctx->Transform.Normalize; - case GL_POINT_SMOOTH: - return ctx->Point.SmoothFlag; - case GL_POLYGON_SMOOTH: - return ctx->Polygon.SmoothFlag; - case GL_POLYGON_STIPPLE: - return ctx->Polygon.StippleFlag; - case GL_POLYGON_OFFSET_POINT: - return ctx->Polygon.OffsetPoint; - case GL_POLYGON_OFFSET_LINE: - return ctx->Polygon.OffsetLine; - case GL_POLYGON_OFFSET_FILL: - /*case GL_POLYGON_OFFSET_EXT:*/ - return ctx->Polygon.OffsetFill; - case GL_RESCALE_NORMAL_EXT: - return ctx->Transform.RescaleNormals; - case GL_SCISSOR_TEST: - return ctx->Scissor.Enabled; - case GL_SHARED_TEXTURE_PALETTE_EXT: - return ctx->Texture.SharedPalette; - case GL_STENCIL_TEST: - return ctx->Stencil.Enabled; - case GL_TEXTURE_1D: - return is_texture_enabled(ctx, TEXTURE_1D_BIT); - case GL_TEXTURE_2D: - return is_texture_enabled(ctx, TEXTURE_2D_BIT); - case GL_TEXTURE_3D: - return is_texture_enabled(ctx, TEXTURE_3D_BIT); - case GL_TEXTURE_GEN_Q: - { - const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE; - } - } - return GL_FALSE; - case GL_TEXTURE_GEN_R: - { - const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE; - } - } - return GL_FALSE; - case GL_TEXTURE_GEN_S: - { - const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE; - } - } - return GL_FALSE; - case GL_TEXTURE_GEN_T: - { - const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE; - } - } - return GL_FALSE; -#if FEATURE_ES1 - case GL_TEXTURE_GEN_STR_OES: - { - const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx); - if (texUnit) { - return (texUnit->TexGenEnabled & STR_BITS) == STR_BITS ? GL_TRUE : GL_FALSE; - } - } -#endif - - /* - * CLIENT STATE!!! - */ - case GL_VERTEX_ARRAY: - return (ctx->Array.ArrayObj->Vertex.Enabled != 0); - case GL_NORMAL_ARRAY: - return (ctx->Array.ArrayObj->Normal.Enabled != 0); - case GL_COLOR_ARRAY: - return (ctx->Array.ArrayObj->Color.Enabled != 0); - case GL_INDEX_ARRAY: - return (ctx->Array.ArrayObj->Index.Enabled != 0); - case GL_TEXTURE_COORD_ARRAY: - return (ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled != 0); - case GL_EDGE_FLAG_ARRAY: - return (ctx->Array.ArrayObj->EdgeFlag.Enabled != 0); - case GL_FOG_COORDINATE_ARRAY_EXT: - CHECK_EXTENSION(EXT_fog_coord); - return (ctx->Array.ArrayObj->FogCoord.Enabled != 0); - case GL_SECONDARY_COLOR_ARRAY_EXT: - CHECK_EXTENSION(EXT_secondary_color); - return (ctx->Array.ArrayObj->SecondaryColor.Enabled != 0); -#if FEATURE_point_size_array - case GL_POINT_SIZE_ARRAY_OES: - return (ctx->Array.ArrayObj->PointSize.Enabled != 0); -#endif - - /* GL_ARB_texture_cube_map */ - case GL_TEXTURE_CUBE_MAP_ARB: - CHECK_EXTENSION(ARB_texture_cube_map); - return is_texture_enabled(ctx, TEXTURE_CUBE_BIT); - - /* GL_EXT_secondary_color */ - case GL_COLOR_SUM_EXT: - CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program); - return ctx->Fog.ColorSumEnabled; - - /* GL_ARB_multisample */ - case GL_MULTISAMPLE_ARB: - return ctx->Multisample.Enabled; - case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB: - return ctx->Multisample.SampleAlphaToCoverage; - case GL_SAMPLE_ALPHA_TO_ONE_ARB: - return ctx->Multisample.SampleAlphaToOne; - case GL_SAMPLE_COVERAGE_ARB: - return ctx->Multisample.SampleCoverage; - case GL_SAMPLE_COVERAGE_INVERT_ARB: - return ctx->Multisample.SampleCoverageInvert; - - /* GL_IBM_rasterpos_clip */ - case GL_RASTER_POSITION_UNCLIPPED_IBM: - CHECK_EXTENSION(IBM_rasterpos_clip); - return ctx->Transform.RasterPositionUnclipped; - - /* GL_NV_point_sprite */ - case GL_POINT_SPRITE_NV: - CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite) - return ctx->Point.PointSprite; - -#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program - case GL_VERTEX_PROGRAM_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program); - return ctx->VertexProgram.Enabled; - case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program); - return ctx->VertexProgram.PointSizeEnabled; - case GL_VERTEX_PROGRAM_TWO_SIDE_ARB: - CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program); - return ctx->VertexProgram.TwoSideEnabled; -#endif -#if FEATURE_NV_vertex_program - case GL_VERTEX_ATTRIB_ARRAY0_NV: - case GL_VERTEX_ATTRIB_ARRAY1_NV: - case GL_VERTEX_ATTRIB_ARRAY2_NV: - case GL_VERTEX_ATTRIB_ARRAY3_NV: - case GL_VERTEX_ATTRIB_ARRAY4_NV: - case GL_VERTEX_ATTRIB_ARRAY5_NV: - case GL_VERTEX_ATTRIB_ARRAY6_NV: - case GL_VERTEX_ATTRIB_ARRAY7_NV: - case GL_VERTEX_ATTRIB_ARRAY8_NV: - case GL_VERTEX_ATTRIB_ARRAY9_NV: - case GL_VERTEX_ATTRIB_ARRAY10_NV: - case GL_VERTEX_ATTRIB_ARRAY11_NV: - case GL_VERTEX_ATTRIB_ARRAY12_NV: - case GL_VERTEX_ATTRIB_ARRAY13_NV: - case GL_VERTEX_ATTRIB_ARRAY14_NV: - case GL_VERTEX_ATTRIB_ARRAY15_NV: - CHECK_EXTENSION(NV_vertex_program); - { - GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV; - ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib)); - return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0); - } - case GL_MAP1_VERTEX_ATTRIB0_4_NV: - case GL_MAP1_VERTEX_ATTRIB1_4_NV: - case GL_MAP1_VERTEX_ATTRIB2_4_NV: - case GL_MAP1_VERTEX_ATTRIB3_4_NV: - case GL_MAP1_VERTEX_ATTRIB4_4_NV: - case GL_MAP1_VERTEX_ATTRIB5_4_NV: - case GL_MAP1_VERTEX_ATTRIB6_4_NV: - case GL_MAP1_VERTEX_ATTRIB7_4_NV: - case GL_MAP1_VERTEX_ATTRIB8_4_NV: - case GL_MAP1_VERTEX_ATTRIB9_4_NV: - case GL_MAP1_VERTEX_ATTRIB10_4_NV: - case GL_MAP1_VERTEX_ATTRIB11_4_NV: - case GL_MAP1_VERTEX_ATTRIB12_4_NV: - case GL_MAP1_VERTEX_ATTRIB13_4_NV: - case GL_MAP1_VERTEX_ATTRIB14_4_NV: - case GL_MAP1_VERTEX_ATTRIB15_4_NV: - CHECK_EXTENSION(NV_vertex_program); - { - const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV); - return ctx->Eval.Map1Attrib[map]; - } - case GL_MAP2_VERTEX_ATTRIB0_4_NV: - case GL_MAP2_VERTEX_ATTRIB1_4_NV: - case GL_MAP2_VERTEX_ATTRIB2_4_NV: - case GL_MAP2_VERTEX_ATTRIB3_4_NV: - case GL_MAP2_VERTEX_ATTRIB4_4_NV: - case GL_MAP2_VERTEX_ATTRIB5_4_NV: - case GL_MAP2_VERTEX_ATTRIB6_4_NV: - case GL_MAP2_VERTEX_ATTRIB7_4_NV: - case GL_MAP2_VERTEX_ATTRIB8_4_NV: - case GL_MAP2_VERTEX_ATTRIB9_4_NV: - case GL_MAP2_VERTEX_ATTRIB10_4_NV: - case GL_MAP2_VERTEX_ATTRIB11_4_NV: - case GL_MAP2_VERTEX_ATTRIB12_4_NV: - case GL_MAP2_VERTEX_ATTRIB13_4_NV: - case GL_MAP2_VERTEX_ATTRIB14_4_NV: - case GL_MAP2_VERTEX_ATTRIB15_4_NV: - CHECK_EXTENSION(NV_vertex_program); - { - const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV); - return ctx->Eval.Map2Attrib[map]; - } -#endif /* FEATURE_NV_vertex_program */ - -#if FEATURE_NV_fragment_program - case GL_FRAGMENT_PROGRAM_NV: - CHECK_EXTENSION(NV_fragment_program); - return ctx->FragmentProgram.Enabled; -#endif /* FEATURE_NV_fragment_program */ - - /* GL_NV_texture_rectangle */ - case GL_TEXTURE_RECTANGLE_NV: - CHECK_EXTENSION(NV_texture_rectangle); - return is_texture_enabled(ctx, TEXTURE_RECT_BIT); - - /* GL_EXT_stencil_two_side */ - case GL_STENCIL_TEST_TWO_SIDE_EXT: - CHECK_EXTENSION(EXT_stencil_two_side); - return ctx->Stencil.TestTwoSide; - -#if FEATURE_ARB_fragment_program - case GL_FRAGMENT_PROGRAM_ARB: - return ctx->FragmentProgram.Enabled; -#endif /* FEATURE_ARB_fragment_program */ - - /* GL_EXT_depth_bounds_test */ - case GL_DEPTH_BOUNDS_TEST_EXT: - CHECK_EXTENSION(EXT_depth_bounds_test); - return ctx->Depth.BoundsTest; - - /* GL_ARB_depth_clamp */ - case GL_DEPTH_CLAMP: - CHECK_EXTENSION(ARB_depth_clamp); - return ctx->Transform.DepthClamp; - -#if FEATURE_ATI_fragment_shader - case GL_FRAGMENT_SHADER_ATI: - CHECK_EXTENSION(ATI_fragment_shader); - return ctx->ATIFragmentShader.Enabled; -#endif /* FEATURE_ATI_fragment_shader */ - - case GL_TEXTURE_CUBE_MAP_SEAMLESS: - CHECK_EXTENSION(ARB_seamless_cube_map); - return ctx->Texture.CubeMapSeamless; - -#if FEATURE_EXT_transform_feedback - case GL_RASTERIZER_DISCARD: - CHECK_EXTENSION(EXT_transform_feedback); - return ctx->TransformFeedback.RasterDiscard; -#endif - - /* GL_NV_primitive_restart */ - case GL_PRIMITIVE_RESTART_NV: - if (!ctx->Extensions.NV_primitive_restart) { - goto invalid_enum_error; - } - return ctx->Array.PrimitiveRestart; - - /* GL 3.1 primitive restart */ - case GL_PRIMITIVE_RESTART: - if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) { - goto invalid_enum_error; - } - return ctx->Array.PrimitiveRestart; - - /* GL3.0 - GL_framebuffer_sRGB */ - case GL_FRAMEBUFFER_SRGB_EXT: - CHECK_EXTENSION(EXT_framebuffer_sRGB); - return ctx->Color.sRGBEnabled; - - default: - goto invalid_enum_error; - } - - return GL_FALSE; - -invalid_enum_error: - _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap); - return GL_FALSE; -} +/**
+ * \file enable.c
+ * Enable/disable/query GL capabilities.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.0.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "glheader.h"
+#include "clip.h"
+#include "context.h"
+#include "enable.h"
+#include "light.h"
+#include "simple_list.h"
+#include "mfeatures.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "api_arrayelt.h"
+#include "texstate.h"
+
+
+
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+
+/**
+ * Helper to enable/disable client-side state.
+ */
+static void
+client_state(struct gl_context *ctx, GLenum cap, GLboolean state)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ GLuint flag;
+ GLboolean *var;
+
+ switch (cap) {
+ case GL_VERTEX_ARRAY:
+ var = &arrayObj->Vertex.Enabled;
+ flag = _NEW_ARRAY_VERTEX;
+ break;
+ case GL_NORMAL_ARRAY:
+ var = &arrayObj->Normal.Enabled;
+ flag = _NEW_ARRAY_NORMAL;
+ break;
+ case GL_COLOR_ARRAY:
+ var = &arrayObj->Color.Enabled;
+ flag = _NEW_ARRAY_COLOR0;
+ break;
+ case GL_INDEX_ARRAY:
+ var = &arrayObj->Index.Enabled;
+ flag = _NEW_ARRAY_INDEX;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ var = &arrayObj->TexCoord[ctx->Array.ActiveTexture].Enabled;
+ flag = _NEW_ARRAY_TEXCOORD(ctx->Array.ActiveTexture);
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ var = &arrayObj->EdgeFlag.Enabled;
+ flag = _NEW_ARRAY_EDGEFLAG;
+ break;
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ var = &arrayObj->FogCoord.Enabled;
+ flag = _NEW_ARRAY_FOGCOORD;
+ break;
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ var = &arrayObj->SecondaryColor.Enabled;
+ flag = _NEW_ARRAY_COLOR1;
+ break;
+
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ var = &arrayObj->PointSize.Enabled;
+ flag = _NEW_ARRAY_POINT_SIZE;
+ break;
+#endif
+
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ var = &arrayObj->VertexAttrib[n].Enabled;
+ flag = _NEW_ARRAY_ATTRIB(n);
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+ /* GL_NV_primitive_restart */
+ case GL_PRIMITIVE_RESTART_NV:
+ if (!ctx->Extensions.NV_primitive_restart) {
+ goto invalid_enum_error;
+ }
+ var = &ctx->Array.PrimitiveRestart;
+ flag = 0;
+ break;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ if (*var == state)
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_ARRAY);
+ ctx->Array.NewState |= flag;
+
+ _ae_invalidate_state(ctx, _NEW_ARRAY);
+
+ *var = state;
+
+ if (state)
+ ctx->Array.ArrayObj->_Enabled |= flag;
+ else
+ ctx->Array.ArrayObj->_Enabled &= ~flag;
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sClientState(0x%x)",
+ state ? "Enable" : "Disable", cap);
+}
+
+
+/**
+ * Enable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_EnableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability.
+ * \param cap state to enable/disable.
+ *
+ * Get's the current context, assures that we're outside glBegin()/glEnd() and
+ * calls client_state().
+ */
+void GLAPIENTRY
+_mesa_DisableClientState( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ client_state( ctx, cap, GL_FALSE );
+}
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME, CAP) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+#define CHECK_EXTENSION2(EXT1, EXT2, CAP) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ goto invalid_enum_error; \
+ }
+
+
+
+/**
+ * Return pointer to current texture unit for setting/getting coordinate
+ * state.
+ * Note that we'll set GL_INVALID_OPERATION and return NULL if the active
+ * texture unit is higher than the number of supported coordinate units.
+ */
+static struct gl_texture_unit *
+get_texcoord_unit(struct gl_context *ctx)
+{
+ if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glEnable/Disable(texcoord unit)");
+ return NULL;
+ }
+ else {
+ return &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ }
+}
+
+
+/**
+ * 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(struct gl_context *ctx, GLboolean state, GLbitfield texBit)
+{
+ struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
+ const GLbitfield newenabled = state
+ ? (texUnit->Enabled | texBit) : (texUnit->Enabled & ~texBit);
+
+ if (texUnit->Enabled == newenabled)
+ return GL_FALSE;
+
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->Enabled = newenabled;
+ return GL_TRUE;
+}
+
+
+/**
+ * Helper function to enable or disable state.
+ *
+ * \param ctx GL context.
+ * \param cap the state to enable/disable
+ * \param state whether to enable or disable the specified capability.
+ *
+ * Updates the current context and flushes the vertices as needed. For
+ * capabilities associated with extensions it verifies that those extensions
+ * are effectivly present before updating. Notifies the driver via
+ * dd_function_table::Enable.
+ */
+void
+_mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
+{
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "%s %s (newstate is %x)\n",
+ state ? "glEnable" : "glDisable",
+ _mesa_lookup_enum_by_nr(cap),
+ ctx->NewState);
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (ctx->Color.AlphaEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.AlphaEnabled = state;
+ break;
+ case GL_AUTO_NORMAL:
+ if (ctx->Eval.AutoNormal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.AutoNormal = state;
+ break;
+ case GL_BLEND:
+ {
+ GLbitfield newEnabled =
+ state * ((1 << ctx->Const.MaxDrawBuffers) - 1);
+ if (newEnabled != ctx->Color.BlendEnabled) {
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.BlendEnabled = newEnabled;
+ }
+ }
+ break;
+#if FEATURE_userclip
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ {
+ const GLuint p = cap - GL_CLIP_PLANE0;
+
+ if ((ctx->Transform.ClipPlanesEnabled & (1 << p))
+ == ((GLuint) state << p))
+ return;
+
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+
+ if (state) {
+ ctx->Transform.ClipPlanesEnabled |= (1 << p);
+ _mesa_update_clip_plane(ctx, p);
+ }
+ else {
+ ctx->Transform.ClipPlanesEnabled &= ~(1 << p);
+ }
+ }
+ break;
+#endif
+ case GL_COLOR_MATERIAL:
+ if (ctx->Light.ColorMaterialEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ FLUSH_CURRENT(ctx, 0);
+ ctx->Light.ColorMaterialEnabled = state;
+ if (state) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ }
+ break;
+ case GL_CULL_FACE:
+ if (ctx->Polygon.CullFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.CullFlag = state;
+ break;
+ case GL_DEPTH_TEST:
+ if (ctx->Depth.Test == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.Test = state;
+ break;
+ case GL_DITHER:
+ if (ctx->Color.DitherFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.DitherFlag = state;
+ break;
+ case GL_FOG:
+ if (ctx->Fog.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.Enabled = state;
+ break;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ if (ctx->Light.Light[cap-GL_LIGHT0].Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Light[cap-GL_LIGHT0].Enabled = state;
+ if (state) {
+ insert_at_tail(&ctx->Light.EnabledList,
+ &ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ else {
+ remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]);
+ }
+ break;
+ case GL_LIGHTING:
+ if (ctx->Light.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LIGHT);
+ ctx->Light.Enabled = state;
+ if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
+ ctx->_TriangleCaps |= DD_TRI_LIGHT_TWOSIDE;
+ else
+ ctx->_TriangleCaps &= ~DD_TRI_LIGHT_TWOSIDE;
+ break;
+ case GL_LINE_SMOOTH:
+ if (ctx->Line.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_SMOOTH;
+ break;
+ case GL_LINE_STIPPLE:
+ if (ctx->Line.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_LINE);
+ ctx->Line.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_LINE_STIPPLE;
+ break;
+ case GL_INDEX_LOGIC_OP:
+ if (ctx->Color.IndexLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.IndexLogicOpEnabled = state;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ if (ctx->Color.ColorLogicOpEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ ctx->Color.ColorLogicOpEnabled = state;
+ break;
+ case GL_MAP1_COLOR_4:
+ if (ctx->Eval.Map1Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Color4 = state;
+ break;
+ case GL_MAP1_INDEX:
+ if (ctx->Eval.Map1Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Index = state;
+ break;
+ case GL_MAP1_NORMAL:
+ if (ctx->Eval.Map1Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Normal = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ if (ctx->Eval.Map1TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord1 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ if (ctx->Eval.Map1TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord2 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ if (ctx->Eval.Map1TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord3 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ if (ctx->Eval.Map1TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1TextureCoord4 = state;
+ break;
+ case GL_MAP1_VERTEX_3:
+ if (ctx->Eval.Map1Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex3 = state;
+ break;
+ case GL_MAP1_VERTEX_4:
+ if (ctx->Eval.Map1Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Vertex4 = state;
+ break;
+ case GL_MAP2_COLOR_4:
+ if (ctx->Eval.Map2Color4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Color4 = state;
+ break;
+ case GL_MAP2_INDEX:
+ if (ctx->Eval.Map2Index == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Index = state;
+ break;
+ case GL_MAP2_NORMAL:
+ if (ctx->Eval.Map2Normal == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Normal = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ if (ctx->Eval.Map2TextureCoord1 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord1 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ if (ctx->Eval.Map2TextureCoord2 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord2 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ if (ctx->Eval.Map2TextureCoord3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord3 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ if (ctx->Eval.Map2TextureCoord4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2TextureCoord4 = state;
+ break;
+ case GL_MAP2_VERTEX_3:
+ if (ctx->Eval.Map2Vertex3 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex3 = state;
+ break;
+ case GL_MAP2_VERTEX_4:
+ if (ctx->Eval.Map2Vertex4 == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Vertex4 = state;
+ break;
+ case GL_NORMALIZE:
+ if (ctx->Transform.Normalize == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.Normalize = state;
+ break;
+ case GL_POINT_SMOOTH:
+ if (ctx->Point.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_POINT_SMOOTH;
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (ctx->Polygon.SmoothFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.SmoothFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_SMOOTH;
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (ctx->Polygon.StippleFlag == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.StippleFlag = state;
+ ctx->_TriangleCaps ^= DD_TRI_STIPPLE;
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ if (ctx->Polygon.OffsetPoint == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetPoint = state;
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ if (ctx->Polygon.OffsetLine == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetLine = state;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ if (ctx->Polygon.OffsetFill == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POLYGON);
+ ctx->Polygon.OffsetFill = state;
+ break;
+ case GL_RESCALE_NORMAL_EXT:
+ if (ctx->Transform.RescaleNormals == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RescaleNormals = state;
+ break;
+ case GL_SCISSOR_TEST:
+ if (ctx->Scissor.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_SCISSOR);
+ ctx->Scissor.Enabled = state;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ if (ctx->Texture.SharedPalette == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ ctx->Texture.SharedPalette = state;
+ break;
+ case GL_STENCIL_TEST:
+ if (ctx->Stencil.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.Enabled = state;
+ break;
+ case GL_TEXTURE_1D:
+ if (!enable_texture(ctx, state, TEXTURE_1D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_2D:
+ if (!enable_texture(ctx, state, TEXTURE_2D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_3D:
+ if (!enable_texture(ctx, state, TEXTURE_3D_BIT)) {
+ return;
+ }
+ break;
+ case GL_TEXTURE_GEN_S:
+ case GL_TEXTURE_GEN_T:
+ case GL_TEXTURE_GEN_R:
+ case GL_TEXTURE_GEN_Q:
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLbitfield coordBit = S_BIT << (cap - GL_TEXTURE_GEN_S);
+ GLbitfield newenabled = texUnit->TexGenEnabled & ~coordBit;
+ if (state)
+ newenabled |= coordBit;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+
+#if FEATURE_ES1
+ case GL_TEXTURE_GEN_STR_OES:
+ /* disable S, T, and R at the same time */
+ {
+ struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLuint newenabled =
+ texUnit->TexGenEnabled & ~STR_BITS;
+ if (state)
+ newenabled |= STR_BITS;
+ if (texUnit->TexGenEnabled == newenabled)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TEXTURE);
+ texUnit->TexGenEnabled = newenabled;
+ }
+ }
+ break;
+#endif
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_INDEX_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_EDGE_FLAG_ARRAY:
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ case GL_POINT_SIZE_ARRAY_OES:
+ client_state( ctx, cap, state );
+ return;
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map, cap);
+ if (!enable_texture(ctx, state, TEXTURE_CUBE_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program, cap);
+ if (ctx->Fog.ColorSumEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_FOG);
+ ctx->Fog.ColorSumEnabled = state;
+ break;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ if (ctx->Multisample.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.Enabled = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ if (ctx->Multisample.SampleAlphaToCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToCoverage = state;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ if (ctx->Multisample.SampleAlphaToOne == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleAlphaToOne = state;
+ break;
+ case GL_SAMPLE_COVERAGE_ARB:
+ if (ctx->Multisample.SampleCoverage == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverage = state;
+ break;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ if (ctx->Multisample.SampleCoverageInvert == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleCoverageInvert = state;
+ break;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip, cap);
+ if (ctx->Transform.RasterPositionUnclipped == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.RasterPositionUnclipped = state;
+ break;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite, cap);
+ if (ctx->Point.PointSprite == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_POINT);
+ ctx->Point.PointSprite = state;
+ break;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.Enabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.PointSizeEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.PointSizeEnabled = state;
+ break;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program, cap);
+ if (ctx->VertexProgram.TwoSideEnabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->VertexProgram.TwoSideEnabled = state;
+ break;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map1Attrib[map] = state;
+ }
+ break;
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program, cap);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ FLUSH_VERTICES(ctx, _NEW_EVAL);
+ ctx->Eval.Map2Attrib[map] = state;
+ }
+ break;
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle, cap);
+ if (!enable_texture(ctx, state, TEXTURE_RECT_BIT)) {
+ return;
+ }
+ break;
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side, cap);
+ if (ctx->Stencil.TestTwoSide == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_STENCIL);
+ ctx->Stencil.TestTwoSide = state;
+ if (state) {
+ ctx->Stencil._BackFace = 2;
+ ctx->_TriangleCaps |= DD_TRI_TWOSTENCIL;
+ } else {
+ ctx->Stencil._BackFace = 1;
+ ctx->_TriangleCaps &= ~DD_TRI_TWOSTENCIL;
+ }
+ break;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ CHECK_EXTENSION(ARB_fragment_program, cap);
+ if (ctx->FragmentProgram.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->FragmentProgram.Enabled = state;
+ break;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test, cap);
+ if (ctx->Depth.BoundsTest == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_DEPTH);
+ ctx->Depth.BoundsTest = state;
+ break;
+
+ case GL_DEPTH_CLAMP:
+ if (ctx->Transform.DepthClamp == state)
+ return;
+ CHECK_EXTENSION(ARB_depth_clamp, cap);
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Transform.DepthClamp = state;
+ break;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader, cap);
+ if (ctx->ATIFragmentShader.Enabled == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_PROGRAM);
+ ctx->ATIFragmentShader.Enabled = state;
+ break;
+#endif
+
+ /* GL_MESA_texture_array */
+ case GL_TEXTURE_1D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_1D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_2D_ARRAY_EXT:
+ CHECK_EXTENSION(MESA_texture_array, cap);
+ if (!enable_texture(ctx, state, TEXTURE_2D_ARRAY_BIT)) {
+ return;
+ }
+ break;
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map, cap);
+ ctx->Texture.CubeMapSeamless = state;
+ break;
+
+#if FEATURE_EXT_transform_feedback
+ case GL_RASTERIZER_DISCARD:
+ CHECK_EXTENSION(EXT_transform_feedback, cap);
+ if (ctx->TransformFeedback.RasterDiscard != state) {
+ ctx->TransformFeedback.RasterDiscard = state;
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ }
+ break;
+#endif
+
+ /* GL 3.1 primitive restart. Note: this enum is different from
+ * GL_PRIMITIVE_RESTART_NV (which is client state).
+ */
+ case GL_PRIMITIVE_RESTART:
+ if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
+ goto invalid_enum_error;
+ }
+ if (ctx->Array.PrimitiveRestart != state) {
+ FLUSH_VERTICES(ctx, _NEW_TRANSFORM);
+ ctx->Array.PrimitiveRestart = state;
+ }
+ break;
+
+ /* GL3.0 - GL_framebuffer_sRGB */
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ CHECK_EXTENSION(EXT_framebuffer_sRGB, cap);
+ FLUSH_VERTICES(ctx, _NEW_BUFFERS);
+ ctx->Color.sRGBEnabled = state;
+ break;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ if (ctx->Driver.Enable) {
+ ctx->Driver.Enable( ctx, cap, state );
+ }
+
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%s(0x%x)",
+ state ? "Enable" : "Disable", cap);
+}
+
+
+/**
+ * Enable GL capability. Called by glEnable()
+ * \param cap state to enable.
+ */
+void GLAPIENTRY
+_mesa_Enable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_TRUE );
+}
+
+
+/**
+ * Disable GL capability. Called by glDisable()
+ * \param cap state to disable.
+ */
+void GLAPIENTRY
+_mesa_Disable( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ _mesa_set_enable( ctx, cap, GL_FALSE );
+}
+
+
+
+/**
+ * Enable/disable an indexed state var.
+ */
+void
+_mesa_set_enablei(struct gl_context *ctx, GLenum cap,
+ GLuint index, GLboolean state)
+{
+ ASSERT(state == 0 || state == 1);
+ switch (cap) {
+ case GL_BLEND:
+ if (!ctx->Extensions.EXT_draw_buffers2) {
+ goto invalid_enum_error;
+ }
+ if (index >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)",
+ state ? "glEnableIndexed" : "glDisableIndexed", index);
+ return;
+ }
+ if (((ctx->Color.BlendEnabled >> index) & 1) != state) {
+ FLUSH_VERTICES(ctx, _NEW_COLOR);
+ if (state)
+ ctx->Color.BlendEnabled |= (1 << index);
+ else
+ ctx->Color.BlendEnabled &= ~(1 << index);
+ }
+ break;
+ default:
+ goto invalid_enum_error;
+ }
+ return;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(cap=%s)",
+ state ? "glEnablei" : "glDisablei",
+ _mesa_lookup_enum_by_nr(cap));
+}
+
+
+void GLAPIENTRY
+_mesa_DisableIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ _mesa_set_enablei(ctx, cap, index, GL_FALSE);
+}
+
+
+void GLAPIENTRY
+_mesa_EnableIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+ _mesa_set_enablei(ctx, cap, index, GL_TRUE);
+}
+
+
+GLboolean GLAPIENTRY
+_mesa_IsEnabledIndexed( GLenum cap, GLuint index )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ switch (cap) {
+ case GL_BLEND:
+ if (index >= ctx->Const.MaxDrawBuffers) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glIsEnabledIndexed(index=%u)",
+ index);
+ return GL_FALSE;
+ }
+ return (ctx->Color.BlendEnabled >> index) & 1;
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabledIndexed(cap=%s)",
+ _mesa_lookup_enum_by_nr(cap));
+ return GL_FALSE;
+ }
+}
+
+
+
+
+#undef CHECK_EXTENSION
+#define CHECK_EXTENSION(EXTNAME) \
+ if (!ctx->Extensions.EXTNAME) { \
+ goto invalid_enum_error; \
+ }
+
+#undef CHECK_EXTENSION2
+#define CHECK_EXTENSION2(EXT1, EXT2) \
+ if (!ctx->Extensions.EXT1 && !ctx->Extensions.EXT2) { \
+ goto invalid_enum_error; \
+ }
+
+
+/**
+ * Helper function to determine whether a texture target is enabled.
+ */
+static GLboolean
+is_texture_enabled(struct gl_context *ctx, GLbitfield bit)
+{
+ const struct gl_texture_unit *const texUnit =
+ &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & bit) ? GL_TRUE : GL_FALSE;
+}
+
+
+/**
+ * Return simple enable/disable state.
+ *
+ * \param cap state variable to query.
+ *
+ * Returns the state of the specified capability from the current GL context.
+ * For the capabilities associated with extensions verifies that those
+ * extensions are effectively present before reporting.
+ */
+GLboolean GLAPIENTRY
+_mesa_IsEnabled( GLenum cap )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ return ctx->Color.AlphaEnabled;
+ case GL_AUTO_NORMAL:
+ return ctx->Eval.AutoNormal;
+ case GL_BLEND:
+ return ctx->Color.BlendEnabled & 1; /* return state for buffer[0] */
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ return (ctx->Transform.ClipPlanesEnabled >> (cap - GL_CLIP_PLANE0)) & 1;
+ case GL_COLOR_MATERIAL:
+ return ctx->Light.ColorMaterialEnabled;
+ case GL_CULL_FACE:
+ return ctx->Polygon.CullFlag;
+ case GL_DEPTH_TEST:
+ return ctx->Depth.Test;
+ case GL_DITHER:
+ return ctx->Color.DitherFlag;
+ case GL_FOG:
+ return ctx->Fog.Enabled;
+ case GL_LIGHTING:
+ return ctx->Light.Enabled;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ return ctx->Light.Light[cap-GL_LIGHT0].Enabled;
+ case GL_LINE_SMOOTH:
+ return ctx->Line.SmoothFlag;
+ case GL_LINE_STIPPLE:
+ return ctx->Line.StippleFlag;
+ case GL_INDEX_LOGIC_OP:
+ return ctx->Color.IndexLogicOpEnabled;
+ case GL_COLOR_LOGIC_OP:
+ return ctx->Color.ColorLogicOpEnabled;
+ case GL_MAP1_COLOR_4:
+ return ctx->Eval.Map1Color4;
+ case GL_MAP1_INDEX:
+ return ctx->Eval.Map1Index;
+ case GL_MAP1_NORMAL:
+ return ctx->Eval.Map1Normal;
+ case GL_MAP1_TEXTURE_COORD_1:
+ return ctx->Eval.Map1TextureCoord1;
+ case GL_MAP1_TEXTURE_COORD_2:
+ return ctx->Eval.Map1TextureCoord2;
+ case GL_MAP1_TEXTURE_COORD_3:
+ return ctx->Eval.Map1TextureCoord3;
+ case GL_MAP1_TEXTURE_COORD_4:
+ return ctx->Eval.Map1TextureCoord4;
+ case GL_MAP1_VERTEX_3:
+ return ctx->Eval.Map1Vertex3;
+ case GL_MAP1_VERTEX_4:
+ return ctx->Eval.Map1Vertex4;
+ case GL_MAP2_COLOR_4:
+ return ctx->Eval.Map2Color4;
+ case GL_MAP2_INDEX:
+ return ctx->Eval.Map2Index;
+ case GL_MAP2_NORMAL:
+ return ctx->Eval.Map2Normal;
+ case GL_MAP2_TEXTURE_COORD_1:
+ return ctx->Eval.Map2TextureCoord1;
+ case GL_MAP2_TEXTURE_COORD_2:
+ return ctx->Eval.Map2TextureCoord2;
+ case GL_MAP2_TEXTURE_COORD_3:
+ return ctx->Eval.Map2TextureCoord3;
+ case GL_MAP2_TEXTURE_COORD_4:
+ return ctx->Eval.Map2TextureCoord4;
+ case GL_MAP2_VERTEX_3:
+ return ctx->Eval.Map2Vertex3;
+ case GL_MAP2_VERTEX_4:
+ return ctx->Eval.Map2Vertex4;
+ case GL_NORMALIZE:
+ return ctx->Transform.Normalize;
+ case GL_POINT_SMOOTH:
+ return ctx->Point.SmoothFlag;
+ case GL_POLYGON_SMOOTH:
+ return ctx->Polygon.SmoothFlag;
+ case GL_POLYGON_STIPPLE:
+ return ctx->Polygon.StippleFlag;
+ case GL_POLYGON_OFFSET_POINT:
+ return ctx->Polygon.OffsetPoint;
+ case GL_POLYGON_OFFSET_LINE:
+ return ctx->Polygon.OffsetLine;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ return ctx->Polygon.OffsetFill;
+ case GL_RESCALE_NORMAL_EXT:
+ return ctx->Transform.RescaleNormals;
+ case GL_SCISSOR_TEST:
+ return ctx->Scissor.Enabled;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ return ctx->Texture.SharedPalette;
+ case GL_STENCIL_TEST:
+ return ctx->Stencil.Enabled;
+ case GL_TEXTURE_1D:
+ return is_texture_enabled(ctx, TEXTURE_1D_BIT);
+ case GL_TEXTURE_2D:
+ return is_texture_enabled(ctx, TEXTURE_2D_BIT);
+ case GL_TEXTURE_3D:
+ return is_texture_enabled(ctx, TEXTURE_3D_BIT);
+ case GL_TEXTURE_GEN_S:
+ case GL_TEXTURE_GEN_T:
+ case GL_TEXTURE_GEN_R:
+ case GL_TEXTURE_GEN_Q:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ GLbitfield coordBit = S_BIT << (cap - GL_TEXTURE_GEN_S);
+ return (texUnit->TexGenEnabled & coordBit) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ return GL_FALSE;
+#if FEATURE_ES1
+ case GL_TEXTURE_GEN_STR_OES:
+ {
+ const struct gl_texture_unit *texUnit = get_texcoord_unit(ctx);
+ if (texUnit) {
+ return (texUnit->TexGenEnabled & STR_BITS) == STR_BITS
+ ? GL_TRUE : GL_FALSE;
+ }
+ }
+#endif
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ return (ctx->Array.ArrayObj->Vertex.Enabled != 0);
+ case GL_NORMAL_ARRAY:
+ return (ctx->Array.ArrayObj->Normal.Enabled != 0);
+ case GL_COLOR_ARRAY:
+ return (ctx->Array.ArrayObj->Color.Enabled != 0);
+ case GL_INDEX_ARRAY:
+ return (ctx->Array.ArrayObj->Index.Enabled != 0);
+ case GL_TEXTURE_COORD_ARRAY:
+ return (ctx->Array.ArrayObj->TexCoord[ctx->Array.ActiveTexture]
+ .Enabled != 0);
+ case GL_EDGE_FLAG_ARRAY:
+ return (ctx->Array.ArrayObj->EdgeFlag.Enabled != 0);
+ case GL_FOG_COORDINATE_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_fog_coord);
+ return (ctx->Array.ArrayObj->FogCoord.Enabled != 0);
+ case GL_SECONDARY_COLOR_ARRAY_EXT:
+ CHECK_EXTENSION(EXT_secondary_color);
+ return (ctx->Array.ArrayObj->SecondaryColor.Enabled != 0);
+#if FEATURE_point_size_array
+ case GL_POINT_SIZE_ARRAY_OES:
+ return (ctx->Array.ArrayObj->PointSize.Enabled != 0);
+#endif
+
+ /* GL_ARB_texture_cube_map */
+ case GL_TEXTURE_CUBE_MAP_ARB:
+ CHECK_EXTENSION(ARB_texture_cube_map);
+ return is_texture_enabled(ctx, TEXTURE_CUBE_BIT);
+
+ /* GL_EXT_secondary_color */
+ case GL_COLOR_SUM_EXT:
+ CHECK_EXTENSION2(EXT_secondary_color, ARB_vertex_program);
+ return ctx->Fog.ColorSumEnabled;
+
+ /* GL_ARB_multisample */
+ case GL_MULTISAMPLE_ARB:
+ return ctx->Multisample.Enabled;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE_ARB:
+ return ctx->Multisample.SampleAlphaToCoverage;
+ case GL_SAMPLE_ALPHA_TO_ONE_ARB:
+ return ctx->Multisample.SampleAlphaToOne;
+ case GL_SAMPLE_COVERAGE_ARB:
+ return ctx->Multisample.SampleCoverage;
+ case GL_SAMPLE_COVERAGE_INVERT_ARB:
+ return ctx->Multisample.SampleCoverageInvert;
+
+ /* GL_IBM_rasterpos_clip */
+ case GL_RASTER_POSITION_UNCLIPPED_IBM:
+ CHECK_EXTENSION(IBM_rasterpos_clip);
+ return ctx->Transform.RasterPositionUnclipped;
+
+ /* GL_NV_point_sprite */
+ case GL_POINT_SPRITE_NV:
+ CHECK_EXTENSION2(NV_point_sprite, ARB_point_sprite)
+ return ctx->Point.PointSprite;
+
+#if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program
+ case GL_VERTEX_PROGRAM_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.Enabled;
+ case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.PointSizeEnabled;
+ case GL_VERTEX_PROGRAM_TWO_SIDE_ARB:
+ CHECK_EXTENSION2(ARB_vertex_program, NV_vertex_program);
+ return ctx->VertexProgram.TwoSideEnabled;
+#endif
+#if FEATURE_NV_vertex_program
+ case GL_VERTEX_ATTRIB_ARRAY0_NV:
+ case GL_VERTEX_ATTRIB_ARRAY1_NV:
+ case GL_VERTEX_ATTRIB_ARRAY2_NV:
+ case GL_VERTEX_ATTRIB_ARRAY3_NV:
+ case GL_VERTEX_ATTRIB_ARRAY4_NV:
+ case GL_VERTEX_ATTRIB_ARRAY5_NV:
+ case GL_VERTEX_ATTRIB_ARRAY6_NV:
+ case GL_VERTEX_ATTRIB_ARRAY7_NV:
+ case GL_VERTEX_ATTRIB_ARRAY8_NV:
+ case GL_VERTEX_ATTRIB_ARRAY9_NV:
+ case GL_VERTEX_ATTRIB_ARRAY10_NV:
+ case GL_VERTEX_ATTRIB_ARRAY11_NV:
+ case GL_VERTEX_ATTRIB_ARRAY12_NV:
+ case GL_VERTEX_ATTRIB_ARRAY13_NV:
+ case GL_VERTEX_ATTRIB_ARRAY14_NV:
+ case GL_VERTEX_ATTRIB_ARRAY15_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ GLint n = (GLint) cap - GL_VERTEX_ATTRIB_ARRAY0_NV;
+ ASSERT(n < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ return (ctx->Array.ArrayObj->VertexAttrib[n].Enabled != 0);
+ }
+ case GL_MAP1_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP1_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP1_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map1Attrib[map];
+ }
+ case GL_MAP2_VERTEX_ATTRIB0_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB1_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB2_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB3_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB4_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB5_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB6_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB7_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB8_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB9_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB10_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB11_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB12_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB13_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB14_4_NV:
+ case GL_MAP2_VERTEX_ATTRIB15_4_NV:
+ CHECK_EXTENSION(NV_vertex_program);
+ {
+ const GLuint map = (GLuint) (cap - GL_MAP2_VERTEX_ATTRIB0_4_NV);
+ return ctx->Eval.Map2Attrib[map];
+ }
+#endif /* FEATURE_NV_vertex_program */
+
+#if FEATURE_NV_fragment_program
+ case GL_FRAGMENT_PROGRAM_NV:
+ CHECK_EXTENSION(NV_fragment_program);
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_NV_fragment_program */
+
+ /* GL_NV_texture_rectangle */
+ case GL_TEXTURE_RECTANGLE_NV:
+ CHECK_EXTENSION(NV_texture_rectangle);
+ return is_texture_enabled(ctx, TEXTURE_RECT_BIT);
+
+ /* GL_EXT_stencil_two_side */
+ case GL_STENCIL_TEST_TWO_SIDE_EXT:
+ CHECK_EXTENSION(EXT_stencil_two_side);
+ return ctx->Stencil.TestTwoSide;
+
+#if FEATURE_ARB_fragment_program
+ case GL_FRAGMENT_PROGRAM_ARB:
+ return ctx->FragmentProgram.Enabled;
+#endif /* FEATURE_ARB_fragment_program */
+
+ /* GL_EXT_depth_bounds_test */
+ case GL_DEPTH_BOUNDS_TEST_EXT:
+ CHECK_EXTENSION(EXT_depth_bounds_test);
+ return ctx->Depth.BoundsTest;
+
+ /* GL_ARB_depth_clamp */
+ case GL_DEPTH_CLAMP:
+ CHECK_EXTENSION(ARB_depth_clamp);
+ return ctx->Transform.DepthClamp;
+
+#if FEATURE_ATI_fragment_shader
+ case GL_FRAGMENT_SHADER_ATI:
+ CHECK_EXTENSION(ATI_fragment_shader);
+ return ctx->ATIFragmentShader.Enabled;
+#endif /* FEATURE_ATI_fragment_shader */
+
+ case GL_TEXTURE_CUBE_MAP_SEAMLESS:
+ CHECK_EXTENSION(ARB_seamless_cube_map);
+ return ctx->Texture.CubeMapSeamless;
+
+#if FEATURE_EXT_transform_feedback
+ case GL_RASTERIZER_DISCARD:
+ CHECK_EXTENSION(EXT_transform_feedback);
+ return ctx->TransformFeedback.RasterDiscard;
+#endif
+
+ /* GL_NV_primitive_restart */
+ case GL_PRIMITIVE_RESTART_NV:
+ if (!ctx->Extensions.NV_primitive_restart) {
+ goto invalid_enum_error;
+ }
+ return ctx->Array.PrimitiveRestart;
+
+ /* GL 3.1 primitive restart */
+ case GL_PRIMITIVE_RESTART:
+ if (ctx->VersionMajor * 10 + ctx->VersionMinor < 31) {
+ goto invalid_enum_error;
+ }
+ return ctx->Array.PrimitiveRestart;
+
+ /* GL3.0 - GL_framebuffer_sRGB */
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ CHECK_EXTENSION(EXT_framebuffer_sRGB);
+ return ctx->Color.sRGBEnabled;
+
+ default:
+ goto invalid_enum_error;
+ }
+
+ return GL_FALSE;
+
+invalid_enum_error:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
+ return GL_FALSE;
+}
diff --git a/mesalib/src/mesa/main/fog.c b/mesalib/src/mesa/main/fog.c index b4356c198..70603576c 100644 --- a/mesalib/src/mesa/main/fog.c +++ b/mesalib/src/mesa/main/fog.c @@ -79,12 +79,17 @@ _mesa_Fogiv(GLenum pname, const GLint *params ) }
-#define UPDATE_FOG_SCALE(ctx) do {\
- if (ctx->Fog.End == ctx->Fog.Start)\
- ctx->Fog._Scale = 1.0f;\
- else\
- ctx->Fog._Scale = 1.0f / (ctx->Fog.End - ctx->Fog.Start);\
- } while(0)
+/**
+ * Update the gl_fog_attrib::_Scale field.
+ */
+static void
+update_fog_scale(struct gl_context *ctx)
+{
+ if (ctx->Fog.End == ctx->Fog.Start)
+ ctx->Fog._Scale = 1.0f;
+ else
+ ctx->Fog._Scale = 1.0f / (ctx->Fog.End - ctx->Fog.Start);
+}
void GLAPIENTRY
@@ -126,14 +131,14 @@ _mesa_Fogfv( GLenum pname, const GLfloat *params ) return;
FLUSH_VERTICES(ctx, _NEW_FOG);
ctx->Fog.Start = *params;
- UPDATE_FOG_SCALE(ctx);
+ update_fog_scale(ctx);
break;
case GL_FOG_END:
if (ctx->Fog.End == *params)
return;
FLUSH_VERTICES(ctx, _NEW_FOG);
ctx->Fog.End = *params;
- UPDATE_FOG_SCALE(ctx);
+ update_fog_scale(ctx);
break;
case GL_FOG_INDEX:
if (ctx->Fog.Index == *params)
diff --git a/mesalib/src/mesa/main/imports.c b/mesalib/src/mesa/main/imports.c index bf89815f2..2935525cc 100644 --- a/mesalib/src/mesa/main/imports.c +++ b/mesalib/src/mesa/main/imports.c @@ -1,1028 +1,1034 @@ -/** - * \file imports.c - * Standard C library function wrappers. - * - * Imports are services which the device driver or window system or - * operating system provides to the core renderer. The core renderer (Mesa) - * will call these functions in order to do memory allocation, simple I/O, - * etc. - * - * Some drivers will want to override/replace this file with something - * specialized, but that'll be rare. - * - * Eventually, I want to move roll the glheader.h file into this. - * - * \todo Functions still needed: - * - scanf - * - qsort - * - rand and RAND_MAX - */ - -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - - -#include "imports.h" -#include "context.h" -#include "mtypes.h" -#include "version.h" - -#ifdef _GNU_SOURCE -#include <locale.h> -#ifdef __APPLE__ -#include <xlocale.h> -#endif -#endif - - -#define MAXSTRING 4000 /* for vsnprintf() */ - -#ifdef WIN32 -#define vsnprintf _vsnprintf -#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 ) -extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg); -#ifdef __VMS -#include "vsnprintf.c" -#endif -#endif - -/**********************************************************************/ -/** \name Memory */ -/*@{*/ - -/** - * Allocate aligned memory. - * - * \param bytes number of bytes to allocate. - * \param alignment alignment (must be greater than zero). - * - * Allocates extra memory to accommodate rounding up the address for - * alignment and to record the real malloc address. - * - * \sa _mesa_align_free(). - */ -void * -_mesa_align_malloc(size_t bytes, unsigned long alignment) -{ -#if defined(HAVE_POSIX_MEMALIGN) - void *mem; - int err = posix_memalign(& mem, alignment, bytes); - if (err) - return NULL; - return mem; -#elif defined(_WIN32) && defined(_MSC_VER) - return _aligned_malloc(bytes, alignment); -#else - uintptr_t ptr, buf; - - ASSERT( alignment > 0 ); - - ptr = (uintptr_t) malloc(bytes + alignment + sizeof(void *)); - if (!ptr) - return NULL; - - buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); - *(uintptr_t *)(buf - sizeof(void *)) = ptr; - -#ifdef DEBUG - /* mark the non-aligned area */ - while ( ptr < buf - sizeof(void *) ) { - *(unsigned long *)ptr = 0xcdcdcdcd; - ptr += sizeof(unsigned long); - } -#endif - - return (void *) buf; -#endif /* defined(HAVE_POSIX_MEMALIGN) */ -} - -/** - * Same as _mesa_align_malloc(), but using calloc(1, ) instead of - * malloc() - */ -void * -_mesa_align_calloc(size_t bytes, unsigned long alignment) -{ -#if defined(HAVE_POSIX_MEMALIGN) - void *mem; - - mem = _mesa_align_malloc(bytes, alignment); - if (mem != NULL) { - (void) memset(mem, 0, bytes); - } - - return mem; -#elif defined(_WIN32) && defined(_MSC_VER) - void *mem; - - mem = _aligned_malloc(bytes, alignment); - if (mem != NULL) { - (void) memset(mem, 0, bytes); - } - - return mem; -#else - uintptr_t ptr, buf; - - ASSERT( alignment > 0 ); - - ptr = (uintptr_t) calloc(1, bytes + alignment + sizeof(void *)); - if (!ptr) - return NULL; - - buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1); - *(uintptr_t *)(buf - sizeof(void *)) = ptr; - -#ifdef DEBUG - /* mark the non-aligned area */ - while ( ptr < buf - sizeof(void *) ) { - *(unsigned long *)ptr = 0xcdcdcdcd; - ptr += sizeof(unsigned long); - } -#endif - - return (void *)buf; -#endif /* defined(HAVE_POSIX_MEMALIGN) */ -} - -/** - * Free memory which was allocated with either _mesa_align_malloc() - * or _mesa_align_calloc(). - * \param ptr pointer to the memory to be freed. - * The actual address to free is stored in the word immediately before the - * address the client sees. - */ -void -_mesa_align_free(void *ptr) -{ -#if defined(HAVE_POSIX_MEMALIGN) - free(ptr); -#elif defined(_WIN32) && defined(_MSC_VER) - _aligned_free(ptr); -#else - void **cubbyHole = (void **) ((char *) ptr - sizeof(void *)); - void *realAddr = *cubbyHole; - free(realAddr); -#endif /* defined(HAVE_POSIX_MEMALIGN) */ -} - -/** - * Reallocate memory, with alignment. - */ -void * -_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize, - unsigned long alignment) -{ -#if defined(_WIN32) && defined(_MSC_VER) - (void) oldSize; - return _aligned_realloc(oldBuffer, newSize, alignment); -#else - const size_t copySize = (oldSize < newSize) ? oldSize : newSize; - void *newBuf = _mesa_align_malloc(newSize, alignment); - if (newBuf && oldBuffer && copySize > 0) { - memcpy(newBuf, oldBuffer, copySize); - } - if (oldBuffer) - _mesa_align_free(oldBuffer); - return newBuf; -#endif -} - - - -/** Reallocate memory */ -void * -_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize) -{ - const size_t copySize = (oldSize < newSize) ? oldSize : newSize; - void *newBuffer = malloc(newSize); - if (newBuffer && oldBuffer && copySize > 0) - memcpy(newBuffer, oldBuffer, copySize); - if (oldBuffer) - free(oldBuffer); - return newBuffer; -} - -/** - * Fill memory with a constant 16bit word. - * \param dst destination pointer. - * \param val value. - * \param n number of words. - */ -void -_mesa_memset16( unsigned short *dst, unsigned short val, size_t n ) -{ - while (n-- > 0) - *dst++ = val; -} - -/*@}*/ - - -/**********************************************************************/ -/** \name Math */ -/*@{*/ - -/** Wrapper around sqrt() */ -double -_mesa_sqrtd(double x) -{ - return sqrt(x); -} - - -/* - * A High Speed, Low Precision Square Root - * by Paul Lalonde and Robert Dawson - * from "Graphics Gems", Academic Press, 1990 - * - * SPARC implementation of a fast square root by table - * lookup. - * SPARC floating point format is as follows: - * - * BIT 31 30 23 22 0 - * sign exponent mantissa - */ -static short sqrttab[0x100]; /* declare table of square roots */ - -void -_mesa_init_sqrt_table(void) -{ -#if defined(USE_IEEE) && !defined(DEBUG) - unsigned short i; - fi_type fi; /* to access the bits of a float in C quickly */ - /* we use a union defined in glheader.h */ - - for(i=0; i<= 0x7f; i++) { - fi.i = 0; - - /* - * Build a float with the bit pattern i as mantissa - * and an exponent of 0, stored as 127 - */ - - fi.i = (i << 16) | (127 << 23); - fi.f = _mesa_sqrtd(fi.f); - - /* - * Take the square root then strip the first 7 bits of - * the mantissa into the table - */ - - sqrttab[i] = (fi.i & 0x7fffff) >> 16; - - /* - * Repeat the process, this time with an exponent of - * 1, stored as 128 - */ - - fi.i = 0; - fi.i = (i << 16) | (128 << 23); - fi.f = sqrt(fi.f); - sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16; - } -#else - (void) sqrttab; /* silence compiler warnings */ -#endif /*HAVE_FAST_MATH*/ -} - - -/** - * Single precision square root. - */ -float -_mesa_sqrtf( float x ) -{ -#if defined(USE_IEEE) && !defined(DEBUG) - fi_type num; - /* to access the bits of a float in C - * we use a union from glheader.h */ - - short e; /* the exponent */ - if (x == 0.0F) return 0.0F; /* check for square root of 0 */ - num.f = x; - e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */ - /* exponent is stored with 127 added */ - num.i &= 0x7fffff; /* leave only the mantissa */ - if (e & 0x01) num.i |= 0x800000; - /* the exponent is odd so we have to */ - /* look it up in the second half of */ - /* the lookup table, so we set the */ - /* high bit */ - e >>= 1; /* divide the exponent by two */ - /* note that in C the shift */ - /* operators are sign preserving */ - /* for signed operands */ - /* Do the table lookup, based on the quaternary mantissa, - * then reconstruct the result back into a float - */ - num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23); - - return num.f; -#else - return (float) _mesa_sqrtd((double) x); -#endif -} - - -/** - inv_sqrt - A single precision 1/sqrt routine for IEEE format floats. - written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk - and Vesa Karvonen. -*/ -float -_mesa_inv_sqrtf(float n) -{ -#if defined(USE_IEEE) && !defined(DEBUG) - float r0, x0, y0; - float r1, x1, y1; - float r2, x2, y2; -#if 0 /* not used, see below -BP */ - float r3, x3, y3; -#endif - fi_type u; - unsigned int magic; - - /* - Exponent part of the magic number - - - We want to: - 1. subtract the bias from the exponent, - 2. negate it - 3. divide by two (rounding towards -inf) - 4. add the bias back - - Which is the same as subtracting the exponent from 381 and dividing - by 2. - - floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2) - */ - - magic = 381 << 23; - - /* - Significand part of magic number - - - With the current magic number, "(magic - u.i) >> 1" will give you: - - for 1 <= u.f <= 2: 1.25 - u.f / 4 - for 2 <= u.f <= 4: 1.00 - u.f / 8 - - This isn't a bad approximation of 1/sqrt. The maximum difference from - 1/sqrt will be around .06. After three Newton-Raphson iterations, the - maximum difference is less than 4.5e-8. (Which is actually close - enough to make the following bias academic...) - - To get a better approximation you can add a bias to the magic - number. For example, if you subtract 1/2 of the maximum difference in - the first approximation (.03), you will get the following function: - - for 1 <= u.f <= 2: 1.22 - u.f / 4 - for 2 <= u.f <= 3.76: 0.97 - u.f / 8 - for 3.76 <= u.f <= 4: 0.72 - u.f / 16 - (The 3.76 to 4 range is where the result is < .5.) - - This is the closest possible initial approximation, but with a maximum - error of 8e-11 after three NR iterations, it is still not perfect. If - you subtract 0.0332281 instead of .03, the maximum error will be - 2.5e-11 after three NR iterations, which should be about as close as - is possible. - - for 1 <= u.f <= 2: 1.2167719 - u.f / 4 - for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8 - for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16 - - */ - - magic -= (int)(0.0332281 * (1 << 25)); - - u.f = n; - u.i = (magic - u.i) >> 1; - - /* - Instead of Newton-Raphson, we use Goldschmidt's algorithm, which - allows more parallelism. From what I understand, the parallelism - comes at the cost of less precision, because it lets error - accumulate across iterations. - */ - x0 = 1.0f; - y0 = 0.5f * n; - r0 = u.f; - - x1 = x0 * r0; - y1 = y0 * r0 * r0; - r1 = 1.5f - y1; - - x2 = x1 * r1; - y2 = y1 * r1 * r1; - r2 = 1.5f - y2; - -#if 1 - return x2 * r2; /* we can stop here, and be conformant -BP */ -#else - x3 = x2 * r2; - y3 = y2 * r2 * r2; - r3 = 1.5f - y3; - - return x3 * r3; -#endif -#else - return (float) (1.0 / sqrt(n)); -#endif -} - -#ifndef __GNUC__ -/** - * Find the first bit set in a word. - */ -int -_mesa_ffs(int32_t i) -{ -#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__) - register int bit = 0; - if (i != 0) { - if ((i & 0xffff) == 0) { - bit += 16; - i >>= 16; - } - if ((i & 0xff) == 0) { - bit += 8; - i >>= 8; - } - if ((i & 0xf) == 0) { - bit += 4; - i >>= 4; - } - while ((i & 1) == 0) { - bit++; - i >>= 1; - } - bit++; - } - return bit; -#else - return ffs(i); -#endif -} - - -/** - * Find position of first bit set in given value. - * XXX Warning: this function can only be used on 64-bit systems! - * \return position of least-significant bit set, starting at 1, return zero - * if no bits set. - */ -int -_mesa_ffsll(int64_t val) -{ - int bit; - - assert(sizeof(val) == 8); - - bit = _mesa_ffs((int32_t)val); - if (bit != 0) - return bit; - - bit = _mesa_ffs((int32_t)(val >> 32)); - if (bit != 0) - return 32 + bit; - - return 0; -} - - -#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4) -/** - * Return number of bits set in given GLuint. - */ -unsigned int -_mesa_bitcount(unsigned int n) -{ - unsigned int bits; - for (bits = 0; n > 0; n = n >> 1) { - bits += (n & 1); - } - return bits; -} -#endif -#endif - - -/** - * Convert a 4-byte float to a 2-byte half float. - * Based on code from: - * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html - */ -GLhalfARB -_mesa_float_to_half(float val) -{ - const fi_type fi = {val}; - const int flt_m = fi.i & 0x7fffff; - const int flt_e = (fi.i >> 23) & 0xff; - const int flt_s = (fi.i >> 31) & 0x1; - int s, e, m = 0; - GLhalfARB result; - - /* sign bit */ - s = flt_s; - - /* handle special cases */ - if ((flt_e == 0) && (flt_m == 0)) { - /* zero */ - /* m = 0; - already set */ - e = 0; - } - else if ((flt_e == 0) && (flt_m != 0)) { - /* denorm -- denorm float maps to 0 half */ - /* m = 0; - already set */ - e = 0; - } - else if ((flt_e == 0xff) && (flt_m == 0)) { - /* infinity */ - /* m = 0; - already set */ - e = 31; - } - else if ((flt_e == 0xff) && (flt_m != 0)) { - /* NaN */ - m = 1; - e = 31; - } - else { - /* regular number */ - const int new_exp = flt_e - 127; - if (new_exp < -24) { - /* this maps to 0 */ - /* m = 0; - already set */ - e = 0; - } - else if (new_exp < -14) { - /* this maps to a denorm */ - unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/ - e = 0; - switch (exp_val) { - case 0: - _mesa_warning(NULL, - "float_to_half: logical error in denorm creation!\n"); - /* m = 0; - already set */ - break; - case 1: m = 512 + (flt_m >> 14); break; - case 2: m = 256 + (flt_m >> 15); break; - case 3: m = 128 + (flt_m >> 16); break; - case 4: m = 64 + (flt_m >> 17); break; - case 5: m = 32 + (flt_m >> 18); break; - case 6: m = 16 + (flt_m >> 19); break; - case 7: m = 8 + (flt_m >> 20); break; - case 8: m = 4 + (flt_m >> 21); break; - case 9: m = 2 + (flt_m >> 22); break; - case 10: m = 1; break; - } - } - else if (new_exp > 15) { - /* map this value to infinity */ - /* m = 0; - already set */ - e = 31; - } - else { - /* regular */ - e = new_exp + 15; - m = flt_m >> 13; - } - } - - result = (s << 15) | (e << 10) | m; - return result; -} - - -/** - * Convert a 2-byte half float to a 4-byte float. - * Based on code from: - * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html - */ -float -_mesa_half_to_float(GLhalfARB val) -{ - /* XXX could also use a 64K-entry lookup table */ - const int m = val & 0x3ff; - const int e = (val >> 10) & 0x1f; - const int s = (val >> 15) & 0x1; - int flt_m, flt_e, flt_s; - fi_type fi; - float result; - - /* sign bit */ - flt_s = s; - - /* handle special cases */ - if ((e == 0) && (m == 0)) { - /* zero */ - flt_m = 0; - flt_e = 0; - } - else if ((e == 0) && (m != 0)) { - /* denorm -- denorm half will fit in non-denorm single */ - const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */ - float mantissa = ((float) (m)) / 1024.0f; - float sign = s ? -1.0f : 1.0f; - return sign * mantissa * half_denorm; - } - else if ((e == 31) && (m == 0)) { - /* infinity */ - flt_e = 0xff; - flt_m = 0; - } - else if ((e == 31) && (m != 0)) { - /* NaN */ - flt_e = 0xff; - flt_m = 1; - } - else { - /* regular */ - flt_e = e + 112; - flt_m = m << 13; - } - - fi.i = (flt_s << 31) | (flt_e << 23) | flt_m; - result = fi.f; - return result; -} - -/*@}*/ - - -/**********************************************************************/ -/** \name Sort & Search */ -/*@{*/ - -/** - * Wrapper for bsearch(). - */ -void * -_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size, - int (*compar)(const void *, const void *) ) -{ -#if defined(_WIN32_WCE) - void *mid; - int cmp; - while (nmemb) { - nmemb >>= 1; - mid = (char *)base + nmemb * size; - cmp = (*compar)(key, mid); - if (cmp == 0) - return mid; - if (cmp > 0) { - base = (char *)mid + size; - --nmemb; - } - } - return NULL; -#else - return bsearch(key, base, nmemb, size, compar); -#endif -} - -/*@}*/ - - -/**********************************************************************/ -/** \name Environment vars */ -/*@{*/ - -/** - * Wrapper for getenv(). - */ -char * -_mesa_getenv( const char *var ) -{ -#if defined(_XBOX) || defined(_WIN32_WCE) - return NULL; -#else - return getenv(var); -#endif -} - -/*@}*/ - - -/**********************************************************************/ -/** \name String */ -/*@{*/ - -/** - * Implemented using malloc() and strcpy. - * Note that NULL is handled accordingly. - */ -char * -_mesa_strdup( const char *s ) -{ - if (s) { - size_t l = strlen(s); - char *s2 = (char *) malloc(l + 1); - if (s2) - strcpy(s2, s); - return s2; - } - else { - return NULL; - } -} - -/** Wrapper around strtof() */ -float -_mesa_strtof( const char *s, char **end ) -{ -#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__) - static locale_t loc = NULL; - if (!loc) { - loc = newlocale(LC_CTYPE_MASK, "C", NULL); - } - return strtof_l(s, end, loc); -#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600) - return strtof(s, end); -#else - return (float)strtod(s, end); -#endif -} - -/** Compute simple checksum/hash for a string */ -unsigned int -_mesa_str_checksum(const char *str) -{ - /* This could probably be much better */ - unsigned int sum, i; - const char *c; - sum = i = 1; - for (c = str; *c; c++, i++) - sum += *c * (i % 100); - return sum + i; -} - - -/*@}*/ - - -/** Wrapper around vsnprintf() */ -int -_mesa_snprintf( char *str, size_t size, const char *fmt, ... ) -{ - int r; - va_list args; - va_start( args, fmt ); - r = vsnprintf( str, size, fmt, args ); - va_end( args ); - return r; -} - - -/**********************************************************************/ -/** \name Diagnostics */ -/*@{*/ - -static void -output_if_debug(const char *prefixString, const char *outputString, - GLboolean newline) -{ - static int debug = -1; - - /* Check the MESA_DEBUG environment variable if it hasn't - * been checked yet. We only have to check it once... - */ - if (debug == -1) { - char *env = _mesa_getenv("MESA_DEBUG"); - - /* In a debug build, we print warning messages *unless* - * MESA_DEBUG is 0. In a non-debug build, we don't - * print warning messages *unless* MESA_DEBUG is - * set *to any value*. - */ -#ifdef DEBUG - debug = (env != NULL && atoi(env) == 0) ? 0 : 1; -#else - debug = (env != NULL) ? 1 : 0; -#endif - } - - /* Now only print the string if we're required to do so. */ - if (debug) { - fprintf(stderr, "%s: %s", prefixString, outputString); - if (newline) - fprintf(stderr, "\n"); - -#if defined(_WIN32) && !defined(_WIN32_WCE) - /* stderr from windows applications without console is not usually - * visible, so communicate with the debugger instead */ - { - char buf[4096]; - _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : ""); - OutputDebugStringA(buf); - } -#endif - } -} - - -/** - * Return string version of GL error code. - */ -static const char * -error_string( GLenum error ) -{ - switch (error) { - case GL_NO_ERROR: - return "GL_NO_ERROR"; - case GL_INVALID_VALUE: - return "GL_INVALID_VALUE"; - case GL_INVALID_ENUM: - return "GL_INVALID_ENUM"; - case GL_INVALID_OPERATION: - return "GL_INVALID_OPERATION"; - case GL_STACK_OVERFLOW: - return "GL_STACK_OVERFLOW"; - case GL_STACK_UNDERFLOW: - return "GL_STACK_UNDERFLOW"; - case GL_OUT_OF_MEMORY: - return "GL_OUT_OF_MEMORY"; - case GL_TABLE_TOO_LARGE: - return "GL_TABLE_TOO_LARGE"; - case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: - return "GL_INVALID_FRAMEBUFFER_OPERATION"; - default: - return "unknown"; - } -} - - -/** - * When a new type of error is recorded, print a message describing - * previous errors which were accumulated. - */ -static void -flush_delayed_errors( struct gl_context *ctx ) -{ - char s[MAXSTRING]; - - if (ctx->ErrorDebugCount) { - _mesa_snprintf(s, MAXSTRING, "%d similar %s errors", - ctx->ErrorDebugCount, - error_string(ctx->ErrorValue)); - - output_if_debug("Mesa", s, GL_TRUE); - - ctx->ErrorDebugCount = 0; - } -} - - -/** - * 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()-like format string. - */ -void -_mesa_warning( struct gl_context *ctx, const char *fmtString, ... ) -{ - char str[MAXSTRING]; - va_list args; - va_start( args, fmtString ); - (void) vsnprintf( str, MAXSTRING, fmtString, args ); - va_end( args ); - - if (ctx) - flush_delayed_errors( ctx ); - - output_if_debug("Mesa warning", str, GL_TRUE); -} - - -/** - * Report an internal implementation problem. - * Prints the message to stderr via fprintf(). - * - * \param ctx GL context. - * \param fmtString problem description string. - */ -void -_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... ) -{ - va_list args; - char str[MAXSTRING]; - (void) ctx; - - va_start( args, fmtString ); - vsnprintf( str, MAXSTRING, fmtString, args ); - va_end( args ); - - fprintf(stderr, "Mesa %s implementation error: %s\n", MESA_VERSION_STRING, str); - fprintf(stderr, "Please report at bugs.freedesktop.org\n"); -} - - -/** - * 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 - * run-time via the MESA_DEBUG environment variable), report the error with - * _mesa_debug(). - * - * \param ctx the GL context. - * \param error the error value. - * \param fmtString printf() style format string, followed by optional args - */ -void -_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... ) -{ - static GLint debug = -1; - - /* Check debug environment variable only once: - */ - if (debug == -1) { - const char *debugEnv = _mesa_getenv("MESA_DEBUG"); - -#ifdef DEBUG - if (debugEnv && strstr(debugEnv, "silent")) - debug = GL_FALSE; - else - debug = GL_TRUE; -#else - if (debugEnv) - debug = GL_TRUE; - else - debug = GL_FALSE; -#endif - } - - if (debug) { - if (ctx->ErrorValue == error && - ctx->ErrorDebugFmtString == fmtString) { - ctx->ErrorDebugCount++; - } - else { - char s[MAXSTRING], s2[MAXSTRING]; - va_list args; - - flush_delayed_errors( ctx ); - - va_start(args, fmtString); - vsnprintf(s, MAXSTRING, fmtString, args); - va_end(args); - - _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s); - output_if_debug("Mesa: User error", s2, GL_TRUE); - - ctx->ErrorDebugFmtString = fmtString; - ctx->ErrorDebugCount = 0; - } - } - - _mesa_record_error(ctx, error); -} - - -/** - * Report debug information. Print error message to stderr via fprintf(). - * No-op if DEBUG mode not enabled. - * - * \param ctx GL context. - * \param fmtString printf()-style format string, followed by optional args. - */ -void -_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... ) -{ -#ifdef DEBUG - char s[MAXSTRING]; - va_list args; - va_start(args, fmtString); - vsnprintf(s, MAXSTRING, fmtString, args); - va_end(args); - output_if_debug("Mesa", s, GL_FALSE); -#endif /* DEBUG */ - (void) ctx; - (void) fmtString; -} - -/*@}*/ +/**
+ * \file imports.c
+ * Standard C library function wrappers.
+ *
+ * Imports are services which the device driver or window system or
+ * operating system provides to the core renderer. The core renderer (Mesa)
+ * will call these functions in order to do memory allocation, simple I/O,
+ * etc.
+ *
+ * Some drivers will want to override/replace this file with something
+ * specialized, but that'll be rare.
+ *
+ * Eventually, I want to move roll the glheader.h file into this.
+ *
+ * \todo Functions still needed:
+ * - scanf
+ * - qsort
+ * - rand and RAND_MAX
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+
+#include "imports.h"
+#include "context.h"
+#include "mtypes.h"
+#include "version.h"
+
+#ifdef _GNU_SOURCE
+#include <locale.h>
+#ifdef __APPLE__
+#include <xlocale.h>
+#endif
+#endif
+
+
+#define MAXSTRING 4000 /* for vsnprintf() */
+
+#ifdef WIN32
+#define vsnprintf _vsnprintf
+#elif defined(__IBMC__) || defined(__IBMCPP__) || ( defined(__VMS) && __CRTL_VER < 70312000 )
+extern int vsnprintf(char *str, size_t count, const char *fmt, va_list arg);
+#ifdef __VMS
+#include "vsnprintf.c"
+#endif
+#endif
+
+/**********************************************************************/
+/** \name Memory */
+/*@{*/
+
+/**
+ * Allocate aligned memory.
+ *
+ * \param bytes number of bytes to allocate.
+ * \param alignment alignment (must be greater than zero).
+ *
+ * Allocates extra memory to accommodate rounding up the address for
+ * alignment and to record the real malloc address.
+ *
+ * \sa _mesa_align_free().
+ */
+void *
+_mesa_align_malloc(size_t bytes, unsigned long alignment)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *mem;
+ int err = posix_memalign(& mem, alignment, bytes);
+ if (err)
+ return NULL;
+ return mem;
+#elif defined(_WIN32) && defined(_MSC_VER)
+ return _aligned_malloc(bytes, alignment);
+#else
+ uintptr_t ptr, buf;
+
+ ASSERT( alignment > 0 );
+
+ ptr = (uintptr_t) malloc(bytes + alignment + sizeof(void *));
+ if (!ptr)
+ return NULL;
+
+ buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
+ *(uintptr_t *)(buf - sizeof(void *)) = ptr;
+
+#ifdef DEBUG
+ /* mark the non-aligned area */
+ while ( ptr < buf - sizeof(void *) ) {
+ *(unsigned long *)ptr = 0xcdcdcdcd;
+ ptr += sizeof(unsigned long);
+ }
+#endif
+
+ return (void *) buf;
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Same as _mesa_align_malloc(), but using calloc(1, ) instead of
+ * malloc()
+ */
+void *
+_mesa_align_calloc(size_t bytes, unsigned long alignment)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ void *mem;
+
+ mem = _mesa_align_malloc(bytes, alignment);
+ if (mem != NULL) {
+ (void) memset(mem, 0, bytes);
+ }
+
+ return mem;
+#elif defined(_WIN32) && defined(_MSC_VER)
+ void *mem;
+
+ mem = _aligned_malloc(bytes, alignment);
+ if (mem != NULL) {
+ (void) memset(mem, 0, bytes);
+ }
+
+ return mem;
+#else
+ uintptr_t ptr, buf;
+
+ ASSERT( alignment > 0 );
+
+ ptr = (uintptr_t) calloc(1, bytes + alignment + sizeof(void *));
+ if (!ptr)
+ return NULL;
+
+ buf = (ptr + alignment + sizeof(void *)) & ~(uintptr_t)(alignment - 1);
+ *(uintptr_t *)(buf - sizeof(void *)) = ptr;
+
+#ifdef DEBUG
+ /* mark the non-aligned area */
+ while ( ptr < buf - sizeof(void *) ) {
+ *(unsigned long *)ptr = 0xcdcdcdcd;
+ ptr += sizeof(unsigned long);
+ }
+#endif
+
+ return (void *)buf;
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Free memory which was allocated with either _mesa_align_malloc()
+ * or _mesa_align_calloc().
+ * \param ptr pointer to the memory to be freed.
+ * The actual address to free is stored in the word immediately before the
+ * address the client sees.
+ */
+void
+_mesa_align_free(void *ptr)
+{
+#if defined(HAVE_POSIX_MEMALIGN)
+ free(ptr);
+#elif defined(_WIN32) && defined(_MSC_VER)
+ _aligned_free(ptr);
+#else
+ void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
+ void *realAddr = *cubbyHole;
+ free(realAddr);
+#endif /* defined(HAVE_POSIX_MEMALIGN) */
+}
+
+/**
+ * Reallocate memory, with alignment.
+ */
+void *
+_mesa_align_realloc(void *oldBuffer, size_t oldSize, size_t newSize,
+ unsigned long alignment)
+{
+#if defined(_WIN32) && defined(_MSC_VER)
+ (void) oldSize;
+ return _aligned_realloc(oldBuffer, newSize, alignment);
+#else
+ const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
+ void *newBuf = _mesa_align_malloc(newSize, alignment);
+ if (newBuf && oldBuffer && copySize > 0) {
+ memcpy(newBuf, oldBuffer, copySize);
+ }
+ if (oldBuffer)
+ _mesa_align_free(oldBuffer);
+ return newBuf;
+#endif
+}
+
+
+
+/** Reallocate memory */
+void *
+_mesa_realloc(void *oldBuffer, size_t oldSize, size_t newSize)
+{
+ const size_t copySize = (oldSize < newSize) ? oldSize : newSize;
+ void *newBuffer = malloc(newSize);
+ if (newBuffer && oldBuffer && copySize > 0)
+ memcpy(newBuffer, oldBuffer, copySize);
+ if (oldBuffer)
+ free(oldBuffer);
+ return newBuffer;
+}
+
+/**
+ * Fill memory with a constant 16bit word.
+ * \param dst destination pointer.
+ * \param val value.
+ * \param n number of words.
+ */
+void
+_mesa_memset16( unsigned short *dst, unsigned short val, size_t n )
+{
+ while (n-- > 0)
+ *dst++ = val;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Math */
+/*@{*/
+
+/** Wrapper around sqrt() */
+double
+_mesa_sqrtd(double x)
+{
+ return sqrt(x);
+}
+
+
+/*
+ * A High Speed, Low Precision Square Root
+ * by Paul Lalonde and Robert Dawson
+ * from "Graphics Gems", Academic Press, 1990
+ *
+ * SPARC implementation of a fast square root by table
+ * lookup.
+ * SPARC floating point format is as follows:
+ *
+ * BIT 31 30 23 22 0
+ * sign exponent mantissa
+ */
+static short sqrttab[0x100]; /* declare table of square roots */
+
+void
+_mesa_init_sqrt_table(void)
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ unsigned short i;
+ fi_type fi; /* to access the bits of a float in C quickly */
+ /* we use a union defined in glheader.h */
+
+ for(i=0; i<= 0x7f; i++) {
+ fi.i = 0;
+
+ /*
+ * Build a float with the bit pattern i as mantissa
+ * and an exponent of 0, stored as 127
+ */
+
+ fi.i = (i << 16) | (127 << 23);
+ fi.f = _mesa_sqrtd(fi.f);
+
+ /*
+ * Take the square root then strip the first 7 bits of
+ * the mantissa into the table
+ */
+
+ sqrttab[i] = (fi.i & 0x7fffff) >> 16;
+
+ /*
+ * Repeat the process, this time with an exponent of
+ * 1, stored as 128
+ */
+
+ fi.i = 0;
+ fi.i = (i << 16) | (128 << 23);
+ fi.f = sqrt(fi.f);
+ sqrttab[i+0x80] = (fi.i & 0x7fffff) >> 16;
+ }
+#else
+ (void) sqrttab; /* silence compiler warnings */
+#endif /*HAVE_FAST_MATH*/
+}
+
+
+/**
+ * Single precision square root.
+ */
+float
+_mesa_sqrtf( float x )
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ fi_type num;
+ /* to access the bits of a float in C
+ * we use a union from glheader.h */
+
+ short e; /* the exponent */
+ if (x == 0.0F) return 0.0F; /* check for square root of 0 */
+ num.f = x;
+ e = (num.i >> 23) - 127; /* get the exponent - on a SPARC the */
+ /* exponent is stored with 127 added */
+ num.i &= 0x7fffff; /* leave only the mantissa */
+ if (e & 0x01) num.i |= 0x800000;
+ /* the exponent is odd so we have to */
+ /* look it up in the second half of */
+ /* the lookup table, so we set the */
+ /* high bit */
+ e >>= 1; /* divide the exponent by two */
+ /* note that in C the shift */
+ /* operators are sign preserving */
+ /* for signed operands */
+ /* Do the table lookup, based on the quaternary mantissa,
+ * then reconstruct the result back into a float
+ */
+ num.i = ((sqrttab[num.i >> 16]) << 16) | ((e + 127) << 23);
+
+ return num.f;
+#else
+ return (float) _mesa_sqrtd((double) x);
+#endif
+}
+
+
+/**
+ inv_sqrt - A single precision 1/sqrt routine for IEEE format floats.
+ written by Josh Vanderhoof, based on newsgroup posts by James Van Buskirk
+ and Vesa Karvonen.
+*/
+float
+_mesa_inv_sqrtf(float n)
+{
+#if defined(USE_IEEE) && !defined(DEBUG)
+ float r0, x0, y0;
+ float r1, x1, y1;
+ float r2, x2, y2;
+#if 0 /* not used, see below -BP */
+ float r3, x3, y3;
+#endif
+ fi_type u;
+ unsigned int magic;
+
+ /*
+ Exponent part of the magic number -
+
+ We want to:
+ 1. subtract the bias from the exponent,
+ 2. negate it
+ 3. divide by two (rounding towards -inf)
+ 4. add the bias back
+
+ Which is the same as subtracting the exponent from 381 and dividing
+ by 2.
+
+ floor(-(x - 127) / 2) + 127 = floor((381 - x) / 2)
+ */
+
+ magic = 381 << 23;
+
+ /*
+ Significand part of magic number -
+
+ With the current magic number, "(magic - u.i) >> 1" will give you:
+
+ for 1 <= u.f <= 2: 1.25 - u.f / 4
+ for 2 <= u.f <= 4: 1.00 - u.f / 8
+
+ This isn't a bad approximation of 1/sqrt. The maximum difference from
+ 1/sqrt will be around .06. After three Newton-Raphson iterations, the
+ maximum difference is less than 4.5e-8. (Which is actually close
+ enough to make the following bias academic...)
+
+ To get a better approximation you can add a bias to the magic
+ number. For example, if you subtract 1/2 of the maximum difference in
+ the first approximation (.03), you will get the following function:
+
+ for 1 <= u.f <= 2: 1.22 - u.f / 4
+ for 2 <= u.f <= 3.76: 0.97 - u.f / 8
+ for 3.76 <= u.f <= 4: 0.72 - u.f / 16
+ (The 3.76 to 4 range is where the result is < .5.)
+
+ This is the closest possible initial approximation, but with a maximum
+ error of 8e-11 after three NR iterations, it is still not perfect. If
+ you subtract 0.0332281 instead of .03, the maximum error will be
+ 2.5e-11 after three NR iterations, which should be about as close as
+ is possible.
+
+ for 1 <= u.f <= 2: 1.2167719 - u.f / 4
+ for 2 <= u.f <= 3.73: 0.9667719 - u.f / 8
+ for 3.73 <= u.f <= 4: 0.7167719 - u.f / 16
+
+ */
+
+ magic -= (int)(0.0332281 * (1 << 25));
+
+ u.f = n;
+ u.i = (magic - u.i) >> 1;
+
+ /*
+ Instead of Newton-Raphson, we use Goldschmidt's algorithm, which
+ allows more parallelism. From what I understand, the parallelism
+ comes at the cost of less precision, because it lets error
+ accumulate across iterations.
+ */
+ x0 = 1.0f;
+ y0 = 0.5f * n;
+ r0 = u.f;
+
+ x1 = x0 * r0;
+ y1 = y0 * r0 * r0;
+ r1 = 1.5f - y1;
+
+ x2 = x1 * r1;
+ y2 = y1 * r1 * r1;
+ r2 = 1.5f - y2;
+
+#if 1
+ return x2 * r2; /* we can stop here, and be conformant -BP */
+#else
+ x3 = x2 * r2;
+ y3 = y2 * r2 * r2;
+ r3 = 1.5f - y3;
+
+ return x3 * r3;
+#endif
+#else
+ return (float) (1.0 / sqrt(n));
+#endif
+}
+
+#ifndef __GNUC__
+/**
+ * Find the first bit set in a word.
+ */
+int
+_mesa_ffs(int32_t i)
+{
+#if (defined(_WIN32) ) || defined(__IBMC__) || defined(__IBMCPP__)
+ register int bit = 0;
+ if (i != 0) {
+ if ((i & 0xffff) == 0) {
+ bit += 16;
+ i >>= 16;
+ }
+ if ((i & 0xff) == 0) {
+ bit += 8;
+ i >>= 8;
+ }
+ if ((i & 0xf) == 0) {
+ bit += 4;
+ i >>= 4;
+ }
+ while ((i & 1) == 0) {
+ bit++;
+ i >>= 1;
+ }
+ bit++;
+ }
+ return bit;
+#else
+ return ffs(i);
+#endif
+}
+
+
+/**
+ * Find position of first bit set in given value.
+ * XXX Warning: this function can only be used on 64-bit systems!
+ * \return position of least-significant bit set, starting at 1, return zero
+ * if no bits set.
+ */
+int
+_mesa_ffsll(int64_t val)
+{
+ int bit;
+
+ assert(sizeof(val) == 8);
+
+ bit = _mesa_ffs((int32_t)val);
+ if (bit != 0)
+ return bit;
+
+ bit = _mesa_ffs((int32_t)(val >> 32));
+ if (bit != 0)
+ return 32 + bit;
+
+ return 0;
+}
+
+
+#if ((_GNUC__ == 3 && __GNUC_MINOR__ < 4) || __GNUC__ < 4)
+/**
+ * Return number of bits set in given GLuint.
+ */
+unsigned int
+_mesa_bitcount(unsigned int n)
+{
+ unsigned int bits;
+ for (bits = 0; n > 0; n = n >> 1) {
+ bits += (n & 1);
+ }
+ return bits;
+}
+#endif
+#endif
+
+
+/**
+ * Convert a 4-byte float to a 2-byte half float.
+ * Based on code from:
+ * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
+ */
+GLhalfARB
+_mesa_float_to_half(float val)
+{
+ const fi_type fi = {val};
+ const int flt_m = fi.i & 0x7fffff;
+ const int flt_e = (fi.i >> 23) & 0xff;
+ const int flt_s = (fi.i >> 31) & 0x1;
+ int s, e, m = 0;
+ GLhalfARB result;
+
+ /* sign bit */
+ s = flt_s;
+
+ /* handle special cases */
+ if ((flt_e == 0) && (flt_m == 0)) {
+ /* zero */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if ((flt_e == 0) && (flt_m != 0)) {
+ /* denorm -- denorm float maps to 0 half */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if ((flt_e == 0xff) && (flt_m == 0)) {
+ /* infinity */
+ /* m = 0; - already set */
+ e = 31;
+ }
+ else if ((flt_e == 0xff) && (flt_m != 0)) {
+ /* NaN */
+ m = 1;
+ e = 31;
+ }
+ else {
+ /* regular number */
+ const int new_exp = flt_e - 127;
+ if (new_exp < -24) {
+ /* this maps to 0 */
+ /* m = 0; - already set */
+ e = 0;
+ }
+ else if (new_exp < -14) {
+ /* this maps to a denorm */
+ unsigned int exp_val = (unsigned int) (-14 - new_exp); /* 2^-exp_val*/
+ e = 0;
+ switch (exp_val) {
+ case 0:
+ _mesa_warning(NULL,
+ "float_to_half: logical error in denorm creation!\n");
+ /* m = 0; - already set */
+ break;
+ case 1: m = 512 + (flt_m >> 14); break;
+ case 2: m = 256 + (flt_m >> 15); break;
+ case 3: m = 128 + (flt_m >> 16); break;
+ case 4: m = 64 + (flt_m >> 17); break;
+ case 5: m = 32 + (flt_m >> 18); break;
+ case 6: m = 16 + (flt_m >> 19); break;
+ case 7: m = 8 + (flt_m >> 20); break;
+ case 8: m = 4 + (flt_m >> 21); break;
+ case 9: m = 2 + (flt_m >> 22); break;
+ case 10: m = 1; break;
+ }
+ }
+ else if (new_exp > 15) {
+ /* map this value to infinity */
+ /* m = 0; - already set */
+ e = 31;
+ }
+ else {
+ /* regular */
+ e = new_exp + 15;
+ m = flt_m >> 13;
+ }
+ }
+
+ result = (s << 15) | (e << 10) | m;
+ return result;
+}
+
+
+/**
+ * Convert a 2-byte half float to a 4-byte float.
+ * Based on code from:
+ * http://www.opengl.org/discussion_boards/ubb/Forum3/HTML/008786.html
+ */
+float
+_mesa_half_to_float(GLhalfARB val)
+{
+ /* XXX could also use a 64K-entry lookup table */
+ const int m = val & 0x3ff;
+ const int e = (val >> 10) & 0x1f;
+ const int s = (val >> 15) & 0x1;
+ int flt_m, flt_e, flt_s;
+ fi_type fi;
+ float result;
+
+ /* sign bit */
+ flt_s = s;
+
+ /* handle special cases */
+ if ((e == 0) && (m == 0)) {
+ /* zero */
+ flt_m = 0;
+ flt_e = 0;
+ }
+ else if ((e == 0) && (m != 0)) {
+ /* denorm -- denorm half will fit in non-denorm single */
+ const float half_denorm = 1.0f / 16384.0f; /* 2^-14 */
+ float mantissa = ((float) (m)) / 1024.0f;
+ float sign = s ? -1.0f : 1.0f;
+ return sign * mantissa * half_denorm;
+ }
+ else if ((e == 31) && (m == 0)) {
+ /* infinity */
+ flt_e = 0xff;
+ flt_m = 0;
+ }
+ else if ((e == 31) && (m != 0)) {
+ /* NaN */
+ flt_e = 0xff;
+ flt_m = 1;
+ }
+ else {
+ /* regular */
+ flt_e = e + 112;
+ flt_m = m << 13;
+ }
+
+ fi.i = (flt_s << 31) | (flt_e << 23) | flt_m;
+ result = fi.f;
+ return result;
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Sort & Search */
+/*@{*/
+
+/**
+ * Wrapper for bsearch().
+ */
+void *
+_mesa_bsearch( const void *key, const void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *) )
+{
+#if defined(_WIN32_WCE)
+ void *mid;
+ int cmp;
+ while (nmemb) {
+ nmemb >>= 1;
+ mid = (char *)base + nmemb * size;
+ cmp = (*compar)(key, mid);
+ if (cmp == 0)
+ return mid;
+ if (cmp > 0) {
+ base = (char *)mid + size;
+ --nmemb;
+ }
+ }
+ return NULL;
+#else
+ return bsearch(key, base, nmemb, size, compar);
+#endif
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Environment vars */
+/*@{*/
+
+/**
+ * Wrapper for getenv().
+ */
+char *
+_mesa_getenv( const char *var )
+{
+#if defined(_XBOX) || defined(_WIN32_WCE)
+ return NULL;
+#else
+ return getenv(var);
+#endif
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name String */
+/*@{*/
+
+/**
+ * Implemented using malloc() and strcpy.
+ * Note that NULL is handled accordingly.
+ */
+char *
+_mesa_strdup( const char *s )
+{
+ if (s) {
+ size_t l = strlen(s);
+ char *s2 = (char *) malloc(l + 1);
+ if (s2)
+ strcpy(s2, s);
+ return s2;
+ }
+ else {
+ return NULL;
+ }
+}
+
+/** Wrapper around strtof() */
+float
+_mesa_strtof( const char *s, char **end )
+{
+#if defined(_GNU_SOURCE) && !defined(__CYGWIN__) && !defined(__FreeBSD__)
+ static locale_t loc = NULL;
+ if (!loc) {
+ loc = newlocale(LC_CTYPE_MASK, "C", NULL);
+ }
+ return strtof_l(s, end, loc);
+#elif defined(_ISOC99_SOURCE) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
+ return strtof(s, end);
+#else
+ return (float)strtod(s, end);
+#endif
+}
+
+/** Compute simple checksum/hash for a string */
+unsigned int
+_mesa_str_checksum(const char *str)
+{
+ /* This could probably be much better */
+ unsigned int sum, i;
+ const char *c;
+ sum = i = 1;
+ for (c = str; *c; c++, i++)
+ sum += *c * (i % 100);
+ return sum + i;
+}
+
+
+/*@}*/
+
+
+/** Wrapper around vsnprintf() */
+int
+_mesa_snprintf( char *str, size_t size, const char *fmt, ... )
+{
+ int r;
+ va_list args;
+ va_start( args, fmt );
+ r = vsnprintf( str, size, fmt, args );
+ va_end( args );
+ return r;
+}
+
+
+/**********************************************************************/
+/** \name Diagnostics */
+/*@{*/
+
+static void
+output_if_debug(const char *prefixString, const char *outputString,
+ GLboolean newline)
+{
+ static int debug = -1;
+
+ /* Check the MESA_DEBUG environment variable if it hasn't
+ * been checked yet. We only have to check it once...
+ */
+ if (debug == -1) {
+ char *env = _mesa_getenv("MESA_DEBUG");
+
+ /* In a debug build, we print warning messages *unless*
+ * MESA_DEBUG is 0. In a non-debug build, we don't
+ * print warning messages *unless* MESA_DEBUG is
+ * set *to any value*.
+ */
+#ifdef DEBUG
+ debug = (env != NULL && atoi(env) == 0) ? 0 : 1;
+#else
+ debug = (env != NULL) ? 1 : 0;
+#endif
+ }
+
+ /* Now only print the string if we're required to do so. */
+ if (debug) {
+ fprintf(stderr, "%s: %s", prefixString, outputString);
+ if (newline)
+ fprintf(stderr, "\n");
+
+#if defined(_WIN32) && !defined(_WIN32_WCE)
+ /* stderr from windows applications without console is not usually
+ * visible, so communicate with the debugger instead */
+ {
+ char buf[4096];
+ _mesa_snprintf(buf, sizeof(buf), "%s: %s%s", prefixString, outputString, newline ? "\n" : "");
+ OutputDebugStringA(buf);
+ }
+#endif
+ }
+}
+
+
+/**
+ * Return string version of GL error code.
+ */
+static const char *
+error_string( GLenum error )
+{
+ switch (error) {
+ case GL_NO_ERROR:
+ return "GL_NO_ERROR";
+ case GL_INVALID_VALUE:
+ return "GL_INVALID_VALUE";
+ case GL_INVALID_ENUM:
+ return "GL_INVALID_ENUM";
+ case GL_INVALID_OPERATION:
+ return "GL_INVALID_OPERATION";
+ case GL_STACK_OVERFLOW:
+ return "GL_STACK_OVERFLOW";
+ case GL_STACK_UNDERFLOW:
+ return "GL_STACK_UNDERFLOW";
+ case GL_OUT_OF_MEMORY:
+ return "GL_OUT_OF_MEMORY";
+ case GL_TABLE_TOO_LARGE:
+ return "GL_TABLE_TOO_LARGE";
+ case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
+ return "GL_INVALID_FRAMEBUFFER_OPERATION";
+ default:
+ return "unknown";
+ }
+}
+
+
+/**
+ * When a new type of error is recorded, print a message describing
+ * previous errors which were accumulated.
+ */
+static void
+flush_delayed_errors( struct gl_context *ctx )
+{
+ char s[MAXSTRING];
+
+ if (ctx->ErrorDebugCount) {
+ _mesa_snprintf(s, MAXSTRING, "%d similar %s errors",
+ ctx->ErrorDebugCount,
+ error_string(ctx->ErrorValue));
+
+ output_if_debug("Mesa", s, GL_TRUE);
+
+ ctx->ErrorDebugCount = 0;
+ }
+}
+
+
+/**
+ * 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()-like format string.
+ */
+void
+_mesa_warning( struct gl_context *ctx, const char *fmtString, ... )
+{
+ char str[MAXSTRING];
+ va_list args;
+ va_start( args, fmtString );
+ (void) vsnprintf( str, MAXSTRING, fmtString, args );
+ va_end( args );
+
+ if (ctx)
+ flush_delayed_errors( ctx );
+
+ output_if_debug("Mesa warning", str, GL_TRUE);
+}
+
+
+/**
+ * Report an internal implementation problem.
+ * Prints the message to stderr via fprintf().
+ *
+ * \param ctx GL context.
+ * \param fmtString problem description string.
+ */
+void
+_mesa_problem( const struct gl_context *ctx, const char *fmtString, ... )
+{
+ va_list args;
+ char str[MAXSTRING];
+ static int numCalls = 0;
+
+ (void) ctx;
+
+ if (numCalls < 50) {
+ numCalls++;
+
+ va_start( args, fmtString );
+ vsnprintf( str, MAXSTRING, fmtString, args );
+ va_end( args );
+ fprintf(stderr, "Mesa %s implementation error: %s\n",
+ MESA_VERSION_STRING, str);
+ fprintf(stderr, "Please report at bugs.freedesktop.org\n");
+ }
+}
+
+
+/**
+ * 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
+ * run-time via the MESA_DEBUG environment variable), report the error with
+ * _mesa_debug().
+ *
+ * \param ctx the GL context.
+ * \param error the error value.
+ * \param fmtString printf() style format string, followed by optional args
+ */
+void
+_mesa_error( struct gl_context *ctx, GLenum error, const char *fmtString, ... )
+{
+ static GLint debug = -1;
+
+ /* Check debug environment variable only once:
+ */
+ if (debug == -1) {
+ const char *debugEnv = _mesa_getenv("MESA_DEBUG");
+
+#ifdef DEBUG
+ if (debugEnv && strstr(debugEnv, "silent"))
+ debug = GL_FALSE;
+ else
+ debug = GL_TRUE;
+#else
+ if (debugEnv)
+ debug = GL_TRUE;
+ else
+ debug = GL_FALSE;
+#endif
+ }
+
+ if (debug) {
+ if (ctx->ErrorValue == error &&
+ ctx->ErrorDebugFmtString == fmtString) {
+ ctx->ErrorDebugCount++;
+ }
+ else {
+ char s[MAXSTRING], s2[MAXSTRING];
+ va_list args;
+
+ flush_delayed_errors( ctx );
+
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+
+ _mesa_snprintf(s2, MAXSTRING, "%s in %s", error_string(error), s);
+ output_if_debug("Mesa: User error", s2, GL_TRUE);
+
+ ctx->ErrorDebugFmtString = fmtString;
+ ctx->ErrorDebugCount = 0;
+ }
+ }
+
+ _mesa_record_error(ctx, error);
+}
+
+
+/**
+ * Report debug information. Print error message to stderr via fprintf().
+ * No-op if DEBUG mode not enabled.
+ *
+ * \param ctx GL context.
+ * \param fmtString printf()-style format string, followed by optional args.
+ */
+void
+_mesa_debug( const struct gl_context *ctx, const char *fmtString, ... )
+{
+#ifdef DEBUG
+ char s[MAXSTRING];
+ va_list args;
+ va_start(args, fmtString);
+ vsnprintf(s, MAXSTRING, fmtString, args);
+ va_end(args);
+ output_if_debug("Mesa", s, GL_FALSE);
+#endif /* DEBUG */
+ (void) ctx;
+ (void) fmtString;
+}
+
+/*@}*/
diff --git a/mesalib/src/mesa/main/matrix.c b/mesalib/src/mesa/main/matrix.c index 5ac6f8108..2579b7384 100644 --- a/mesalib/src/mesa/main/matrix.c +++ b/mesalib/src/mesa/main/matrix.c @@ -140,8 +140,8 @@ _mesa_Ortho( GLdouble left, GLdouble right, * \sa glMatrixMode().
*
* Flushes the vertices, validates the parameter and updates
- * __struct gl_contextRec::CurrentStack and gl_transform_attrib::MatrixMode with the
- * specified matrix stack.
+ * __struct gl_contextRec::CurrentStack and gl_transform_attrib::MatrixMode
+ * with the specified matrix stack.
*/
void GLAPIENTRY
_mesa_MatrixMode( GLenum mode )
@@ -170,7 +170,8 @@ _mesa_MatrixMode( GLenum mode ) */
#if 0
if (ctx->Texture.CurrentUnit >= ctx->Const.MaxTextureCoordUnits) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glMatrixMode(invalid tex unit %d)",
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glMatrixMode(invalid tex unit %d)",
ctx->Texture.CurrentUnit);
return;
}
@@ -232,8 +233,8 @@ _mesa_MatrixMode( GLenum mode ) * \sa glPushMatrix().
*
* Verifies the current matrix stack is not full, and duplicates the top-most
- * matrix in the stack. Marks __struct gl_contextRec::NewState with the stack dirty
- * flag.
+ * matrix in the stack.
+ * Marks __struct gl_contextRec::NewState with the stack dirty flag.
*/
void GLAPIENTRY
_mesa_PushMatrix( void )
@@ -272,8 +273,8 @@ _mesa_PushMatrix( void ) * \sa glPopMatrix().
*
* Flushes the vertices, verifies the current matrix stack is not empty, and
- * moves the stack head down. Marks __struct gl_contextRec::NewState with the dirty
- * stack flag.
+ * moves the stack head down.
+ * Marks __struct gl_contextRec::NewState with the dirty stack flag.
*/
void GLAPIENTRY
_mesa_PopMatrix( void )
@@ -309,9 +310,9 @@ _mesa_PopMatrix( void ) *
* \sa glLoadIdentity().
*
- * Flushes the vertices and calls _math_matrix_set_identity() with the top-most
- * matrix in the current stack. Marks __struct gl_contextRec::NewState with the stack
- * dirty flag.
+ * Flushes the vertices and calls _math_matrix_set_identity() with the
+ * top-most matrix in the current stack.
+ * Marks __struct gl_contextRec::NewState with the stack dirty flag.
*/
void GLAPIENTRY
_mesa_LoadIdentity( void )
@@ -334,9 +335,9 @@ _mesa_LoadIdentity( void ) *
* \sa glLoadMatrixf().
*
- * Flushes the vertices and calls _math_matrix_loadf() with the top-most matrix
- * in the current stack and the given matrix. Marks __struct gl_contextRec::NewState
- * with the dirty stack flag.
+ * Flushes the vertices and calls _math_matrix_loadf() with the top-most
+ * matrix in the current stack and the given matrix.
+ * Marks __struct gl_contextRec::NewState with the dirty stack flag.
*/
void GLAPIENTRY
_mesa_LoadMatrixf( const GLfloat *m )
@@ -560,8 +561,8 @@ _mesa_MultTransposeMatrixdARB( const GLdouble *m ) * Calls _math_matrix_analyse() with the top-matrix of the projection matrix
* stack, and recomputes user clip positions if necessary.
*
- * \note This routine references __struct gl_contextRec::Tranform attribute values to
- * compute userclip positions in clip space, but is only called on
+ * \note This routine references __struct gl_contextRec::Tranform attribute
+ * values to compute userclip positions in clip space, but is only called on
* _NEW_PROJECTION. The _mesa_ClipPlane() function keeps these values up to
* date across changes to the __struct gl_contextRec::Transform attributes.
*/
@@ -594,8 +595,8 @@ update_projection( struct gl_context *ctx ) * \param ctx GL context.
*
* Multiplies the top matrices of the projection and model view stacks into
- * __struct gl_contextRec::_ModelProjectMatrix via _math_matrix_mul_matrix() and
- * analyzes the resulting matrix via _math_matrix_analyse().
+ * __struct gl_contextRec::_ModelProjectMatrix via _math_matrix_mul_matrix()
+ * and analyzes the resulting matrix via _math_matrix_analyse().
*/
static void
calculate_model_project_matrix( struct gl_context *ctx )
@@ -624,7 +625,7 @@ void _mesa_update_modelview_project( struct gl_context *ctx, GLuint new_state ) if (new_state & _NEW_MODELVIEW) {
_math_matrix_analyse( ctx->ModelviewMatrixStack.Top );
- /* Bring cull position uptodate.
+ /* Bring cull position up to date.
*/
TRANSFORM_POINT3( ctx->Transform.CullObjPos,
ctx->ModelviewMatrixStack.Top->inv,
@@ -635,7 +636,7 @@ void _mesa_update_modelview_project( struct gl_context *ctx, GLuint new_state ) if (new_state & _NEW_PROJECTION)
update_projection( ctx );
- /* Keep ModelviewProject uptodate always to allow tnl
+ /* Keep ModelviewProject up to date always to allow tnl
* implementations that go model->clip even when eye is required.
*/
calculate_model_project_matrix(ctx);
diff --git a/mesalib/src/mesa/main/readpix.c b/mesalib/src/mesa/main/readpix.c index 6e09a52c8..864e5b6dc 100644 --- a/mesalib/src/mesa/main/readpix.c +++ b/mesalib/src/mesa/main/readpix.c @@ -1,244 +1,244 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "glheader.h" -#include "imports.h" -#include "bufferobj.h" -#include "context.h" -#include "enums.h" -#include "readpix.h" -#include "framebuffer.h" -#include "formats.h" -#include "image.h" -#include "mtypes.h" -#include "pbo.h" -#include "state.h" - - -/** - * Do error checking of the format/type parameters to glReadPixels and - * glDrawPixels. - * \param drawing if GL_TRUE do checking for DrawPixels, else do checking - * for ReadPixels. - * \return GL_TRUE if error detected, GL_FALSE if no errors - */ -GLboolean -_mesa_error_check_format_type(struct gl_context *ctx, GLenum format, GLenum type, - GLboolean drawing) -{ - const char *readDraw = drawing ? "Draw" : "Read"; - const GLboolean reading = !drawing; - - /* state validation should have already been done */ - ASSERT(ctx->NewState == 0x0); - - if (ctx->Extensions.EXT_packed_depth_stencil - && type == GL_UNSIGNED_INT_24_8_EXT - && format != GL_DEPTH_STENCIL_EXT) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw); - return GL_TRUE; - } - - /* basic combinations test */ - if (!_mesa_is_legal_format_and_type(ctx, format, type)) { - _mesa_error(ctx, GL_INVALID_ENUM, - "gl%sPixels(format or type)", readDraw); - return GL_TRUE; - } - - /* additional checks */ - switch (format) { - case GL_RG: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_RGB: - case GL_BGR: - case GL_RGBA: - case GL_BGRA: - case GL_ABGR_EXT: - case GL_RED_INTEGER_EXT: - case GL_GREEN_INTEGER_EXT: - case GL_BLUE_INTEGER_EXT: - case GL_ALPHA_INTEGER_EXT: - case GL_RGB_INTEGER_EXT: - case GL_RGBA_INTEGER_EXT: - case GL_BGR_INTEGER_EXT: - case GL_BGRA_INTEGER_EXT: - case GL_LUMINANCE_INTEGER_EXT: - case GL_LUMINANCE_ALPHA_INTEGER_EXT: - if (!drawing) { - /* reading */ - if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(no color buffer)"); - return GL_TRUE; - } - } - break; - case GL_COLOR_INDEX: - if (drawing) { - if (ctx->PixelMaps.ItoR.Size == 0 || - ctx->PixelMaps.ItoG.Size == 0 || - ctx->PixelMaps.ItoB.Size == 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glDrawPixels(drawing color index pixels into RGB buffer)"); - return GL_TRUE; - } - } - else { - /* reading */ - if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(no color buffer)"); - return GL_TRUE; - } - /* We no longer support CI-mode color buffers so trying to read - * GL_COLOR_INDEX pixels is always an error. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(color buffer is RGB)"); - return GL_TRUE; - } - break; - case GL_STENCIL_INDEX: - if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || - (reading && !_mesa_source_buffer_exists(ctx, format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "gl%sPixels(no stencil buffer)", readDraw); - return GL_TRUE; - } - break; - case GL_DEPTH_COMPONENT: - if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "gl%sPixels(no depth buffer)", readDraw); - return GL_TRUE; - } - break; - case GL_DEPTH_STENCIL_EXT: - if (!ctx->Extensions.EXT_packed_depth_stencil || - type != GL_UNSIGNED_INT_24_8_EXT) { - _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw); - return GL_TRUE; - } - if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) || - (reading && !_mesa_source_buffer_exists(ctx, format))) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "gl%sPixels(no depth or stencil buffer)", readDraw); - return GL_TRUE; - } - break; - default: - /* this should have been caught in _mesa_is_legal_format_type() */ - _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw); - return GL_TRUE; - } - - /* no errors */ - return GL_FALSE; -} - - - -void GLAPIENTRY -_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels ) -{ - GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); - - FLUSH_CURRENT(ctx, 0); - - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", - width, height, - _mesa_lookup_enum_by_nr(format), - _mesa_lookup_enum_by_nr(type), - pixels); - - if (width < 0 || height < 0) { - _mesa_error( ctx, GL_INVALID_VALUE, - "glReadPixels(width=%d height=%d)", width, height ); - return; - } - - if (ctx->NewState) - _mesa_update_state(ctx); - - if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) { - /* found an error */ - return; - } - - /* Check that the destination format and source buffer are both - * integer-valued or both non-integer-valued. - */ - if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) { - const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; - const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format); - const GLboolean dstInteger = _mesa_is_integer_format(format); - if (dstInteger != srcInteger) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(integer / non-integer format mismatch"); - return; - } - } - - if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glReadPixels(incomplete framebuffer)" ); - return; - } - - if (!_mesa_source_buffer_exists(ctx, format)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); - return; - } - - if (width == 0 || height == 0) - return; /* nothing to do */ - - if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1, - format, type, pixels)) { - _mesa_error(ctx, GL_INVALID_OPERATION, - "glReadPixels(invalid PBO access)"); - return; - } - - if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { - /* buffer is mapped - that's an error */ - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); - return; - } - } - - ctx->Driver.ReadPixels(ctx, x, y, width, height, - format, type, &ctx->Pack, pixels); -} +/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "bufferobj.h"
+#include "context.h"
+#include "enums.h"
+#include "readpix.h"
+#include "framebuffer.h"
+#include "formats.h"
+#include "image.h"
+#include "mtypes.h"
+#include "pbo.h"
+#include "state.h"
+
+
+/**
+ * Do error checking of the format/type parameters to glReadPixels and
+ * glDrawPixels.
+ * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
+ * for ReadPixels.
+ * \return GL_TRUE if error detected, GL_FALSE if no errors
+ */
+GLboolean
+_mesa_error_check_format_type(struct gl_context *ctx, GLenum format,
+ GLenum type, GLboolean drawing)
+{
+ const char *readDraw = drawing ? "Draw" : "Read";
+ const GLboolean reading = !drawing;
+
+ /* state validation should have already been done */
+ ASSERT(ctx->NewState == 0x0);
+
+ if (ctx->Extensions.EXT_packed_depth_stencil
+ && type == GL_UNSIGNED_INT_24_8_EXT
+ && format != GL_DEPTH_STENCIL_EXT) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* basic combinations test */
+ if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "gl%sPixels(format or type)", readDraw);
+ return GL_TRUE;
+ }
+
+ /* additional checks */
+ switch (format) {
+ case GL_RG:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_BGR:
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ case GL_RED_INTEGER_EXT:
+ case GL_GREEN_INTEGER_EXT:
+ case GL_BLUE_INTEGER_EXT:
+ case GL_ALPHA_INTEGER_EXT:
+ case GL_RGB_INTEGER_EXT:
+ case GL_RGBA_INTEGER_EXT:
+ case GL_BGR_INTEGER_EXT:
+ case GL_BGRA_INTEGER_EXT:
+ case GL_LUMINANCE_INTEGER_EXT:
+ case GL_LUMINANCE_ALPHA_INTEGER_EXT:
+ if (!drawing) {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ }
+ break;
+ case GL_COLOR_INDEX:
+ if (drawing) {
+ if (ctx->PixelMaps.ItoR.Size == 0 ||
+ ctx->PixelMaps.ItoG.Size == 0 ||
+ ctx->PixelMaps.ItoB.Size == 0) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDrawPixels(drawing color index pixels into RGB buffer)");
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* reading */
+ if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(no color buffer)");
+ return GL_TRUE;
+ }
+ /* We no longer support CI-mode color buffers so trying to read
+ * GL_COLOR_INDEX pixels is always an error.
+ */
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(color buffer is RGB)");
+ return GL_TRUE;
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ case GL_DEPTH_STENCIL_EXT:
+ if (!ctx->Extensions.EXT_packed_depth_stencil ||
+ type != GL_UNSIGNED_INT_24_8_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
+ return GL_TRUE;
+ }
+ if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
+ (reading && !_mesa_source_buffer_exists(ctx, format))) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "gl%sPixels(no depth or stencil buffer)", readDraw);
+ return GL_TRUE;
+ }
+ break;
+ default:
+ /* this should have been caught in _mesa_is_legal_format_type() */
+ _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
+ return GL_TRUE;
+ }
+
+ /* no errors */
+ return GL_FALSE;
+}
+
+
+
+void GLAPIENTRY
+_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+ FLUSH_CURRENT(ctx, 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
+ width, height,
+ _mesa_lookup_enum_by_nr(format),
+ _mesa_lookup_enum_by_nr(type),
+ pixels);
+
+ if (width < 0 || height < 0) {
+ _mesa_error( ctx, GL_INVALID_VALUE,
+ "glReadPixels(width=%d height=%d)", width, height );
+ return;
+ }
+
+ if (ctx->NewState)
+ _mesa_update_state(ctx);
+
+ if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
+ /* found an error */
+ return;
+ }
+
+ /* Check that the destination format and source buffer are both
+ * integer-valued or both non-integer-valued.
+ */
+ if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
+ const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
+ const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
+ const GLboolean dstInteger = _mesa_is_integer_format(format);
+ if (dstInteger != srcInteger) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(integer / non-integer format mismatch");
+ return;
+ }
+ }
+
+ if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+ "glReadPixels(incomplete framebuffer)" );
+ return;
+ }
+
+ if (!_mesa_source_buffer_exists(ctx, format)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
+ return;
+ }
+
+ if (width == 0 || height == 0)
+ return; /* nothing to do */
+
+ if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
+ if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
+ format, type, pixels)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glReadPixels(invalid PBO access)");
+ return;
+ }
+
+ if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
+ /* buffer is mapped - that's an error */
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
+ return;
+ }
+ }
+
+ ctx->Driver.ReadPixels(ctx, x, y, width, height,
+ format, type, &ctx->Pack, pixels);
+}
diff --git a/mesalib/src/mesa/main/shaderobj.c b/mesalib/src/mesa/main/shaderobj.c index 06a2f53af..67dd5c9aa 100644 --- a/mesalib/src/mesa/main/shaderobj.c +++ b/mesalib/src/mesa/main/shaderobj.c @@ -410,6 +410,5 @@ _mesa_init_shader_object_functions(struct dd_function_table *driver) driver->DeleteShader = _mesa_delete_shader;
driver->NewShaderProgram = _mesa_new_shader_program;
driver->DeleteShaderProgram = _mesa_delete_shader_program;
- driver->CompileShader = _mesa_ir_compile_shader;
driver->LinkShader = _mesa_ir_link_shader;
}
diff --git a/mesalib/src/mesa/main/texenv.c b/mesalib/src/mesa/main/texenv.c index c802f6f3b..9caca7c11 100644 --- a/mesalib/src/mesa/main/texenv.c +++ b/mesalib/src/mesa/main/texenv.c @@ -411,9 +411,11 @@ set_combiner_scale(struct gl_context *ctx, void GLAPIENTRY
_mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param )
{
+ const GLint iparam0 = (GLint) param[0];
+ struct gl_texture_unit *texUnit;
GLuint maxUnit;
+
GET_CURRENT_CONTEXT(ctx);
- struct gl_texture_unit *texUnit;
ASSERT_OUTSIDE_BEGIN_END(ctx);
maxUnit = (target == GL_POINT_SPRITE_NV && pname == GL_COORD_REPLACE_NV)
@@ -428,14 +430,14 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) if (target == GL_TEXTURE_ENV) {
switch (pname) {
case GL_TEXTURE_ENV_MODE:
- set_env_mode(ctx, texUnit, (GLenum) (GLint) param[0]);
+ set_env_mode(ctx, texUnit, (GLenum) iparam0);
break;
case GL_TEXTURE_ENV_COLOR:
set_env_color(ctx, texUnit, param);
break;
case GL_COMBINE_RGB:
case GL_COMBINE_ALPHA:
- set_combiner_mode(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ set_combiner_mode(ctx, texUnit, pname, (GLenum) iparam0);
break;
case GL_SOURCE0_RGB:
case GL_SOURCE1_RGB:
@@ -445,7 +447,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) case GL_SOURCE1_ALPHA:
case GL_SOURCE2_ALPHA:
case GL_SOURCE3_ALPHA_NV:
- set_combiner_source(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ set_combiner_source(ctx, texUnit, pname, (GLenum) iparam0);
break;
case GL_OPERAND0_RGB:
case GL_OPERAND1_RGB:
@@ -455,7 +457,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) case GL_OPERAND1_ALPHA:
case GL_OPERAND2_ALPHA:
case GL_OPERAND3_ALPHA_NV:
- set_combiner_operand(ctx, texUnit, pname, (GLenum) (GLint) param[0]);
+ set_combiner_operand(ctx, texUnit, pname, (GLenum) iparam0);
break;
case GL_RGB_SCALE:
case GL_ALPHA_SCALE:
@@ -466,19 +468,19 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname=0x%x)", pname );
return;
}
- if (((GLenum) (GLint) param[0] < GL_TEXTURE0) ||
- ((GLenum) (GLint) param[0] > GL_TEXTURE31)) {
+ if ((iparam0 < GL_TEXTURE0) ||
+ (iparam0 > GL_TEXTURE31)) {
/* spec doesn't say this but it seems logical */
- _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
+ _mesa_error( ctx, GL_INVALID_ENUM, "glTexEnv(param=0x%x)", iparam0);
return;
}
- if (!((1 << ((GLenum) (GLint) param[0] - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", (GLenum) (GLint) param[0]);
+ if (!((1 << (iparam0 - GL_TEXTURE0)) & ctx->Const.SupportedBumpUnits)) {
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0);
return;
}
else {
FLUSH_VERTICES(ctx, _NEW_TEXTURE);
- texUnit->BumpTarget = (GLenum) (GLint) param[0];
+ texUnit->BumpTarget = iparam0;
}
break;
default:
@@ -511,19 +513,18 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) return;
}
if (pname == GL_COORD_REPLACE_NV) {
- const GLenum value = (GLenum) param[0];
- if (value == GL_TRUE || value == GL_FALSE) {
+ if (iparam0 == GL_TRUE || iparam0 == GL_FALSE) {
/* It's kind of weird to set point state via glTexEnv,
* but that's what the spec calls for.
*/
- const GLboolean state = (GLboolean) value;
+ const GLboolean state = (GLboolean) iparam0;
if (ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] == state)
return;
FLUSH_VERTICES(ctx, _NEW_POINT);
ctx->Point.CoordReplace[ctx->Texture.CurrentUnit] = state;
}
else {
- _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", value);
+ _mesa_error( ctx, GL_INVALID_VALUE, "glTexEnv(param=0x%x)", iparam0);
return;
}
}
@@ -542,7 +543,7 @@ _mesa_TexEnvfv( GLenum target, GLenum pname, const GLfloat *param ) _mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(pname),
*param,
- _mesa_lookup_enum_by_nr((GLenum) (GLint) *param));
+ _mesa_lookup_enum_by_nr((GLenum) iparam0));
/* Tell device driver about the new texture environment */
if (ctx->Driver.TexEnv) {
|