Added __glExtensionBiIsEnabled and __GLXcontext::gl_extension_bits. This

enables libGL to query which extension are exported to applications.

Refactored array-query functionality (from glGet*v) in src/glx/x11/single2.c.

Massive re-write of indirect vertex array support.  The most noticable
effect is that glDrawElements now generates DrawArrays protocol.  The
side-effects (and the main reasons for the re-work) are that it is much
easier to add support for new arrays (e.g., GL_VERTEX_ATTRIB_ARRAY,
GL_WEIGHT_ARRAY_ARB, etc.) and it is much easier to add support for the new
DrawArrays protocol (required to support ARB_vertex_buffer_object).

These changes were primarilly tested with progs/demos/isosurf.
This commit is contained in:
Ian Romanick 2005-02-22 22:36:31 +00:00
parent cb83f62e30
commit fdb07636f2
9 changed files with 2187 additions and 1358 deletions

View File

@ -36,77 +36,34 @@
#include <assert.h>
#include "glxclient.h"
#include "indirect_vertex_array.h"
/*****************************************************************************/
void __indirect_glEnableClientState(GLenum array)
static void
do_enable_disable(GLenum array, GLboolean val )
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
unsigned index = 0;
switch (array) {
case GL_COLOR_ARRAY:
ENABLE_ARRAY(state, color);
break;
case GL_EDGE_FLAG_ARRAY:
ENABLE_ARRAY(state, edgeFlag);
break;
case GL_INDEX_ARRAY:
ENABLE_ARRAY(state, index);
break;
case GL_NORMAL_ARRAY:
ENABLE_ARRAY(state, normal);
break;
case GL_TEXTURE_COORD_ARRAY:
ENABLE_TEXARRAY(state, state->vertArray.activeTexture);
break;
case GL_VERTEX_ARRAY:
ENABLE_ARRAY(state, vertex);
break;
case GL_SECONDARY_COLOR_ARRAY:
ENABLE_ARRAY(state, secondaryColor);
break;
case GL_FOG_COORD_ARRAY:
ENABLE_ARRAY(state, fogCoord);
break;
default:
__glXSetError(gc, GL_INVALID_ENUM);
if ( array == GL_TEXTURE_COORD_ARRAY ) {
index = __glXGetActiveTextureUnit( state );
}
if ( ! __glXSetArrayEnable( state, array, index, val ) ) {
__glXSetError(gc, GL_INVALID_ENUM);
}
}
void __indirect_glEnableClientState(GLenum array)
{
do_enable_disable( array, GL_TRUE );
}
void __indirect_glDisableClientState(GLenum array)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
switch (array) {
case GL_COLOR_ARRAY:
DISABLE_ARRAY(state, color);
break;
case GL_EDGE_FLAG_ARRAY:
DISABLE_ARRAY(state, edgeFlag);
break;
case GL_INDEX_ARRAY:
DISABLE_ARRAY(state, index);
break;
case GL_NORMAL_ARRAY:
DISABLE_ARRAY(state, normal);
break;
case GL_TEXTURE_COORD_ARRAY:
DISABLE_TEXARRAY(state, state->vertArray.activeTexture);
break;
case GL_VERTEX_ARRAY:
DISABLE_ARRAY(state, vertex);
break;
case GL_SECONDARY_COLOR_ARRAY:
DISABLE_ARRAY(state, secondaryColor);
break;
case GL_FOG_COORD_ARRAY:
DISABLE_ARRAY(state, fogCoord);
break;
default:
__glXSetError(gc, GL_INVALID_ENUM);
}
do_enable_disable( array, GL_FALSE );
}
/************************************************************************/
@ -129,7 +86,7 @@ void __indirect_glPushClientAttrib(GLuint mask)
sp->storeUnpack = state->storeUnpack;
}
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
sp->vertArray = state->vertArray;
__glXPushArrayState( state );
}
} else {
__glXSetError(gc, GL_STACK_OVERFLOW);
@ -156,7 +113,7 @@ void __indirect_glPopClientAttrib(void)
state->storeUnpack = sp->storeUnpack;
}
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
state->vertArray = sp->vertArray;
__glXPopArrayState( state );
}
sp->mask = 0;
@ -181,5 +138,3 @@ void __glFreeAttributeState(__GLXcontext *gc)
}
}
}

View File

