From 1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 7 May 2009 13:52:26 -0600 Subject: mesa: reference counting for gl_array_object Every kind of object that can be shared by multiple contexts should be refcounted. --- src/mesa/main/arrayobj.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index c7d66ec166..9c4036af5a 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -41,17 +41,26 @@ * Internal functions */ -struct gl_array_object * _mesa_new_array_object( GLcontext *ctx, - GLuint name ); +extern struct gl_array_object * +_mesa_new_array_object( GLcontext *ctx, GLuint name ); -void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); -void _mesa_initialize_array_object( GLcontext *ctx, - struct gl_array_object *obj, GLuint name ); +extern void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj); -void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_initialize_array_object( GLcontext *ctx, + struct gl_array_object *obj, GLuint name ); -void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); + +extern void +_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); -- cgit v1.2.3 From fa95ecb467d656e293a12c089b3e85fcbbadb848 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 7 May 2009 14:33:18 -0600 Subject: mesa: make the array object save/remove functions static --- src/mesa/main/arrayobj.c | 14 +++++++------- src/mesa/main/arrayobj.h | 7 ------- 2 files changed, 7 insertions(+), 14 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index b4d1a77b97..8ec73b9526 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -243,8 +243,8 @@ _mesa_initialize_array_object( GLcontext *ctx, /** * Add the given array object to the array object pool. */ -void -_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ) +static void +save_array_object( GLcontext *ctx, struct gl_array_object *obj ) { if (obj->Name > 0) { /* insert into hash table */ @@ -257,8 +257,8 @@ _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ) * Remove the given array object from the array object pool. * Do not deallocate the array object though. */ -void -_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ) +static void +remove_array_object( GLcontext *ctx, struct gl_array_object *obj ) { if (obj->Name > 0) { /* remove from hash table */ @@ -312,7 +312,7 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); return; } - _mesa_save_array_object(ctx, newObj); + save_array_object(ctx, newObj); } } @@ -361,7 +361,7 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) } /* The ID is immediately freed for re-use */ - _mesa_remove_array_object(ctx, obj); + remove_array_object(ctx, obj); /* Unreference the array object. * If refcount hits zero, the object will be deleted. @@ -415,7 +415,7 @@ _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); return; } - _mesa_save_array_object(ctx, obj); + save_array_object(ctx, obj); arrays[i] = first + i; } diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index 9c4036af5a..9c2f340cfa 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -56,13 +56,6 @@ extern void _mesa_initialize_array_object( GLcontext *ctx, struct gl_array_object *obj, GLuint name ); -extern void -_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); - -extern void -_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); - - /* * API functions -- cgit v1.2.3 From 5568f2f601fbd974af402da92548904f6fafc6dc Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Wed, 13 May 2009 09:27:31 -0600 Subject: mesa: reference counting for gl_array_object Every kind of object that can be shared by multiple contexts should be refcounted. (cherry picked from commit 1030bf0ded2a88a5e27f7a4d393c11cfde3d3c5a) --- src/mesa/main/arrayobj.c | 67 +++++++++++++++++++++++++++++++++++++++++++++--- src/mesa/main/arrayobj.h | 23 ++++++++++++----- src/mesa/main/mtypes.h | 3 +++ src/mesa/main/varray.c | 4 +-- 4 files changed, 84 insertions(+), 13 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index b04095fd16..ccb5b8e157 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -94,10 +94,69 @@ void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ) { (void) ctx; + _glthread_DESTROY_MUTEX(obj->Mutex); _mesa_free(obj); } +/** + * Set ptr to arrayObj w/ reference counting. + */ +void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj) +{ + if (*ptr == arrayObj) + return; + + if (*ptr) { + /* Unreference the old array object */ + GLboolean deleteFlag = GL_FALSE; + struct gl_array_object *oldObj = *ptr; + + _glthread_LOCK_MUTEX(oldObj->Mutex); + ASSERT(oldObj->RefCount > 0); + oldObj->RefCount--; +#if 0 + printf("ArrayObj %p %d DECR to %d\n", + (void *) oldObj, oldObj->Name, oldObj->RefCount); +#endif + deleteFlag = (oldObj->RefCount == 0); + _glthread_UNLOCK_MUTEX(oldObj->Mutex); + + if (deleteFlag) { + ASSERT(ctx->Driver.DeleteArrayObject); + ctx->Driver.DeleteArrayObject(ctx, oldObj); + } + + *ptr = NULL; + } + ASSERT(!*ptr); + + if (arrayObj) { + /* reference new array object */ + _glthread_LOCK_MUTEX(arrayObj->Mutex); + if (arrayObj->RefCount == 0) { + /* this array's being deleted (look just above) */ + /* Not sure this can every really happen. Warn if it does. */ + _mesa_problem(NULL, "referencing deleted array object"); + *ptr = NULL; + } + else { + arrayObj->RefCount++; +#if 0 + printf("ArrayObj %p %d INCR to %d\n", + (void *) arrayObj, arrayObj->Name, arrayObj->RefCount); +#endif + *ptr = arrayObj; + } + _glthread_UNLOCK_MUTEX(arrayObj->Mutex); + } +} + + + static void init_array(GLcontext *ctx, struct gl_client_array *array, GLint size, GLint type) @@ -129,6 +188,9 @@ _mesa_initialize_array_object( GLcontext *ctx, obj->Name = name; + _glthread_INIT_MUTEX(obj->Mutex); + obj->RefCount = 1; + /* Init the individual arrays */ init_array(ctx, &obj->Vertex, 4, GL_FLOAT); init_array(ctx, &obj->Normal, 3, GL_FLOAT); @@ -226,7 +288,6 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) if (!newObj) { /* If this is a new array object id, allocate an array object now. */ - newObj = (*ctx->Driver.NewArrayObject)(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); @@ -236,11 +297,9 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) } } - ctx->NewState |= _NEW_ARRAY; ctx->Array.NewState |= _NEW_ARRAY_ALL; - ctx->Array.ArrayObj = newObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, newObj); /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index c7d66ec166..9c4036af5a 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -41,17 +41,26 @@ * Internal functions */ -struct gl_array_object * _mesa_new_array_object( GLcontext *ctx, - GLuint name ); +extern struct gl_array_object * +_mesa_new_array_object( GLcontext *ctx, GLuint name ); -void _mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_delete_array_object( GLcontext *ctx, struct gl_array_object *obj ); -void _mesa_initialize_array_object( GLcontext *ctx, - struct gl_array_object *obj, GLuint name ); +extern void +_mesa_reference_array_object(GLcontext *ctx, + struct gl_array_object **ptr, + struct gl_array_object *arrayObj); -void _mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_initialize_array_object( GLcontext *ctx, + struct gl_array_object *obj, GLuint name ); -void _mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); +extern void +_mesa_save_array_object( GLcontext *ctx, struct gl_array_object *obj ); + +extern void +_mesa_remove_array_object( GLcontext *ctx, struct gl_array_object *obj ); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index ed6b1062bd..50dc2def87 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1557,6 +1557,9 @@ struct gl_array_object /** Name of the array object as received from glGenVertexArrayAPPLE. */ GLuint Name; + GLint RefCount; + _glthread_Mutex Mutex; + /** Conventional vertex arrays */ /*@{*/ struct gl_client_array Vertex; diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index 106252e460..72b3e834b3 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -1050,7 +1050,7 @@ void _mesa_init_varray(GLcontext *ctx) { ctx->Array.DefaultArrayObj = _mesa_new_array_object(ctx, 0); - ctx->Array.ArrayObj = ctx->Array.DefaultArrayObj; - + _mesa_reference_array_object(ctx, &ctx->Array.ArrayObj, + ctx->Array.DefaultArrayObj); ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */ } -- cgit v1.2.3 From de1cfc5e8a8e9d0b0b397671575ae448a554a002 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Thu, 21 May 2009 09:56:41 -0600 Subject: mesa: new _mesa_update_array_object_max_element() function This will replace the code in state.c --- src/mesa/main/arrayobj.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++- src/mesa/main/arrayobj.h | 7 ++++- 2 files changed, 83 insertions(+), 2 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index 8ec73b9526..eab6fac94e 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -1,9 +1,10 @@ /* * Mesa 3-D graphics library - * Version: 7.2 + * Version: 7.6 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * (C) Copyright IBM Corporation 2006 + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -46,6 +47,7 @@ #include "bufferobj.h" #endif #include "arrayobj.h" +#include "macros.h" #include "glapi/dispatch.h" @@ -267,6 +269,80 @@ remove_array_object( GLcontext *ctx, struct gl_array_object *obj ) } + +/** + * Compute the index of the last array element that can be safely accessed + * in a vertex array. We can really only do this when the array lives in + * a VBO. + * The array->_MaxElement field will be updated. + * Later in glDrawArrays/Elements/etc we can do some bounds checking. + */ +static void +compute_max_element(struct gl_client_array *array) +{ + if (array->BufferObj->Name) { + /* Compute the max element we can access in the VBO without going + * out of bounds. + */ + array->_MaxElement = ((GLsizeiptrARB) array->BufferObj->Size + - (GLsizeiptrARB) array->Ptr + array->StrideB + - array->_ElementSize) / array->StrideB; + if (0) + _mesa_printf("%s Object %u Size %u MaxElement %u\n", + __FUNCTION__, + array->BufferObj->Name, + (GLuint) array->BufferObj->Size, + array->_MaxElement); + } + else { + /* user-space array, no idea how big it is */ + array->_MaxElement = 2 * 1000 * 1000 * 1000; /* just a big number */ + } +} + + +/** + * Helper for update_arrays(). + * \return min(current min, array->_MaxElement). + */ +static GLuint +update_min(GLuint min, struct gl_client_array *array) +{ + compute_max_element(array); + if (array->Enabled) + return MIN2(min, array->_MaxElement); + else + return min; +} + + +/** + * Examine vertex arrays to update the gl_array_object::_MaxElement field. + */ +void +_mesa_update_array_object_max_element(GLcontext *ctx, + struct gl_array_object *arrayObj) +{ + GLuint i, min = ~0; + + min = update_min(min, &arrayObj->Vertex); + min = update_min(min, &arrayObj->Normal); + min = update_min(min, &arrayObj->Color); + min = update_min(min, &arrayObj->SecondaryColor); + min = update_min(min, &arrayObj->FogCoord); + min = update_min(min, &arrayObj->Index); + min = update_min(min, &arrayObj->EdgeFlag); + min = update_min(min, &arrayObj->PointSize); + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) + min = update_min(min, &arrayObj->TexCoord[i]); + for (i = 0; i < VERT_ATTRIB_MAX; i++) + min = update_min(min, &arrayObj->VertexAttrib[i]); + + /* _MaxElement is one past the last legal array element */ + arrayObj->_MaxElement = min; +} + + /**********************************************************************/ /* API Functions */ /**********************************************************************/ diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index 90c2aea155..abca5ab9b4 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -1,9 +1,10 @@ /* * Mesa 3-D graphics library - * Version: 6.5 + * Version: 7.6 * * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * (C) Copyright IBM Corporation 2006 + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -57,6 +58,10 @@ _mesa_initialize_array_object( GLcontext *ctx, struct gl_array_object *obj, GLuint name ); +extern void +_mesa_update_array_object_max_element(GLcontext *ctx, + struct gl_array_object *arrayObj); + /* * API functions -- cgit v1.2.3 From b8000c874ecb33b1554407c5e568afbb471dda3a Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 19 Jun 2009 18:07:49 -0600 Subject: mesa: implement _mesa_BindVertexArray() --- src/mesa/main/arrayobj.c | 55 +++++++++++++++++++++++++++++++++++++----------- src/mesa/main/arrayobj.h | 3 +++ 2 files changed, 46 insertions(+), 12 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index e078f69ff9..ae9db212ae 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -353,18 +353,15 @@ _mesa_update_array_object_max_element(GLcontext *ctx, /* API Functions */ /**********************************************************************/ + /** - * Bind a new array. - * - * \todo - * The binding could be done more efficiently by comparing the non-NULL - * pointers in the old and new objects. The only arrays that are "dirty" are - * the ones that are non-NULL in either object. + * Helper for _mesa_BindVertexArray() and _mesa_BindVertexArrayAPPLE(). + * \param genRequired specifies behavour when id was not generated with + * glGenVertexArrays(). */ -void GLAPIENTRY -_mesa_BindVertexArrayAPPLE( GLuint id ) +static void +bind_vertex_array(GLcontext *ctx, GLuint id, GLboolean genRequired) { - GET_CURRENT_CONTEXT(ctx); struct gl_array_object * const oldObj = ctx->Array.ArrayObj; struct gl_array_object *newObj = NULL; ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -387,8 +384,12 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) /* non-default array object */ newObj = lookup_arrayobj(ctx, id); if (!newObj) { - /* If this is a new array object id, allocate an array object now. - */ + if (genRequired) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glBindVertexArray(id)"); + return; + } + + /* For APPLE version, generate a new array object now */ newObj = (*ctx->Driver.NewArrayObject)(ctx, id); if (!newObj) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindVertexArrayAPPLE"); @@ -404,7 +405,37 @@ _mesa_BindVertexArrayAPPLE( GLuint id ) /* Pass BindVertexArray call to device driver */ if (ctx->Driver.BindArrayObject && newObj) - (*ctx->Driver.BindArrayObject)( ctx, newObj ); + ctx->Driver.BindArrayObject(ctx, newObj); +} + + +/** + * ARB version of glBindVertexArray() + * This function behaves differently from glBindVertexArrayAPPLE() in + * that this function requires all ids to have been previously generated + * by glGenVertexArrays[APPLE](). + */ +void GLAPIENTRY +_mesa_BindVertexArray( GLuint id ) +{ + GET_CURRENT_CONTEXT(ctx); + bind_vertex_array(ctx, id, GL_TRUE); +} + + +/** + * Bind a new array. + * + * \todo + * The binding could be done more efficiently by comparing the non-NULL + * pointers in the old and new objects. The only arrays that are "dirty" are + * the ones that are non-NULL in either object. + */ +void GLAPIENTRY +_mesa_BindVertexArrayAPPLE( GLuint id ) +{ + GET_CURRENT_CONTEXT(ctx); + bind_vertex_array(ctx, id, GL_FALSE); } diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index abca5ab9b4..e2f156d16c 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -67,6 +67,9 @@ _mesa_update_array_object_max_element(GLcontext *ctx, * API functions */ + +void GLAPIENTRY _mesa_BindVertexArray( GLuint id ); + void GLAPIENTRY _mesa_BindVertexArrayAPPLE( GLuint id ); void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids); -- cgit v1.2.3 From 9342e6f5a94d3b884dcb98b4741295f1aa23e282 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 19 Jun 2009 18:17:25 -0600 Subject: mesa: implement _mesa_GenVertexArrays() for GL_ARB_vertex_array_object This also involves adding a gl_array_object::VBOonly field. For the ARB extension, all arrays in the object must reside in a VBO. This flag keeps track of that requirement. --- src/mesa/main/arrayobj.c | 33 +++++++++++++++++++++++++++++---- src/mesa/main/arrayobj.h | 2 ++ src/mesa/main/mtypes.h | 1 + 3 files changed, 32 insertions(+), 4 deletions(-) (limited to 'src/mesa/main/arrayobj.h') diff --git a/src/mesa/main/arrayobj.c b/src/mesa/main/arrayobj.c index ae9db212ae..fd35d4e38c 100644 --- a/src/mesa/main/arrayobj.c +++ b/src/mesa/main/arrayobj.c @@ -485,14 +485,14 @@ _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids) /** * Generate a set of unique array object IDs and store them in \c arrays. - * + * Helper for _mesa_GenVertexArrays[APPLE]() functions below. * \param n Number of IDs to generate. * \param arrays Array of \c n locations to store the IDs. + * \param vboOnly Will arrays have to reside in VBOs? */ -void GLAPIENTRY -_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) +static void +gen_vertex_arrays(GLcontext *ctx, GLsizei n, GLuint *arrays, GLboolean vboOnly) { - GET_CURRENT_CONTEXT(ctx); GLuint first; GLint i; ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -518,12 +518,37 @@ _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenVertexArraysAPPLE"); return; } + obj->VBOonly = vboOnly; save_array_object(ctx, obj); arrays[i] = first + i; } } +/** + * ARB version of glGenVertexArrays() + * All arrays will be required to live in VBOs. + */ +void GLAPIENTRY +_mesa_GenVertexArrays(GLsizei n, GLuint *arrays) +{ + GET_CURRENT_CONTEXT(ctx); + gen_vertex_arrays(ctx, n, arrays, GL_TRUE); +} + + +/** + * APPLE version of glGenVertexArraysAPPLE() + * Arrays may live in VBOs or ordinary memory. + */ +void GLAPIENTRY +_mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *arrays) +{ + GET_CURRENT_CONTEXT(ctx); + gen_vertex_arrays(ctx, n, arrays, GL_FALSE); +} + + /** * Determine if ID is the name of an array object. * diff --git a/src/mesa/main/arrayobj.h b/src/mesa/main/arrayobj.h index e2f156d16c..8999edc724 100644 --- a/src/mesa/main/arrayobj.h +++ b/src/mesa/main/arrayobj.h @@ -74,6 +74,8 @@ void GLAPIENTRY _mesa_BindVertexArrayAPPLE( GLuint id ); void GLAPIENTRY _mesa_DeleteVertexArraysAPPLE(GLsizei n, const GLuint *ids); +void GLAPIENTRY _mesa_GenVertexArrays(GLsizei n, GLuint *arrays); + void GLAPIENTRY _mesa_GenVertexArraysAPPLE(GLsizei n, GLuint *buffer); GLboolean GLAPIENTRY _mesa_IsVertexArrayAPPLE( GLuint id ); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 69a23fe98a..0d082cbc8a 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1563,6 +1563,7 @@ struct gl_array_object GLint RefCount; _glthread_Mutex Mutex; + GLboolean VBOonly; /**< require all arrays to live in VBOs? */ /** Conventional vertex arrays */ /*@{*/ -- cgit v1.2.3