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.tags/before_upgrade_03_01_05
@@ -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; | |||
if ( array == GL_TEXTURE_COORD_ARRAY ) { | |||
index = __glXGetActiveTextureUnit( state ); | |||
} | |||
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 ( ! __glXSetArrayEnable( state, array, index, val ) ) { | |||
__glXSetError(gc, GL_INVALID_ENUM); | |||
} | |||
} | |||
void __indirect_glDisableClientState(GLenum array) | |||
void __indirect_glEnableClientState(GLenum array) | |||
{ | |||
__GLXcontext *gc = __glXGetCurrentContext(); | |||
__GLXattribute * state = (__GLXattribute *)(gc->client_state_private); | |||
do_enable_disable( array, GL_TRUE ); | |||
} | |||
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); | |||
} | |||
void __indirect_glDisableClientState(GLenum array) | |||
{ | |||
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) | |||
} | |||
} | |||
} | |||
@@ -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) | |||
typedef struct __GLXattributeRec { | |||
GLuint mask; | |||
/** | |||
* 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. | |||
* 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. | |||
*/ | |||
GLuint enables; | |||
__GLXpixelStoreMode storePack, storeUnpack; | |||
/** | |||
* Which of the texture coordinate arrays are enabled? | |||
* Is EXT_vertex_array / GL 1.1 DrawArrays protocol specifically | |||
* disabled? | |||
*/ | |||
GLuint texture_enables; | |||
GLboolean NoDrawArraysProtocol; | |||
/** | |||
* 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. | |||
* 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. | |||
*/ | |||
__GLXvertexArrayPointerState arrays[__GLX_MAX_ARRAYS]; | |||
__GLXvertexArrayPointerState texCoord[__GLX_MAX_TEXTURE_UNITS]; | |||
GLint maxElementsVertices; | |||
GLint maxElementsIndices; | |||
GLint activeTexture; | |||
} __GLXvertArrayState; | |||
typedef struct __GLXattributeRec { | |||
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; | |||
/* | |||
** 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; | |||
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) \ |
@@ -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]; | |||
/* |
@@ -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 ) ); | |||
} | |||
@@ -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. | |||
*/ |
@@ -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 */ |
@@ -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; | |||
} |
@@ -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; | |||
} |