@ -59,6 +59,7 @@
#include "GL/glxproto.h"
#include "GL/internal/glcore.h"
#include "glapitable.h"
#include "glxextensions.h"
#ifdef XTHREADS
#include "Xthreads.h"
#endif
@ -220,110 +221,29 @@ typedef struct __GLXattributeRecDEPRECATED {
__GLXvertArrayStateDEPRECATED vertArray;
} __GLXattributeDEPRECATED;
typedef struct __GLXvertexArrayPointerStateRec {
void (*proc)(const void *);
void (*mtex_proc)(GLenum, const void *);
const GLubyte *ptr;
GLsizei skip;
GLint size;
GLenum type;
GLsizei stride;
} __GLXvertexArrayPointerState;
/**
* Define which entries of \c __GLXvertArrayState::arrays match which
* vertex arrays in the client-state vector. These are only the one-of
* arrays. See the \c __GLXvertArrayState::arrays documentation for more
* details.
*
* \sa __GLXvertArrayState
*/
enum {
edgeFlag_ARRAY, /**< \c GL_EDGE_FLAG_ARRAY */
index_ARRAY, /**< \c GL_INDEX_ARRAY */
fogCoord_ARRAY, /**< \c GL_FOG_COORD_ARRAY */
secondaryColor_ARRAY, /**< \c GL_SECONDARY_COLOR_ARRAY */
color_ARRAY, /**< \c GL_COLOR_ARRAY */
normal_ARRAY, /**< \c GL_NORMAL_ARRAY */
/**
* \c GL_VERTEX_ARRAY \b must be last! All of the code for emitting arrays
* and array elements is written based on the assumption that the vertex
* array is last.
*/
vertex_ARRAY,
__GLX_MAX_ARRAYS /**< Place holder entry. */
};
#define ENABLE_ARRAY(state,a) \
do { (state)->vertArray.enables |= (1U << (a ## _ARRAY)); } while( 0 )
#define DISABLE_ARRAY(state,a) \
do { (state)->vertArray.enables &= ~(1U << (a ## _ARRAY)); } while( 0 )
#define IS_ARRAY_ENABLED_BY_INDEX(state, i) \
(((state)->vertArray.enables & (1U << (i))) != 0)
#define IS_ARRAY_ENABLED(state, a) \
IS_ARRAY_ENABLED_BY_INDEX(state, a ## _ARRAY)
#define ENABLE_TEXARRAY(state,a) \
do { (state)->vertArray.texture_enables |= (1U << a); } while( 0 )
#define DISABLE_TEXARRAY(state,a) \
do { (state)->vertArray.texture_enables &= ~(1U << a); } while( 0 )
#define IS_TEXARRAY_ENABLED(state, a) \
(((state)->vertArray.texture_enables & (1U << a)) != 0)
/**
* Client-side vertex array state.
*/
typedef struct __GLXvertArrayStateRec {
/**
* Which client-side arrays are enabled? These are the flag bits for
* all of the non-texture coordinate arrays.
*/
GLuint enables;
/**
* Which of the texture coordinate arrays are enabled?
*/
GLuint texture_enables;
/**
* State for "one-of" arrays. These are the arrays, such as
* GL_COLOR_ARRAY or GL_FOG_COORD_ARRAY for which there is only one
* array. There are also "many-of" arrays, such as
* GL_TEXTURE_COORD_ARRAY.
*/
__GLXvertexArrayPointerState arrays[__GLX_MAX_ARRAYS];
__GLXvertexArrayPointerState texCoord[__GLX_MAX_TEXTURE_UNITS];
GLint maxElementsVertices;
GLint maxElementsIndices;
GLint activeTexture;
} __GLXvertArrayState;
typedef struct __GLXattributeRec {
GLuint mask;
GLuint mask;
/*
** Pixel storage state. Most of the pixel store mode state is kept
** here and used by the client code to manage the packing and
** unpacking of data sent to/received from the server.
*/
__GLXpixelStoreMode storePack, storeUnpack;
/**
* Pixel storage state. Most of the pixel store mode state is kept
* here and used by the client code to manage the packing and
* unpacking of data sent to/received from the server.
*/
__GLXpixelStoreMode storePack, storeUnpack;
/*
** Vertex Array storage state. The vertex array component
** state is stored here and is used to manage the packing of
** DrawArrays data sent to the server.
*/
__GLXvertArrayState vertArray;
/**
* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
* disabled?
*/
GLboolean NoDrawArraysProtocol;
/**
* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically
* disabled?
*/
GLboolean NoDrawArraysProtocol;
/**
* Vertex Array storage state. The vertex array component
* state is stored here and is used to manage the packing of
* DrawArrays data sent to the server.
*/
struct array_state_vector * array_state;
} __GLXattribute;
typedef struct __GLXattributeMachineRec {
@ -529,7 +449,7 @@ struct __GLXcontextRec {
* drivers should NEVER use this data or even care that it exists.
*/
void * client_state_private;
/**
* Stored value for \c glXQueryContext attribute \c GLX_RENDER_TYPE.
*/
@ -546,6 +466,8 @@ struct __GLXcontextRec {
int server_major; /**< Major version number. */
int server_minor; /**< Minor version number. */
/*@}*/
char gl_extension_bits[ __GL_EXT_BYTES ];
};
#define __glXSetError(gc,code) \

View File

@ -375,8 +375,6 @@ GLXContext AllocateGLXContext( Display *dpy )
state->storePack.alignment = 4;
state->storeUnpack.alignment = 4;
__glXInitVertexArrayState(gc);
gc->attributes.stackPointer = &gc->attributes.stack[0];
/*

View File

@ -237,8 +237,6 @@ static const struct extension_info known_gl_extensions[] = {
};
#define __GL_EXT_BYTES ((__NUM_GL_EXTS + 7) / 8)
/* global bit-fields of available extensions and their characteristics */
static unsigned char client_glx_support[8];
static unsigned char client_glx_only[8];
@ -493,6 +491,24 @@ __glXExtensionBitIsEnabled( __GLXscreenConfigs *psc, unsigned bit )
}
/**
* Check if a certain extension is enabled in a given context.
*
*/
GLboolean
__glExtensionBitIsEnabled( const __GLXcontext * gc, unsigned bit )
{
GLboolean enabled = GL_FALSE;
if ( gc != NULL ) {
enabled = EXT_ENABLED( bit, gc->gl_extension_bits );
}
return enabled;
}
/**
* Convert a bit-field to a string of supported extensions.
*/
@ -680,6 +696,7 @@ __glXCalculateUsableGLExtensions( __GLXcontext * gc,
gc->extensions = (unsigned char *)
__glXGetStringFromTable( known_gl_extensions, usable );
(void) memcpy( gc->gl_extension_bits, usable, sizeof( usable ) );
}

View File

@ -216,16 +216,25 @@ enum {
GL_SUN_multi_draw_arrays_bit = GL_EXT_multi_draw_arrays_bit
};
extern GLboolean __glXExtensionBitIsEnabled( __GLXscreenConfigs *psc, unsigned bit );
#define __GL_EXT_BYTES ((__NUM_GL_EXTS + 7) / 8)
struct __GLXscreenConfigsRec;
struct __GLXcontextRec;
extern GLboolean __glXExtensionBitIsEnabled( struct __GLXscreenConfigsRec *psc, unsigned bit );
extern const char * __glXGetClientExtensions( void );
extern void __glXCalculateUsableExtensions( __GLXscreenConfigs *psc,
extern void __glXCalculateUsableExtensions( struct __GLXscreenConfigsRec *psc,
GLboolean display_is_direct_capable, int server_minor_version );
extern void __glXScrEnableExtension( __GLXscreenConfigs *psc, const char * name );
extern void __glXCalculateUsableGLExtensions( __GLXcontext * gc,
extern void __glXScrEnableExtension( struct __GLXscreenConfigsRec *psc, const char * name );
extern void __glXCalculateUsableGLExtensions( struct __GLXcontextRec * gc,
const char * server_string, int major_version, int minor_version );
extern void __glXGetGLVersion( int * major_version, int * minor_version );
extern char * __glXGetClientGLExtensionString( void );
extern GLboolean __glExtensionBitIsEnabled( const struct __GLXcontextRec * gc,
unsigned bit );
/* Source-level backwards compatibility with old drivers. They won't
* find the respective functions, though.
*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
/*
* (C) Copyright IBM Corporation 2004, 2005
* 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, sub license,
* 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 (including the next
* paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* IBM,
* AND/OR THEIR SUPPLIERS 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.
*/
#ifndef INDIRECT_VERTEX_ARRAY_H
#define INDIRECT_VERTEX_ARRAY_H
extern const GLuint __glXTypeSize_table[16];
#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
? 0 : __glXTypeSize_table[ (e) & 0x0f ])
extern void __glXArrayDisableAll( __GLXattribute * state );
extern GLboolean __glXSetArrayEnable( __GLXattribute * state,
GLenum key, unsigned index, GLboolean enable );
extern GLboolean __glXGetArrayEnable( const __GLXattribute * const state,
GLenum key, unsigned index, GLintptr * dest );
extern GLboolean __glXGetArraySize( const __GLXattribute * const state,
GLenum key, unsigned index, GLintptr * dest );
extern GLboolean __glXGetArrayType( const __GLXattribute * const state,
GLenum key, unsigned index, GLintptr * dest );
extern GLboolean __glXGetArrayStride( const __GLXattribute * const state,
GLenum key, unsigned index, GLintptr * dest );
extern GLboolean __glXGetArrayPointer( const __GLXattribute * const state,
GLenum key, unsigned index, void ** dest );
extern void __glXPushArrayState( __GLXattribute * state );
extern void __glXPopArrayState( __GLXattribute * state );
extern GLuint __glXGetActiveTextureUnit( const __GLXattribute * const state );
#endif /* INDIRECT_VERTEX_ARRAY_H */

View File

@ -35,9 +35,11 @@
*/
#include <stdio.h>
#include <assert.h>
#include "glxclient.h"
#include "packsingle.h"
#include "glxextensions.h"
#include "indirect_vertex_array.h"
/* Used for GL_ARB_transpose_matrix */
static void TransposeMatrixf(GLfloat m[16])
@ -134,24 +136,106 @@ GLenum __indirect_glGetError(void)
return retval;
}
#define CASE_ARRAY_ENABLE(enum_name,array,dest,gl_type) \
case GL_ ## enum_name ## _ARRAY: \
*dest = (gl_type) (IS_ARRAY_ENABLED(state, array)); break
#define CASE_ARRAY_SIZE(enum_name,array,dest,gl_type) \
case GL_ ## enum_name ## _ARRAY_SIZE: \
*dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].size ; break
#define CASE_ARRAY_TYPE(enum_name,array,dest,gl_type) \
case GL_ ## enum_name ## _ARRAY_TYPE: \
*dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].type ; break
#define CASE_ARRAY_STRIDE(enum_name,array,dest,gl_type) \
case GL_ ## enum_name ## _ARRAY_STRIDE: \
*dest = (gl_type) state->vertArray.arrays[array ## _ARRAY].stride ; break
#define CASE_ARRAY_ALL(enum_name,array,dest,gl_type) \
CASE_ARRAY_ENABLE(enum_name,array,dest,gl_type); \
CASE_ARRAY_STRIDE(enum_name,array,dest,gl_type); \
CASE_ARRAY_TYPE(enum_name,array,dest,gl_type); \
CASE_ARRAY_SIZE(enum_name,array,dest,gl_type)
/**
* Get the selected attribute from the vertex array state vector.
*
* \returns
* On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
*/
static GLboolean
get_array_data( __GLXattribute * state, GLenum cap, GLintptr * data )
{
GLboolean retval = GL_FALSE;
const GLint tex_unit = __glXGetActiveTextureUnit( state );
switch( cap ) {
case GL_VERTEX_ARRAY:
case GL_NORMAL_ARRAY:
case GL_COLOR_ARRAY:
case GL_INDEX_ARRAY:
case GL_EDGE_FLAG_ARRAY:
case GL_SECONDARY_COLOR_ARRAY:
case GL_FOG_COORD_ARRAY:
retval = __glXGetArrayEnable( state, cap, 0, data );
break;
case GL_VERTEX_ARRAY_SIZE:
retval = __glXGetArraySize( state, GL_VERTEX_ARRAY, 0, data );
break;
case GL_COLOR_ARRAY_SIZE:
retval = __glXGetArraySize( state, GL_COLOR_ARRAY, 0, data );
break;
case GL_SECONDARY_COLOR_ARRAY_SIZE:
retval = __glXGetArraySize( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
break;
case GL_VERTEX_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_VERTEX_ARRAY, 0, data );
break;
case GL_NORMAL_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_NORMAL_ARRAY, 0, data );
break;
case GL_INDEX_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_INDEX_ARRAY, 0, data );
break;
case GL_COLOR_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_COLOR_ARRAY, 0, data );
break;
case GL_SECONDARY_COLOR_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
break;
case GL_FOG_COORD_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_FOG_COORD_ARRAY, 0, data );
break;
case GL_VERTEX_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_VERTEX_ARRAY, 0, data );
break;
case GL_NORMAL_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_NORMAL_ARRAY, 0, data );
break;
case GL_INDEX_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_INDEX_ARRAY, 0, data );
break;
case GL_EDGE_FLAG_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_EDGE_FLAG_ARRAY, 0, data );
break;
case GL_COLOR_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_COLOR_ARRAY, 0, data );
break;
case GL_SECONDARY_COLOR_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_SECONDARY_COLOR_ARRAY, 0, data );
break;
case GL_FOG_COORD_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_FOG_COORD_ARRAY, 0, data );
break;
case GL_TEXTURE_COORD_ARRAY:
retval = __glXGetArrayEnable( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
break;
case GL_TEXTURE_COORD_ARRAY_SIZE:
retval = __glXGetArraySize( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
break;
case GL_TEXTURE_COORD_ARRAY_TYPE:
retval = __glXGetArrayType( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
break;
case GL_TEXTURE_COORD_ARRAY_STRIDE:
retval = __glXGetArrayStride( state, GL_TEXTURE_COORD_ARRAY, tex_unit, data );
break;
case GL_MAX_ELEMENTS_VERTICES:
case GL_MAX_ELEMENTS_INDICES:
retval = GL_TRUE;
*data = ~0UL;
break;
}
return retval;
}
void __indirect_glGetBooleanv(GLenum val, GLboolean *b)
{
@ -173,6 +257,8 @@ void __indirect_glGetBooleanv(GLenum val, GLboolean *b)
** Error occured; don't modify user's buffer.
*/
} else {
GLintptr data;
/*
** For all the queries listed here, we use the locally stored
** values rather than the one returned by the server. Note that
@ -180,6 +266,12 @@ void __indirect_glGetBooleanv(GLenum val, GLboolean *b)
** find out whether it was legal to make a query (it's illegal,
** for example, to call a query between glBegin() and glEnd()).
*/
if ( get_array_data( state, val, & data ) ) {
*b = (GLboolean) data;
return;
}
switch (val) {
case GL_PACK_ROW_LENGTH:
*b = (GLboolean)state->storePack.rowLength;
@ -229,52 +321,11 @@ void __indirect_glGetBooleanv(GLenum val, GLboolean *b)
case GL_UNPACK_LSB_FIRST:
*b = (GLboolean)state->storeUnpack.lsbFirst;
break;
CASE_ARRAY_ALL(VERTEX, vertex, b, GLboolean);
CASE_ARRAY_ENABLE(NORMAL, normal, b, GLboolean);
CASE_ARRAY_TYPE(NORMAL, normal, b, GLboolean);
CASE_ARRAY_STRIDE(NORMAL, normal, b, GLboolean);
CASE_ARRAY_ALL(COLOR, color, b, GLboolean);
CASE_ARRAY_ENABLE(INDEX, index, b, GLboolean);
CASE_ARRAY_TYPE(INDEX, index, b, GLboolean);
CASE_ARRAY_STRIDE(INDEX, index, b, GLboolean);
case GL_TEXTURE_COORD_ARRAY:
*b = (GLboolean)IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
break;
case GL_TEXTURE_COORD_ARRAY_SIZE:
*b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].size;
break;
case GL_TEXTURE_COORD_ARRAY_TYPE:
*b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].type;
break;
case GL_TEXTURE_COORD_ARRAY_STRIDE:
*b = (GLboolean)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
break;
CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, b, GLboolean);
CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, b, GLboolean);
CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, b, GLboolean);
CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, b, GLboolean);
CASE_ARRAY_TYPE(FOG_COORD, fogCoord, b, GLboolean);
CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, b, GLboolean);
case GL_MAX_ELEMENTS_VERTICES:
*b = (GLboolean)state->vertArray.maxElementsVertices;
break;
case GL_MAX_ELEMENTS_INDICES:
*b = (GLboolean)state->vertArray.maxElementsIndices;
break;
case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
*b = (GLboolean)__GL_CLIENT_ATTRIB_STACK_DEPTH;
break;
case GL_CLIENT_ACTIVE_TEXTURE_ARB:
*b = (GLboolean)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
case GL_CLIENT_ACTIVE_TEXTURE:
*b = (GLboolean)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
break;
default:
/*
@ -314,6 +365,8 @@ void __indirect_glGetDoublev(GLenum val, GLdouble *d)
** Error occured; don't modify user's buffer.
*/
} else {
GLintptr data;
/*
** For all the queries listed here, we use the locally stored
** values rather than the one returned by the server. Note that
@ -321,6 +374,12 @@ void __indirect_glGetDoublev(GLenum val, GLdouble *d)
** find out whether it was legal to make a query (it's illegal,
** for example, to call a query between glBegin() and glEnd()).
*/
if ( get_array_data( state, val, & data ) ) {
*d = (GLdouble) data;
return;
}
switch (val) {
case GL_PACK_ROW_LENGTH:
*d = (GLdouble)state->storePack.rowLength;
@ -370,52 +429,11 @@ void __indirect_glGetDoublev(GLenum val, GLdouble *d)
case GL_UNPACK_LSB_FIRST:
*d = (GLdouble)state->storeUnpack.lsbFirst;
break;
CASE_ARRAY_ALL(VERTEX, vertex, d, GLdouble);
CASE_ARRAY_ENABLE(NORMAL, normal, d, GLdouble);
CASE_ARRAY_TYPE(NORMAL, normal, d, GLdouble);
CASE_ARRAY_STRIDE(NORMAL, normal, d, GLdouble);
CASE_ARRAY_ALL(COLOR, color, d, GLdouble);
CASE_ARRAY_ENABLE(INDEX, index, d, GLdouble);
CASE_ARRAY_TYPE(INDEX, index, d, GLdouble);
CASE_ARRAY_STRIDE(INDEX, index, d, GLdouble);
case GL_TEXTURE_COORD_ARRAY:
*d = (GLdouble) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
break;
case GL_TEXTURE_COORD_ARRAY_SIZE:
*d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].size;
break;
case GL_TEXTURE_COORD_ARRAY_TYPE:
*d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].type;
break;
case GL_TEXTURE_COORD_ARRAY_STRIDE:
*d = (GLdouble)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
break;
CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, d, GLdouble);
CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, d, GLdouble);
CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, d, GLdouble);
CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, d, GLdouble);
CASE_ARRAY_TYPE(FOG_COORD, fogCoord, d, GLdouble);
CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, d, GLdouble);
case GL_MAX_ELEMENTS_VERTICES:
*d = (GLdouble)state->vertArray.maxElementsVertices;
break;
case GL_MAX_ELEMENTS_INDICES:
*d = (GLdouble)state->vertArray.maxElementsIndices;
break;
case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
*d = (GLdouble)__GL_CLIENT_ATTRIB_STACK_DEPTH;
break;
case GL_CLIENT_ACTIVE_TEXTURE_ARB:
*d = (GLdouble)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
case GL_CLIENT_ACTIVE_TEXTURE:
*d = (GLdouble)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
break;
default:
/*
@ -455,6 +473,8 @@ void __indirect_glGetFloatv(GLenum val, GLfloat *f)
** Error occured; don't modify user's buffer.
*/
} else {
GLintptr data;
/*
** For all the queries listed here, we use the locally stored
** values rather than the one returned by the server. Note that
@ -462,6 +482,12 @@ void __indirect_glGetFloatv(GLenum val, GLfloat *f)
** find out whether it was legal to make a query (it's illegal,
** for example, to call a query between glBegin() and glEnd()).
*/
if ( get_array_data( state, val, & data ) ) {
*f = (GLfloat) data;
return;
}
switch (val) {
case GL_PACK_ROW_LENGTH:
*f = (GLfloat)state->storePack.rowLength;
@ -511,52 +537,11 @@ void __indirect_glGetFloatv(GLenum val, GLfloat *f)
case GL_UNPACK_LSB_FIRST:
*f = (GLfloat)state->storeUnpack.lsbFirst;
break;
CASE_ARRAY_ALL(VERTEX, vertex, f, GLfloat);
CASE_ARRAY_ENABLE(NORMAL, normal, f, GLfloat);
CASE_ARRAY_TYPE(NORMAL, normal, f, GLfloat);
CASE_ARRAY_STRIDE(NORMAL, normal, f, GLfloat);
CASE_ARRAY_ALL(COLOR, color, f, GLfloat);
CASE_ARRAY_ENABLE(INDEX, index, f, GLfloat);
CASE_ARRAY_TYPE(INDEX, index, f, GLfloat);
CASE_ARRAY_STRIDE(INDEX, index, f, GLfloat);
case GL_TEXTURE_COORD_ARRAY:
*f = (GLfloat) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
break;
case GL_TEXTURE_COORD_ARRAY_SIZE:
*f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].size;
break;
case GL_TEXTURE_COORD_ARRAY_TYPE:
*f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].type;
break;
case GL_TEXTURE_COORD_ARRAY_STRIDE:
*f = (GLfloat)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
break;
CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, f, GLfloat);
CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, f, GLfloat);
CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, f, GLfloat);
CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, f, GLfloat);
CASE_ARRAY_TYPE(FOG_COORD, fogCoord, f, GLfloat);
CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, f, GLfloat);
case GL_MAX_ELEMENTS_VERTICES:
*f = (GLfloat)state->vertArray.maxElementsVertices;
break;
case GL_MAX_ELEMENTS_INDICES:
*f = (GLfloat)state->vertArray.maxElementsIndices;
break;
case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
*f = (GLfloat)__GL_CLIENT_ATTRIB_STACK_DEPTH;
break;
case GL_CLIENT_ACTIVE_TEXTURE_ARB:
*f = (GLfloat)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
case GL_CLIENT_ACTIVE_TEXTURE:
*f = (GLfloat)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
break;
default:
/*
@ -596,6 +581,8 @@ void __indirect_glGetIntegerv(GLenum val, GLint *i)
** Error occured; don't modify user's buffer.
*/
} else {
GLintptr data;
/*
** For all the queries listed here, we use the locally stored
** values rather than the one returned by the server. Note that
@ -603,6 +590,12 @@ void __indirect_glGetIntegerv(GLenum val, GLint *i)
** find out whether it was legal to make a query (it's illegal,
** for example, to call a query between glBegin() and glEnd()).
*/
if ( get_array_data( state, val, & data ) ) {
*i = (GLint) data;
return;
}
switch (val) {
case GL_PACK_ROW_LENGTH:
*i = (GLint)state->storePack.rowLength;
@ -652,52 +645,11 @@ void __indirect_glGetIntegerv(GLenum val, GLint *i)
case GL_UNPACK_LSB_FIRST:
*i = (GLint)state->storeUnpack.lsbFirst;
break;
CASE_ARRAY_ALL(VERTEX, vertex, i, GLint);
CASE_ARRAY_ENABLE(NORMAL, normal, i, GLint);
CASE_ARRAY_TYPE(NORMAL, normal, i, GLint);
CASE_ARRAY_STRIDE(NORMAL, normal, i, GLint);
CASE_ARRAY_ALL(COLOR, color, i, GLint);
CASE_ARRAY_ENABLE(INDEX, index, i, GLint);
CASE_ARRAY_TYPE(INDEX, index, i, GLint);
CASE_ARRAY_STRIDE(INDEX, index, i, GLint);
case GL_TEXTURE_COORD_ARRAY:
*i = (GLint) IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
break;
case GL_TEXTURE_COORD_ARRAY_SIZE:
*i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].size;
break;
case GL_TEXTURE_COORD_ARRAY_TYPE:
*i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].type;
break;
case GL_TEXTURE_COORD_ARRAY_STRIDE:
*i = (GLint)state->vertArray.texCoord[state->vertArray.activeTexture].stride;
break;
CASE_ARRAY_ENABLE(EDGE_FLAG, edgeFlag, i, GLint);
CASE_ARRAY_STRIDE(EDGE_FLAG, edgeFlag, i, GLint);
CASE_ARRAY_ALL(SECONDARY_COLOR, secondaryColor, i, GLint);
CASE_ARRAY_ENABLE(FOG_COORD, fogCoord, i, GLint);
CASE_ARRAY_TYPE(FOG_COORD, fogCoord, i, GLint);
CASE_ARRAY_STRIDE(FOG_COORD, fogCoord, i, GLint);
case GL_MAX_ELEMENTS_VERTICES:
*i = (GLint)state->vertArray.maxElementsVertices;
break;
case GL_MAX_ELEMENTS_INDICES:
*i = (GLint)state->vertArray.maxElementsIndices;
break;
case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
*i = (GLint)__GL_CLIENT_ATTRIB_STACK_DEPTH;
break;
case GL_CLIENT_ACTIVE_TEXTURE_ARB:
*i = (GLint)(state->vertArray.activeTexture + GL_TEXTURE0_ARB);
case GL_CLIENT_ACTIVE_TEXTURE:
*i = (GLint)(__glXGetActiveTextureUnit(state) + GL_TEXTURE0);
break;
default:
/*
@ -981,26 +933,28 @@ GLboolean __indirect_glIsEnabled(GLenum cap)
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
xGLXSingleReply reply;
GLboolean retval = 0;
GLintptr enable;
if (!dpy) return 0;
switch(cap) {
case GL_VERTEX_ARRAY:
return IS_ARRAY_ENABLED(state, vertex);
case GL_NORMAL_ARRAY:
return IS_ARRAY_ENABLED(state, normal);
case GL_COLOR_ARRAY:
return IS_ARRAY_ENABLED(state, color);
case GL_INDEX_ARRAY:
return IS_ARRAY_ENABLED(state, index);
case GL_TEXTURE_COORD_ARRAY:
return IS_TEXARRAY_ENABLED(state, state->vertArray.activeTexture);
case GL_EDGE_FLAG_ARRAY:
return IS_ARRAY_ENABLED(state, edgeFlag);
case GL_SECONDARY_COLOR_ARRAY:
return IS_ARRAY_ENABLED(state, secondaryColor);
case GL_FOG_COORD_ARRAY:
return IS_ARRAY_ENABLED(state, fogCoord);
case GL_VERTEX_ARRAY:
case GL_NORMAL_ARRAY:
case GL_COLOR_ARRAY:
case GL_INDEX_ARRAY:
case GL_EDGE_FLAG_ARRAY:
case GL_SECONDARY_COLOR_ARRAY:
case GL_FOG_COORD_ARRAY:
retval = __glXGetArrayEnable( state, cap, 0, & enable );
assert( retval );
return (GLboolean) enable;
break;
case GL_TEXTURE_COORD_ARRAY:
retval = __glXGetArrayEnable( state, GL_TEXTURE_COORD_ARRAY,
__glXGetActiveTextureUnit( state ), & enable );
assert( retval );
return (GLboolean) enable;
break;
}
__GLX_SINGLE_LOAD_VARIABLES();
@ -1021,37 +975,32 @@ void __indirect_glGetPointerv(GLenum pname, void **params)
if (!dpy) return;
switch(pname) {
case GL_VERTEX_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ vertex_ARRAY ].ptr;
return;
case GL_NORMAL_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ normal_ARRAY ].ptr;
return;
case GL_COLOR_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ color_ARRAY ].ptr;
return;
case GL_INDEX_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ index_ARRAY ].ptr;
return;
case GL_TEXTURE_COORD_ARRAY_POINTER:
*params = (void *)state->vertArray.texCoord[state->vertArray.activeTexture].ptr;
return;
case GL_EDGE_FLAG_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ edgeFlag_ARRAY ].ptr;
case GL_VERTEX_ARRAY_POINTER:
case GL_NORMAL_ARRAY_POINTER:
case GL_COLOR_ARRAY_POINTER:
case GL_INDEX_ARRAY_POINTER:
case GL_EDGE_FLAG_ARRAY_POINTER:
__glXGetArrayPointer( state, pname - GL_VERTEX_ARRAY_POINTER
+ GL_VERTEX_ARRAY,
0, params );
return;
case GL_SECONDARY_COLOR_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ secondaryColor_ARRAY ].ptr;
case GL_TEXTURE_COORD_ARRAY_POINTER:
__glXGetArrayPointer( state, GL_TEXTURE_COORD_ARRAY,
__glXGetActiveTextureUnit( state ), params );
return;
case GL_FOG_COORD_ARRAY_POINTER:
*params = (void *)state->vertArray.arrays[ fogCoord_ARRAY ].ptr;
case GL_SECONDARY_COLOR_ARRAY_POINTER:
case GL_FOG_COORD_ARRAY_POINTER:
__glXGetArrayPointer( state, pname - GL_FOG_COORD_ARRAY_POINTER
+ GL_FOG_COORD_ARRAY,
0, params );
return;
case GL_FEEDBACK_BUFFER_POINTER:
case GL_FEEDBACK_BUFFER_POINTER:
*params = (void *)gc->feedbackBuf;
return;
case GL_SELECTION_BUFFER_POINTER:
case GL_SELECTION_BUFFER_POINTER:
*params = (void *)gc->selectBuf;
return;
default:
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}

View File

@ -34,134 +34,10 @@
**
*/
#include <assert.h>
#include "glxclient.h"
#include "packrender.h"
#include "indirect.h"
#include <string.h>
#include <limits.h> /* INT_MAX */
#include "indirect_vertex_array.h"
/* macros for setting function pointers */
#define __GL_VERTEX_FUNC(NAME, let) \
case GL_##NAME: \
if (size == 2) \
vertexPointer->proc = (void (*)(const void *))__indirect_glVertex2##let##v; \
else if (size == 3) \
vertexPointer->proc = (void (*)(const void *))__indirect_glVertex3##let##v; \
else if (size == 4) \
vertexPointer->proc = (void (*)(const void *))__indirect_glVertex4##let##v; \
break
#define __GL_NORMAL_FUNC(NAME, let) \
case GL_##NAME: \
normalPointer->proc = (void (*)(const void *))__indirect_glNormal3##let##v; \
break
#define __GL_COLOR_FUNC(NAME, let) \
case GL_##NAME: \
if (size == 3) \
colorPointer->proc = (void (*)(const void *))__indirect_glColor3##let##v; \
else if (size == 4)\
colorPointer->proc = (void (*)(const void *))__indirect_glColor4##let##v; \
break
#define __GL_SEC_COLOR_FUNC(NAME, let) \
case GL_##NAME: \
seccolorPointer->proc = (void (*)(const void *))__indirect_glSecondaryColor3##let##vEXT; \
#define __GL_FOG_FUNC(NAME, let) \
case GL_##NAME: \
fogPointer->proc = (void (*)(const void *))__indirect_glFogCoord##let##vEXT; \
#define __GL_INDEX_FUNC(NAME, let) \
case GL_##NAME: \
indexPointer->proc = (void (*)(const void *))__indirect_glIndex##let##v; \
break
#define __GL_TEXTURE_FUNC(NAME, let) \
case GL_##NAME: \
if (size == 1) { \
texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord1##let##v; \
texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord1##let##vARB; \
} else if (size == 2) { \
texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord2##let##v; \
texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
} else if (size == 3) { \
texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord3##let##v; \
texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \
} else if (size == 4) { \
texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord4##let##v; \
texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord4##let##vARB; \
} break
/**
* Table of sizes, in bytes, of a GL types. All of the type enums are be in
* the range 0x1400 - 0x140F. That includes types added by extensions (i.e.,
* \c GL_HALF_FLOAT_NV). This elements of this table correspond to the
* type enums masked with 0x0f.
*
* \notes
* \c GL_HAVE_FLOAT_NV is not included. Neither are \c GL_2_BYTES,
* \c GL_3_BYTES, or \c GL_4_BYTES.
*/
static const GLuint __glXTypeSize_table[16] = {
1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0
};
#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \
? 0 : __glXTypeSize_table[ (e) & 0x0f ])
/**
* Initialize vertex array state for a GLX context.
*
* \param gc GLX context whose vertex array state is to be initialized.
*
* \todo
* Someone is going to have to check the spec. This function takes greate
* care to initialize the \c size and \c type fields to "correct" values
* for each array. I'm not sure this is necessary. I think it should be
* acceptable to just \c memset the whole \c arrays and \c texCoord arrays
* to zero and be done with it. The spec may say something to the contrary,
* however.
*/
void __glXInitVertexArrayState(__GLXcontext *gc)
{
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertArrayState *va = &state->vertArray;
GLint i;
va->enables = 0;
va->texture_enables = 0;
for ( i = 0 ; i < __GLX_MAX_ARRAYS ; i++ ) {
va->arrays[ i ].proc = NULL;
va->arrays[ i ].skip = 0;
va->arrays[ i ].ptr = 0;
va->arrays[ i ].size = 1;
va->arrays[ i ].type = GL_FLOAT;
va->arrays[ i ].stride = 0;
}
va->arrays[ edgeFlag_ARRAY ].type = GL_UNSIGNED_BYTE;;
va->arrays[ secondaryColor_ARRAY ].size = 3;
va->arrays[ color_ARRAY ].size = 4;
va->arrays[ normal_ARRAY ].size = 3;
va->arrays[ vertex_ARRAY ].size = 4;
for ( i = 0 ; i < __GLX_MAX_TEXTURE_UNITS ; i++ ) {
va->texCoord[ i ].proc = NULL;
va->texCoord[ i ].skip = 0;
va->texCoord[ i ].ptr = 0;
va->texCoord[ i ].size = 4;
va->texCoord[ i ].type = GL_FLOAT;
va->texCoord[ i ].stride = 0;
}
va->maxElementsVertices = INT_MAX;
va->maxElementsIndices = INT_MAX;
}
/*****************************************************************************/
@ -214,296 +90,6 @@ void __indirect_glVertexPointerEXT(GLint size, GLenum type, GLsizei stride,
/*****************************************************************************/
void __indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *vertexPointer = &state->vertArray.arrays[ vertex_ARRAY ];
/* Check arguments */
if (size < 2 || size > 4 || stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_VERTEX_FUNC(SHORT, s);
__GL_VERTEX_FUNC(INT, i);
__GL_VERTEX_FUNC(FLOAT, f);
__GL_VERTEX_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
vertexPointer->size = size;
vertexPointer->type = type;
vertexPointer->stride = stride;
vertexPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
vertexPointer->skip = __glXTypeSize(type) * size;
} else {
vertexPointer->skip = stride;
}
}
void __indirect_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *normalPointer = &state->vertArray.arrays[ normal_ARRAY ];
/* Check arguments */
if (stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_NORMAL_FUNC(BYTE, b);
__GL_NORMAL_FUNC(SHORT, s);
__GL_NORMAL_FUNC(INT, i);
__GL_NORMAL_FUNC(FLOAT, f);
__GL_NORMAL_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
normalPointer->type = type;
normalPointer->stride = stride;
normalPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
normalPointer->skip = 3 * __glXTypeSize(type);
} else {
normalPointer->skip = stride;
}
}
void __indirect_glColorPointer(GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *colorPointer = &state->vertArray.arrays[ color_ARRAY ];
/* Check arguments */
if (stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_COLOR_FUNC(BYTE, b);
__GL_COLOR_FUNC(UNSIGNED_BYTE, ub);
__GL_COLOR_FUNC(SHORT, s);
__GL_COLOR_FUNC(UNSIGNED_SHORT, us);
__GL_COLOR_FUNC(INT, i);
__GL_COLOR_FUNC(UNSIGNED_INT, ui);
__GL_COLOR_FUNC(FLOAT, f);
__GL_COLOR_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
colorPointer->size = size;
colorPointer->type = type;
colorPointer->stride = stride;
colorPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
colorPointer->skip = size * __glXTypeSize(type);
} else {
colorPointer->skip = stride;
}
}
void __indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *indexPointer = &state->vertArray.arrays[ index_ARRAY ];
/* Check arguments */
if (stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_INDEX_FUNC(UNSIGNED_BYTE, ub);
__GL_INDEX_FUNC(SHORT, s);
__GL_INDEX_FUNC(INT, i);
__GL_INDEX_FUNC(FLOAT, f);
__GL_INDEX_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
indexPointer->type = type;
indexPointer->stride = stride;
indexPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
indexPointer->skip = __glXTypeSize(type);
} else {
indexPointer->skip = stride;
}
}
void __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride,
const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *texCoordPointer =
&state->vertArray.texCoord[state->vertArray.activeTexture];
/* Check arguments */
if (size < 1 || size > 4 || stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_TEXTURE_FUNC(SHORT, s);
__GL_TEXTURE_FUNC(INT, i);
__GL_TEXTURE_FUNC(FLOAT, f);
__GL_TEXTURE_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
texCoordPointer->size = size;
texCoordPointer->type = type;
texCoordPointer->stride = stride;
texCoordPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
texCoordPointer->skip = __glXTypeSize(type) * size;
} else {
texCoordPointer->skip = stride;
}
}
void __indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *edgeFlagPointer = &state->vertArray.arrays[ edgeFlag_ARRAY ];
/* Check arguments */
if (stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
edgeFlagPointer->proc = (void (*)(const void *))__indirect_glEdgeFlagv;
edgeFlagPointer->stride = stride;
edgeFlagPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
edgeFlagPointer->skip = sizeof(GLboolean);
} else {
edgeFlagPointer->skip = stride;
}
}
void __indirect_glSecondaryColorPointerEXT(GLint size, GLenum type, GLsizei stride,
const GLvoid * pointer )
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *seccolorPointer = &state->vertArray.arrays[ secondaryColor_ARRAY ];
/* Check arguments */
if ( (stride < 0) || (size != 3) ) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_SEC_COLOR_FUNC(BYTE, b);
__GL_SEC_COLOR_FUNC(UNSIGNED_BYTE, ub);
__GL_SEC_COLOR_FUNC(SHORT, s);
__GL_SEC_COLOR_FUNC(UNSIGNED_SHORT, us);
__GL_SEC_COLOR_FUNC(INT, i);
__GL_SEC_COLOR_FUNC(UNSIGNED_INT, ui);
__GL_SEC_COLOR_FUNC(FLOAT, f);
__GL_SEC_COLOR_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
seccolorPointer->size = size;
seccolorPointer->type = type;
seccolorPointer->stride = stride;
seccolorPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
seccolorPointer->skip = size * __glXTypeSize(type);
} else {
seccolorPointer->skip = stride;
}
}
void __indirect_glFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertexArrayPointerState *fogPointer = &state->vertArray.arrays[ fogCoord_ARRAY ];
/* Check arguments */
if (stride < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
/* Choose appropriate api proc */
switch(type) {
__GL_FOG_FUNC(FLOAT, f);
__GL_FOG_FUNC(DOUBLE, d);
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
fogPointer->size = 1;
fogPointer->type = type;
fogPointer->stride = stride;
fogPointer->ptr = pointer;
/* Set internal state */
if (stride == 0) {
fogPointer->skip = __glXTypeSize(type);
} else {
fogPointer->skip = stride;
}
}
void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer)
{
__GLXcontext *gc = __glXGetCurrentContext();
@ -642,8 +228,8 @@ void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid
trueStride = (stride == 0) ? size : stride;
state->vertArray.enables = 0;
state->vertArray.texture_enables = 0;
__glXArrayDisableAll( state );
if (tEnable) {
__indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
__indirect_glTexCoordPointer(tSize, tType, trueStride, (const char *)pointer);
@ -659,543 +245,3 @@ void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid
__indirect_glEnableClientState(GL_VERTEX_ARRAY);
__indirect_glVertexPointer(vSize, vType, trueStride, (const char *)pointer+vOffset);
}
/*****************************************************************************/
void __indirect_glArrayElement(GLint i)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertArrayState *va = &state->vertArray;
GLint j;
if (IS_TEXARRAY_ENABLED(state, 0)) {
(*va->texCoord[0].proc)(va->texCoord[0].ptr+i*va->texCoord[0].skip);
}
/* Multitexturing is handled specially because the protocol
* requires an extra parameter.
*/
for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
if (IS_TEXARRAY_ENABLED(state, j)) {
(*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, va->texCoord[j].ptr+i*va->texCoord[j].skip);
}
}
for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
(*va->arrays[ j ].proc)(va->arrays[ j ].ptr+i*va->arrays[ j ].skip);
}
}
}
struct array_info {
__GLXdispatchDrawArraysComponentHeader ai;
GLsizei bytes;
const GLubyte *ptr;
GLsizei skip;
};
/**
* Initialize a \c array_info structure for each array that is enabled in
* \c state. Determine how many arrays are enabled, and store the result
* in \c num_arrays. Determine how big each vertex is, and store the result
* in \c total_vertex_size.
*
* \returns The size of the final request. This is the size, in bytes, of
* the DrawArrays header, the ARRAY_INFO structures, and all the vertex data.
* This value \b assumes a \c X_GLXRender command is used. The true size
* will be 4 bytes larger if a \c X_GLXRenderLarge command is used.
*/
static GLuint
prep_arrays(const __GLXattribute * const state, struct array_info * arrays,
GLint count,
GLsizei *num_arrays, GLsizei *total_vertex_size)
{
GLsizei na = 0;
GLsizei vs = 0;
#define ASSIGN_ARRAY_INFO(state, enum_name, arr) \
do { \
arrays[ na ].ai.datatype = state->vertArray. arr .type ; \
arrays[ na ].ai.numVals = state->vertArray. arr .size ; \
arrays[ na ].ai.component = GL_ ## enum_name ## _ARRAY; \
\
arrays[ na ].bytes = state->vertArray. arr .size \
* __glXTypeSize( state->vertArray. arr .type ); \
arrays[ na ].ptr = state->vertArray. arr .ptr; \
arrays[ na ].skip = state->vertArray. arr .skip; \
\
vs += __GLX_PAD(arrays[ na ].bytes); \
na++; \
} while( 0 )
#define ADD_ARRAY_IF_ENABLED(state, enum_name, arr) \
do { if ( IS_ARRAY_ENABLED(state, arr) ) { \
ASSIGN_ARRAY_INFO(state, enum_name, arrays[ arr ## _ARRAY ] ); \
} } while( 0 )
ADD_ARRAY_IF_ENABLED(state, VERTEX, vertex);
ADD_ARRAY_IF_ENABLED(state, NORMAL, normal);
ADD_ARRAY_IF_ENABLED(state, COLOR, color);
ADD_ARRAY_IF_ENABLED(state, SECONDARY_COLOR, secondaryColor);
ADD_ARRAY_IF_ENABLED(state, FOG_COORD, fogCoord);
ADD_ARRAY_IF_ENABLED(state, EDGE_FLAG, edgeFlag);
ADD_ARRAY_IF_ENABLED(state, INDEX, index);
/* The standard DrawArrays protocol *only* supports a single array of
* texture coordinates.
*/
if ( IS_TEXARRAY_ENABLED(state, 0) ) {
ASSIGN_ARRAY_INFO(state, TEXTURE_COORD, texCoord[0]);
}
*num_arrays = na;
*total_vertex_size = vs;
return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE * na)
+ (vs * count)
+ __GLX_DRAWARRAYS_CMD_HDR_SIZE);
}
/**
* Emits the vertex data for the DrawArrays GLX protocol.
*/
static GLsizei
emit_vertex(GLubyte * data, const struct array_info * arrays,
GLsizei num_arrays, GLint element, GLsizei offset)
{
GLint i;
for ( i = 0 ; i < num_arrays ; i++ ) {
(void) memcpy( data + offset,
arrays[i].ptr + (arrays[i].skip * element),
arrays[i].bytes );
offset += __GLX_PAD(arrays[i].bytes);
}
return offset;
}
static void
emit_header(GLubyte * pc, const struct array_info * arrays,
GLsizei num_arrays, GLsizei count, GLenum mode)
{
__GLXdispatchDrawArraysComponentHeader *arrayInfo;
GLsizei i;
__GLX_PUT_LONG(0, count);
__GLX_PUT_LONG(4, num_arrays);
__GLX_PUT_LONG(8, mode);
arrayInfo = (__GLXdispatchDrawArraysComponentHeader *)
(pc + __GLX_DRAWARRAYS_HDR_SIZE);
/* Write the ARRAY_INFO data.
*/
for ( i = 0 ; i < num_arrays ; i++ ) {
arrayInfo[i] = arrays[i].ai;
}
}
/**
* Emit GLX DrawArrays protocol using a GLXRender packet.
*/
static void
emit_Render_DrawArrays(__GLXcontext * gc, const struct array_info * arrays,
GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode,
GLsizei cmdlen, GLsizei total_vertex_size)
{
GLubyte * pc = gc->pc;
GLsizei offset;
GLsizei i;
__GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays, cmdlen);
emit_header(pc + 4, arrays, num_arrays, count, mode);
/* Write the actual array data.
*/
offset = __GLX_DRAWARRAYS_CMD_HDR_SIZE
+ (num_arrays * __GLX_COMPONENT_HDR_SIZE);
for ( i = 0 ; i < count ; i++ ) {
offset = emit_vertex(pc, arrays, num_arrays, i + first, offset);
}
__GLX_END(cmdlen);
}
/**
* Emit GLX DrawArrays protocol using a GLXRenderLarge packet.
*/
static void
emit_RenderLarge_DrawArrays(__GLXcontext * gc, const struct array_info * arrays,
GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode,
GLsizei cmdlen, GLsizei total_vertex_size)
{
GLubyte * pc = gc->pc;
GLsizei offset;
GLsizei i;
GLint maxSize;
GLint totalRequests;
GLint requestNumber;
GLsizei elements_per_request;
/* Calculate the maximum amount of data can be stuffed into a single
* packet. sz_xGLXRenderReq is added because bufSize is the maximum
* packet size minus sz_xGLXRenderReq.
*
* The important value here is elements_per_request. This is the number
* of complete array elements that will fit in a single buffer. There
* may be some wasted space at the end of the buffer, but splitting
* elements across buffer boundries would be painful.
*/
maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq;
elements_per_request = maxSize / total_vertex_size;
totalRequests = ((count + (elements_per_request - 1))
/ elements_per_request) + 1;
/* Fill in the header data and send it away.
*/
__GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays, cmdlen+4);
emit_header(pc + 8, arrays, num_arrays, count, mode);
gc->pc = pc + (__GLX_DRAWARRAYS_CMD_HDR_SIZE + 4)
+ (__GLX_COMPONENT_HDR_SIZE * num_arrays);
__glXSendLargeChunk(gc, 1, totalRequests, gc->buf, gc->pc - gc->buf);
/* Write the actual array data.
*/
offset = 0;
requestNumber = 2;
for ( i = 0 ; i < count ; i++ ) {
if ( i == elements_per_request ) {
__glXSendLargeChunk(gc, requestNumber, totalRequests,
gc->buf, offset);
requestNumber++;
offset = 0;
count -= i;
first += i;
i = 0;
}
offset = emit_vertex(gc->buf, arrays, num_arrays, i + first, offset);
}
/* If the buffer isn't empty, emit the last, partial request.
*/
if ( offset != 0 ) {
assert(requestNumber == totalRequests);
__glXSendLargeChunk(gc, requestNumber, totalRequests, gc->buf, offset);
}
gc->pc = gc->buf;
}
/**
* Emit DrawArrays protocol. This function acts as a switch betteen
* \c emit_Render_DrawArrays and \c emit_RenderLarge_DrawArrays depending
* on how much array data is to be sent.
*/
static void
emit_DrawArraysEXT(const __GLXattribute * const state,
GLint first, GLsizei count, GLenum mode)
{
struct array_info arrays[32];
GLsizei num_arrays;
GLsizei total_vertex_size;
__GLXcontext *gc = __glXGetCurrentContext();
GLuint cmdlen;
/* Determine how big the final request will be. This depends on a number
* of factors. It depends on how many array elemets there are (which is
* the passed-in 'count'), how many arrays are enabled, how many elements
* are in each array entry, and what the types are for each array.
*/
cmdlen = prep_arrays(state, arrays, count, & num_arrays,
& total_vertex_size);
/* If the data payload and the protocol header is too large for a Render
* command, use a RenderLarge command.
*/
if (cmdlen > gc->maxSmallRenderCommandSize) {
emit_RenderLarge_DrawArrays(gc, arrays, first, count, num_arrays,
mode, cmdlen, total_vertex_size);
}
else {
emit_Render_DrawArrays(gc, arrays, first, count, num_arrays,
mode, cmdlen, total_vertex_size);
}
}
/**
* Emit a DrawArrays call using the old "protocol." This isn't really
* DrawArrays protocol at all. It just simulates DrawArrays by using
* immediate-mode vertex calls. Very, very slow for large arrays, but works
* with every GLX server.
*/
static void
emit_DrawArrays_old(const __GLXattribute * const state,
GLint first, GLsizei count, GLenum mode)
{
const __GLXvertArrayState *va = &state->vertArray;
const GLubyte *vaPtr[__GLX_MAX_ARRAYS];
const GLubyte *tcaPtr[__GLX_MAX_TEXTURE_UNITS];
GLint i, j;
/*
** Set up pointers for quick array traversal.
*/
(void) memset( vaPtr, 0, sizeof(vaPtr) );
(void) memset( tcaPtr, 0, sizeof(tcaPtr) );
for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
vaPtr[ j ] = va->arrays[ j ].ptr + first * va->arrays[ j ].skip;
}
}
for ( j = 0 ; j < __GLX_MAX_TEXTURE_UNITS ; j++ ) {
if (IS_TEXARRAY_ENABLED(state, j))
tcaPtr[ j ] = va->texCoord[ j ].ptr + first * va->texCoord[ j ].skip;
}
__indirect_glBegin(mode);
for (i = 0; i < count; i++) {
if (IS_TEXARRAY_ENABLED(state, 0)) {
(*va->texCoord[0].proc)(tcaPtr[0]);
tcaPtr[0] += va->texCoord[0].skip;
}
/* Multitexturing is handled specially because the protocol
* requires an extra parameter.
*/
for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
if (IS_TEXARRAY_ENABLED(state, j)) {
(*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, tcaPtr[j]);
tcaPtr[j] += va->texCoord[j].skip;
}
}
for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
(*va->arrays[ j ].proc)(vaPtr[ j ]);
vaPtr[ j ] += va->arrays[ j ].skip;
}
}
}
__indirect_glEnd();
}
/**
* Validate that the \c mode and \c count parameters to \c glDrawArrays or
* \c glDrawElements are valid. If the arguments are not valid, then an
* error code is set in the GLX context.
*
* \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are
* not.
*/
static GLboolean
glx_validate_array_args(__GLXcontext *gc, GLenum mode, GLsizei count)
{
switch(mode) {
case GL_POINTS:
case GL_LINE_STRIP:
case GL_LINE_LOOP:
case GL_LINES:
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN:
case GL_TRIANGLES:
case GL_QUAD_STRIP:
case GL_QUADS:
case GL_POLYGON:
break;
default:
__glXSetError(gc, GL_INVALID_ENUM);
return GL_FALSE;
}
if (count < 0) {
__glXSetError(gc, GL_INVALID_VALUE);
return GL_FALSE;
}
return GL_TRUE;
}
void __indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
__GLXcontext *gc = __glXGetCurrentContext();
const __GLXattribute * state =
(const __GLXattribute *)(gc->client_state_private);
if ( ! glx_validate_array_args(gc, mode, count) ) {
return;
}
/* The "true" DrawArrays protocol does not support generic attributes,
* multiple vertex arrays, or multiple texture coordinate arrays.
*/
if ( state->NoDrawArraysProtocol
|| (state->vertArray.texture_enables > 1) ) {
emit_DrawArrays_old(state, first, count, mode);
}
else {
emit_DrawArraysEXT(state, first, count, mode);
}
}
/**
* \todo Modify this to use the "true" DrawArrays protocol if possible. This
* would probably require refactoring out parts of \c emit_DrawArraysEXT into
* more general functions that could be used in either place.
*/
void __indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
__GLXvertArrayState *va = &state->vertArray;
const GLubyte *iPtr1 = NULL;
const GLushort *iPtr2 = NULL;
const GLuint *iPtr3 = NULL;
GLint i, j, offset = 0;
if ( ! glx_validate_array_args(gc, mode, count) ) {
return;
}
switch (type) {
case GL_UNSIGNED_BYTE:
iPtr1 = (const GLubyte *)indices;
break;
case GL_UNSIGNED_SHORT:
iPtr2 = (const GLushort *)indices;
break;
case GL_UNSIGNED_INT:
iPtr3 = (const GLuint *)indices;
break;
default:
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
__indirect_glBegin(mode);
for (i = 0; i < count; i++) {
switch (type) {
case GL_UNSIGNED_BYTE:
offset = (GLint)(*iPtr1++);
break;
case GL_UNSIGNED_SHORT:
offset = (GLint)(*iPtr2++);
break;
case GL_UNSIGNED_INT:
offset = (GLint)(*iPtr3++);
break;
}
if (IS_TEXARRAY_ENABLED(state, 0)) {
(*va->texCoord[0].proc)(va->texCoord[0].ptr+
(offset*va->texCoord[0].skip));
}
/* Multitexturing is handled specially because the protocol
* requires an extra parameter.
*/
for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) {
if (IS_TEXARRAY_ENABLED(state, j)) {
(*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j,
va->texCoord[j].ptr+
(offset*va->texCoord[j].skip));
}
}
for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) {
if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) {
(*va->arrays[ j ].proc)(va->arrays[ j ].ptr
+(offset*va->arrays[ j ].skip));
}
}
}
__indirect_glEnd();
}
void __indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices)
{
__GLXcontext *gc = __glXGetCurrentContext();
if (end < start) {
__glXSetError(gc, GL_INVALID_VALUE);
return;
}
__indirect_glDrawElements(mode,count,type,indices);
}
void __indirect_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count,
GLsizei primcount)
{
GLsizei i;
for(i=0; i<primcount; i++) {
if ( count[i] > 0 ) {
__indirect_glDrawArrays( mode, first[i], count[i] );
}
}
}
void __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count,
GLenum type, const GLvoid ** indices,
GLsizei primcount)
{
GLsizei i;
for(i=0; i<primcount; i++) {
if ( count[i] > 0 ) {
__indirect_glDrawElements( mode, count[i], type, indices[i] );
}
}
}
void __indirect_glClientActiveTextureARB(GLenum texture)
{
__GLXcontext *gc = __glXGetCurrentContext();
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
GLint unit = (GLint) texture - GL_TEXTURE0;
if (unit < 0 || __GLX_MAX_TEXTURE_UNITS <= unit) {
__glXSetError(gc, GL_INVALID_ENUM);
return;
}
state->vertArray.activeTexture = unit;
}