mesa: Add ARB_vertex_attrib_binding

update_array() and update_array_format() are changed to update the new
attrib and binding states, and the client arrays become derived state.

Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
Fredrik Höglund 2013-04-09 20:54:25 +02:00
parent bb2d02c7b5
commit 59b01ca252
16 changed files with 691 additions and 125 deletions

View file

@ -35,6 +35,7 @@
*/
#include "glheader.h"
#include "arrayobj.h"
#include "api_arrayelt.h"
#include "bufferobj.h"
#include "context.h"
@ -1485,6 +1486,12 @@ _ae_update_state(struct gl_context *ctx)
actx->nr_vbos = 0;
if (arrayObj->NewArrays) {
/* update the derived client arrays */
_mesa_update_array_object_client_arrays(ctx, arrayObj);
arrayObj->NewArrays = 0;
}
/* conventional vertex arrays */
if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX];

View file

@ -120,7 +120,7 @@ check_valid_to_render(struct gl_context *ctx, const char *function)
case API_OPENGLES:
/* For OpenGL ES, only draw if we have vertex positions
*/
if (!ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
if (!ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
return GL_FALSE;
break;
@ -141,8 +141,8 @@ check_valid_to_render(struct gl_context *ctx, const char *function)
/* Draw if we have vertex positions (GL_VERTEX_ARRAY or generic
* array [0]).
*/
return (ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled ||
ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled);
return (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled ||
ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled);
}
}
break;

View file

@ -72,7 +72,7 @@ _mesa_lookup_arrayobj(struct gl_context *ctx, GLuint id)
/**
* For all the vertex arrays in the array object, unbind any pointers
* For all the vertex binding points in the array object, unbind any pointers
* to any buffer objects (VBOs).
* This is done just prior to array object destruction.
*/
@ -81,6 +81,9 @@ unbind_array_object_vbos(struct gl_context *ctx, struct gl_array_object *obj)
{
GLuint i;
for (i = 0; i < Elements(obj->VertexBinding); i++)
_mesa_reference_buffer_object(ctx, &obj->VertexBinding[i].BufferObj, NULL);
for (i = 0; i < Elements(obj->_VertexAttrib); i++)
_mesa_reference_buffer_object(ctx, &obj->_VertexAttrib[i].BufferObj, NULL);
}
@ -181,20 +184,30 @@ _mesa_reference_array_object_(struct gl_context *ctx,
static void
init_array(struct gl_context *ctx,
struct gl_client_array *array, GLint size, GLint type)
struct gl_array_object *obj, GLuint index, GLint size, GLint type)
{
struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index];
struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index];
array->Size = size;
array->Type = type;
array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
array->Stride = 0;
array->StrideB = 0;
array->Ptr = NULL;
array->RelativeOffset = 0;
array->Enabled = GL_FALSE;
array->Normalized = GL_FALSE;
array->Integer = GL_FALSE;
array->_ElementSize = size * _mesa_sizeof_type(type);
array->VertexBinding = index;
binding->Offset = 0;
binding->Stride = array->_ElementSize;
binding->BufferObj = NULL;
binding->_BoundArrays = BITFIELD64_BIT(index);
/* Vertex array buffers */
_mesa_reference_buffer_object(ctx, &array->BufferObj,
_mesa_reference_buffer_object(ctx, &binding->BufferObj,
ctx->Shared->NullBufferObj);
}
@ -218,28 +231,28 @@ _mesa_initialize_array_object( struct gl_context *ctx,
for (i = 0; i < Elements(obj->_VertexAttrib); i++) {
switch (i) {
case VERT_ATTRIB_WEIGHT:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_WEIGHT], 1, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT);
break;
case VERT_ATTRIB_NORMAL:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_NORMAL], 3, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_NORMAL, 3, GL_FLOAT);
break;
case VERT_ATTRIB_COLOR1:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_COLOR1], 3, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_COLOR1, 3, GL_FLOAT);
break;
case VERT_ATTRIB_FOG:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_FOG], 1, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_FOG, 1, GL_FLOAT);
break;
case VERT_ATTRIB_COLOR_INDEX:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX], 1, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT);
break;
case VERT_ATTRIB_EDGEFLAG:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG], 1, GL_BOOL);
init_array(ctx, obj, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL);
break;
case VERT_ATTRIB_POINT_SIZE:
init_array(ctx, &obj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE], 1, GL_FLOAT);
init_array(ctx, obj, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
break;
default:
init_array(ctx, &obj->_VertexAttrib[i], 4, GL_FLOAT);
init_array(ctx, obj, i, 4, GL_FLOAT);
break;
}
}
@ -322,6 +335,32 @@ _mesa_update_array_object_max_element(struct gl_context *ctx,
}
/**
* Updates the derived gl_client_arrays when a gl_vertex_attrib_array
* or a gl_vertex_buffer_binding has changed.
*/
void
_mesa_update_array_object_client_arrays(struct gl_context *ctx, struct gl_array_object *arrayObj)
{
GLbitfield64 arrays = arrayObj->NewArrays;
while (arrays) {
struct gl_client_array *client_array;
struct gl_vertex_attrib_array *attrib_array;
struct gl_vertex_buffer_binding *buffer_binding;
GLint attrib = ffsll(arrays) - 1;
arrays ^= BITFIELD64_BIT(attrib);
attrib_array = &arrayObj->VertexAttrib[attrib];
buffer_binding = &arrayObj->VertexBinding[attrib_array->VertexBinding];
client_array = &arrayObj->_VertexAttrib[attrib];
_mesa_update_client_array(ctx, client_array, attrib_array, buffer_binding);
}
}
/**********************************************************************/
/* API Functions */
/**********************************************************************/

View file

@ -78,6 +78,11 @@ extern void
_mesa_update_array_object_max_element(struct gl_context *ctx,
struct gl_array_object *arrayObj);
extern void
_mesa_update_array_object_client_arrays(struct gl_context *ctx,
struct gl_array_object *arrayObj);
/** Returns the bitmask of all enabled arrays in fixed function mode.
*
* In fixed function mode only the traditional fixed function arrays

View file

@ -1369,8 +1369,11 @@ copy_array_object(struct gl_context *ctx,
/* In theory must be the same anyway, but on recreate make sure it matches */
dest->ARBsemantics = src->ARBsemantics;
for (i = 0; i < Elements(src->_VertexAttrib); i++)
for (i = 0; i < Elements(src->_VertexAttrib); i++) {
_mesa_copy_client_array(ctx, &dest->_VertexAttrib[i], &src->_VertexAttrib[i]);
_mesa_copy_vertex_attrib_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]);
_mesa_copy_vertex_buffer_binding(ctx, &dest->VertexBinding[i], &src->VertexBinding[i]);
}
/* _Enabled must be the same than on push */
dest->_Enabled = src->_Enabled;

View file

@ -864,8 +864,8 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids)
}
/* unbind any vertex pointers bound to this buffer */
for (j = 0; j < Elements(arrayObj->_VertexAttrib); j++) {
unbind(ctx, &arrayObj->_VertexAttrib[j].BufferObj, bufObj);
for (j = 0; j < Elements(arrayObj->VertexBinding); j++) {
unbind(ctx, &arrayObj->VertexBinding[j].BufferObj, bufObj);
}
if (ctx->Array.ArrayBufferObj == bufObj) {

View file

@ -678,6 +678,10 @@ _mesa_init_constants(struct gl_context *ctx)
ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE;
ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS;
ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS;
/* GL_ARB_vertex_attrib_binding */
ctx->Const.MaxVertexAttribRelativeOffset = 2047;
ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS;
}

View file

@ -69,40 +69,40 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state)
switch (cap) {
case GL_VERTEX_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled;
flag = VERT_BIT_POS;
break;
case GL_NORMAL_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled;
flag = VERT_BIT_NORMAL;
break;
case GL_COLOR_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled;
flag = VERT_BIT_COLOR0;
break;
case GL_INDEX_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled;
flag = VERT_BIT_COLOR_INDEX;
break;
case GL_TEXTURE_COORD_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled;
flag = VERT_BIT_TEX(ctx->Array.ActiveTexture);
break;
case GL_EDGE_FLAG_ARRAY:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled;
flag = VERT_BIT_EDGEFLAG;
break;
case GL_FOG_COORDINATE_ARRAY_EXT:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled;
flag = VERT_BIT_FOG;
break;
case GL_SECONDARY_COLOR_ARRAY_EXT:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled;
flag = VERT_BIT_COLOR1;
break;
case GL_POINT_SIZE_ARRAY_OES:
var = &arrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled;
var = &arrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled;
flag = VERT_BIT_POINT_SIZE;
break;
@ -1417,41 +1417,41 @@ _mesa_IsEnabled( GLenum cap )
case GL_VERTEX_ARRAY:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled;
case GL_NORMAL_ARRAY:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled;
case GL_COLOR_ARRAY:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled;
case GL_INDEX_ARRAY:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_enum_error;
return ctx->Array.ArrayObj->
_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled;
VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled;
case GL_TEXTURE_COORD_ARRAY:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_enum_error;
return ctx->Array.ArrayObj->
_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled;
VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].Enabled;
case GL_EDGE_FLAG_ARRAY:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled;
case GL_FOG_COORDINATE_ARRAY_EXT:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled;
case GL_SECONDARY_COLOR_ARRAY_EXT:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled;
case GL_POINT_SIZE_ARRAY_OES:
if (ctx->API != API_OPENGLES)
goto invalid_enum_error;
return ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled;
return ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled;
/* GL_ARB_texture_cube_map */
case GL_TEXTURE_CUBE_MAP_ARB:

View file

@ -228,7 +228,7 @@ static void make_state_key( struct gl_context *ctx, struct state_key *key )
if (ctx->Point._Attenuated)
key->point_attenuated = 1;
if (ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled)
if (ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled)
key->point_array = 1;
if (ctx->Texture._TexGenEnabled ||

View file

@ -550,7 +550,7 @@ static void
find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v)
{
struct gl_buffer_object **buffer_obj;
struct gl_client_array *array;
struct gl_vertex_attrib_array *array;
GLuint unit, *p;
switch (d->pname) {
@ -629,7 +629,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
case GL_TEXTURE_COORD_ARRAY_SIZE:
case GL_TEXTURE_COORD_ARRAY_TYPE:
case GL_TEXTURE_COORD_ARRAY_STRIDE:
array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)];
array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)];
v->value_int = *(GLuint *) ((char *) array + d->offset);
break;
@ -775,7 +775,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
break;
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB:
v->value_int =
ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name;
ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name;
break;
case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB:
v->value_int = ctx->Array.ArrayObj->ElementArrayBufferObj->Name;
@ -819,7 +819,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu
ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0;
break;
case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
v->value_int = ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].BufferObj->Name;
v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_POINT_SIZE].BufferObj->Name;
break;
case GL_FOG_COLOR:

View file

@ -191,17 +191,17 @@ descriptor=[
[ "TEXTURE_2D", "LOC_CUSTOM, TYPE_BOOLEAN, 0, NO_EXTRA" ],
[ "TEXTURE_MATRIX", "LOC_CUSTOM, TYPE_MATRIX, 0, extra_valid_texture_unit" ],
[ "TEXTURE_STACK_DEPTH", "LOC_CUSTOM, TYPE_INT, 0, extra_valid_texture_unit" ],
[ "VERTEX_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_POS].Enabled), NO_EXTRA" ],
[ "VERTEX_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_POS].Size), NO_EXTRA" ],
[ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_POS].Type), NO_EXTRA" ],
[ "VERTEX_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_POS].Stride), NO_EXTRA" ],
[ "NORMAL_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled), NO_EXTRA" ],
[ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_NORMAL].Type), NO_EXTRA" ],
[ "NORMAL_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_NORMAL].Stride), NO_EXTRA" ],
[ "COLOR_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled), NO_EXTRA" ],
[ "COLOR_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR0].Size), NO_EXTRA" ],
[ "COLOR_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR0].Type), NO_EXTRA" ],
[ "COLOR_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR0].Stride), NO_EXTRA" ],
[ "VERTEX_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_POS].Enabled), NO_EXTRA" ],
[ "VERTEX_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_POS].Size), NO_EXTRA" ],
[ "VERTEX_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_POS].Type), NO_EXTRA" ],
[ "VERTEX_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_POS].Stride), NO_EXTRA" ],
[ "NORMAL_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_NORMAL].Enabled), NO_EXTRA" ],
[ "NORMAL_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_NORMAL].Type), NO_EXTRA" ],
[ "NORMAL_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_NORMAL].Stride), NO_EXTRA" ],
[ "COLOR_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR0].Enabled), NO_EXTRA" ],
[ "COLOR_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR0].Size), NO_EXTRA" ],
[ "COLOR_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR0].Type), NO_EXTRA" ],
[ "COLOR_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR0].Stride), NO_EXTRA" ],
[ "TEXTURE_COORD_ARRAY", "LOC_CUSTOM, TYPE_BOOLEAN, offsetof(struct gl_client_array, Enabled), NO_EXTRA" ],
[ "TEXTURE_COORD_ARRAY_SIZE", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_client_array, Size), NO_EXTRA" ],
[ "TEXTURE_COORD_ARRAY_TYPE", "LOC_CUSTOM, TYPE_ENUM, offsetof(struct gl_client_array, Type), NO_EXTRA" ],
@ -221,9 +221,9 @@ descriptor=[
[ "SAMPLE_ALPHA_TO_ONE_ARB", "CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA" ],
# GL_ARB_vertex_buffer_object
[ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ],
[ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ],
[ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ],
[ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ],
[ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ],
[ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ],
[ "TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA" ],
# GL_OES_point_sprite
@ -233,9 +233,9 @@ descriptor=[
{ "apis": ["GLES"], "params": [
# OES_point_size_array
[ "POINT_SIZE_ARRAY_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled, TYPE_BOOLEAN)" ],
[ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Type, TYPE_ENUM)" ],
[ "POINT_SIZE_ARRAY_STRIDE_OES", "ARRAY_FIELD(_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Stride, TYPE_INT)" ],
[ "POINT_SIZE_ARRAY_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Enabled, TYPE_BOOLEAN)" ],
[ "POINT_SIZE_ARRAY_TYPE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Type, TYPE_ENUM)" ],
[ "POINT_SIZE_ARRAY_STRIDE_OES", "ARRAY_FIELD(VertexAttrib[VERT_ATTRIB_POINT_SIZE].Stride, TYPE_INT)" ],
[ "POINT_SIZE_ARRAY_BUFFER_BINDING_OES", "LOC_CUSTOM, TYPE_INT, 0" ],
]},
@ -521,13 +521,13 @@ descriptor=[
[ "VERTEX_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
[ "NORMAL_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
[ "COLOR_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
[ "INDEX_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled), NO_EXTRA" ],
[ "INDEX_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Type), NO_EXTRA" ],
[ "INDEX_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride), NO_EXTRA" ],
[ "INDEX_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled), NO_EXTRA" ],
[ "INDEX_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Type), NO_EXTRA" ],
[ "INDEX_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Stride), NO_EXTRA" ],
[ "INDEX_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
[ "TEXTURE_COORD_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_EDGEFLAG].Stride), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY_COUNT_EXT", "CONST(0), NO_EXTRA" ],
# GL_ARB_texture_compression
@ -545,16 +545,16 @@ descriptor=[
# GL_EXT_secondary_color
[ "COLOR_SUM", "CONTEXT_BOOL(Fog.ColorSumEnabled), extra_ARB_vertex_program" ],
[ "CURRENT_SECONDARY_COLOR", "CONTEXT_FIELD(Current.Attrib[VERT_ATTRIB_COLOR1][0], TYPE_FLOATN_4), extra_flush_current" ],
[ "SECONDARY_COLOR_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_COLOR1].Type), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR1].Stride), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_SIZE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_COLOR1].Size), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_COLOR1].Enabled), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_COLOR1].Type), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR1].Stride), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_SIZE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_COLOR1].Size), NO_EXTRA" ],
# GL_EXT_fog_coord
[ "CURRENT_FOG_COORDINATE", "CONTEXT_FLOAT(Current.Attrib[VERT_ATTRIB_FOG][0]), extra_flush_current" ],
[ "FOG_COORDINATE_ARRAY", "ARRAY_BOOL(_VertexAttrib[VERT_ATTRIB_FOG].Enabled), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM(_VertexAttrib[VERT_ATTRIB_FOG].Type), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_STRIDE", "ARRAY_INT(_VertexAttrib[VERT_ATTRIB_FOG].Stride), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY", "ARRAY_BOOL(VertexAttrib[VERT_ATTRIB_FOG].Enabled), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_TYPE", "ARRAY_ENUM(VertexAttrib[VERT_ATTRIB_FOG].Type), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_STRIDE", "ARRAY_INT(VertexAttrib[VERT_ATTRIB_FOG].Stride), NO_EXTRA" ],
[ "FOG_COORDINATE_SOURCE", "CONTEXT_ENUM(Fog.FogCoordinateSource), NO_EXTRA" ],
# GL_NV_fog_distance
@ -585,10 +585,10 @@ descriptor=[
[ "PRIMITIVE_RESTART_INDEX_NV", "CONTEXT_INT(Array.RestartIndex), extra_NV_primitive_restart" ],
# GL_ARB_vertex_buffer_object
[ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, _VertexAttrib[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ],
[ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ],
[ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ],
[ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ],
[ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ],
# GL_ARB_vertex_program
# == GL_VERTEX_PROGRAM_NV

View file

@ -202,42 +202,42 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
case GL_VERTEX_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POS].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POS].Ptr;
break;
case GL_NORMAL_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Ptr;
break;
case GL_COLOR_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Ptr;
break;
case GL_SECONDARY_COLOR_ARRAY_POINTER_EXT:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Ptr;
break;
case GL_FOG_COORDINATE_ARRAY_POINTER_EXT:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_FOG].Ptr;
break;
case GL_INDEX_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Ptr;
break;
case GL_TEXTURE_COORD_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT && ctx->API != API_OPENGLES)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(clientUnit)].Ptr;
break;
case GL_EDGE_FLAG_ARRAY_POINTER:
if (ctx->API != API_OPENGL_COMPAT)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Ptr;
break;
case GL_FEEDBACK_BUFFER_POINTER:
if (ctx->API != API_OPENGL_COMPAT)
@ -252,7 +252,7 @@ _mesa_GetPointerv( GLenum pname, GLvoid **params )
case GL_POINT_SIZE_ARRAY_POINTER_OES:
if (ctx->API != API_OPENGLES)
goto invalid_pname;
*params = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
*params = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].Ptr;
break;
case GL_DEBUG_CALLBACK_FUNCTION_ARB:
if (!_mesa_is_desktop_gl(ctx))

View file

@ -1473,6 +1473,44 @@ struct gl_client_array
};
/**
* Vertex attribute array as seen by the client.
*
* Contains the size, type, format and normalization flag,
* along with the index of a vertex buffer binding point.
*
* Note that the Stride field corresponds to VERTEX_ATTRIB_ARRAY_STRIDE
* and is only present for backwards compatibility reasons.
* Rendering always uses VERTEX_BINDING_STRIDE.
* The gl*Pointer() functions will set VERTEX_ATTRIB_ARRAY_STRIDE
* and VERTEX_BINDING_STRIDE to the same value, while
* glBindVertexBuffer() will only set VERTEX_BINDING_STRIDE.
*/
struct gl_vertex_attrib_array
{
GLint Size; /**< Components per element (1,2,3,4) */
GLenum Type; /**< Datatype: GL_FLOAT, GL_INT, etc */
GLenum Format; /**< Default: GL_RGBA, but may be GL_BGRA */
GLsizei Stride; /**< Stride as specified with gl*Pointer() */
const GLubyte *Ptr; /**< Points to client array data. Not used when a VBO is bound */
GLintptr RelativeOffset; /**< Offset of the first element relative to the binding offset */
GLboolean Enabled; /**< Whether the array is enabled */
GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */
GLboolean Integer; /**< Fixed-point values are not converted to floats */
GLuint _ElementSize; /**< Size of each element in bytes */
GLuint VertexBinding; /**< Vertex buffer binding */
};
struct gl_vertex_buffer_binding
{
GLintptr Offset; /**< User-specified offset */
GLsizei Stride; /**< User-specified stride */
GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */
struct gl_buffer_object *BufferObj; /**< GL_ARB_vertex_buffer_object */
GLbitfield64 _BoundArrays; /**< Arrays bound to this binding point */
};
/**
* Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object
* extension, but a nice encapsulation in any case.
@ -1507,9 +1545,15 @@ struct gl_array_object
*/
GLboolean EverBound;
/** Vertex attribute arrays */
/** Derived vertex attribute arrays */
struct gl_client_array _VertexAttrib[VERT_ATTRIB_MAX];
/** Vertex attribute arrays */
struct gl_vertex_attrib_array VertexAttrib[VERT_ATTRIB_MAX];
/** Vertex buffer bindings */
struct gl_vertex_buffer_binding VertexBinding[VERT_ATTRIB_MAX];
/** Mask of VERT_BIT_* values indicating which arrays are enabled */
GLbitfield64 _Enabled;
@ -3216,6 +3260,10 @@ struct gl_constants
GLuint MaxAtomicBufferSize;
GLuint MaxCombinedAtomicBuffers;
GLuint MaxCombinedAtomicCounters;
/** GL_ARB_vertex_attrib_binding */
GLint MaxVertexAttribRelativeOffset;
GLint MaxVertexAttribBindings;
};

View file

@ -410,6 +410,9 @@ _mesa_update_state_locked( struct gl_context *ctx )
new_prog_state |= update_program( ctx );
}
if (new_state & _NEW_ARRAY)
_mesa_update_array_object_client_arrays(ctx, ctx->Array.ArrayObj);
if (ctx->Const.CheckArrayBounds &&
new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) {
_mesa_update_array_object_max_element(ctx, ctx->Array.ArrayObj);

View file

@ -102,20 +102,94 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
}
/**
* Sets the VertexBinding field in the vertex attribute given by attribIndex.
*/
static void
vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
GLuint bindingIndex)
{
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex];
if (array->VertexBinding != bindingIndex) {
const GLbitfield64 array_bit = VERT_BIT(attribIndex);
FLUSH_VERTICES(ctx, _NEW_ARRAY);
arrayObj->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit;
arrayObj->VertexBinding[bindingIndex]._BoundArrays |= array_bit;
array->VertexBinding = bindingIndex;
arrayObj->NewArrays |= array_bit;
}
}
/**
* Binds a buffer object to the vertex buffer binding point given by index,
* and sets the Offset and Stride fields.
*/
static void
bind_vertex_buffer(struct gl_context *ctx, GLuint index,
struct gl_buffer_object *vbo,
GLintptr offset, GLsizei stride)
{
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
struct gl_vertex_buffer_binding *binding = &arrayObj->VertexBinding[index];
if (binding->BufferObj != vbo ||
binding->Offset != offset ||
binding->Stride != stride) {
FLUSH_VERTICES(ctx, _NEW_ARRAY);
_mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo);
binding->Offset = offset;
binding->Stride = stride;
arrayObj->NewArrays |= binding->_BoundArrays;
}
}
/**
* Sets the InstanceDivisor field in the vertex buffer binding point
* given by bindingIndex.
*/
static void
vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex,
GLuint divisor)
{
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
struct gl_vertex_buffer_binding *binding =
&arrayObj->VertexBinding[bindingIndex];
if (binding->InstanceDivisor != divisor) {
FLUSH_VERTICES(ctx, _NEW_ARRAY);
binding->InstanceDivisor = divisor;
arrayObj->NewArrays |= binding->_BoundArrays;
}
}
/**
* Does error checking and updates the format in an attrib array.
*
* Called by update_array().
* Called by update_array() and VertexAttrib*Format().
*
* \param func Name of calling function used for error reporting
* \param attrib The index of the attribute array
* \param legalTypes Bitmask of *_BIT above indicating legal datatypes
* \param sizeMin Min allowable size value
* \param sizeMax Max allowable size value (may also be BGRA_OR_4)
* \param size Components per element (1, 2, 3 or 4)
* \param type Datatype of each component (GL_FLOAT, GL_INT, etc)
* \param normalized Whether integer types are converted to floats in [-1, 1]
* \param integer Integer-valued values (will not be normalized to [-1, 1])
* \param func Name of calling function used for error reporting
* \param attrib The index of the attribute array
* \param legalTypes Bitmask of *_BIT above indicating legal datatypes
* \param sizeMin Min allowable size value
* \param sizeMax Max allowable size value (may also be BGRA_OR_4)
* \param size Components per element (1, 2, 3 or 4)
* \param type Datatype of each component (GL_FLOAT, GL_INT, etc)
* \param normalized Whether integer types are converted to floats in [-1, 1]
* \param integer Integer-valued values (will not be normalized to [-1, 1])
* \param relativeOffset Offset of the first element relative to the binding offset.
*/
static bool
update_array_format(struct gl_context *ctx,
@ -123,9 +197,10 @@ update_array_format(struct gl_context *ctx,
GLuint attrib, GLbitfield legalTypesMask,
GLint sizeMin, GLint sizeMax,
GLint size, GLenum type,
GLboolean normalized, GLboolean integer)
GLboolean normalized, GLboolean integer,
GLuint relativeOffset)
{
struct gl_client_array *array;
struct gl_vertex_attrib_array *array;
GLbitfield typeBit;
GLuint elementSize;
GLenum format = GL_RGBA;
@ -224,19 +299,36 @@ update_array_format(struct gl_context *ctx,
return false;
}
/* The ARB_vertex_attrib_binding_spec says:
*
* An INVALID_VALUE error is generated if <relativeoffset> is larger than
* the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.
*/
if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) {
_mesa_error(ctx, GL_INVALID_VALUE,
"%s(relativeOffset=%d > "
"GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)",
func, relativeOffset);
return GL_FALSE;
}
ASSERT(size <= 4);
elementSize = _mesa_bytes_per_vertex_attrib(size, type);
assert(elementSize != -1);
array = &ctx->Array.ArrayObj->_VertexAttrib[attrib];
array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
array->Size = size;
array->Type = type;
array->Format = format;
array->Normalized = normalized;
array->Integer = integer;
array->RelativeOffset = relativeOffset;
array->_ElementSize = elementSize;
ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib);
ctx->NewState |= _NEW_ARRAY;
return true;
}
@ -266,7 +358,8 @@ update_array(struct gl_context *ctx,
GLboolean normalized, GLboolean integer,
const GLvoid *ptr)
{
struct gl_client_array *array;
struct gl_vertex_attrib_array *array;
GLsizei effectiveStride;
/* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
*
@ -286,7 +379,7 @@ update_array(struct gl_context *ctx,
}
if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax,
size, type, normalized, integer)) {
size, type, normalized, integer, 0)) {
return;
}
@ -313,16 +406,18 @@ update_array(struct gl_context *ctx,
return;
}
array = &ctx->Array.ArrayObj->_VertexAttrib[attrib];
/* Reset the vertex attrib binding */
vertex_attrib_binding(ctx, attrib, attrib);
/* The Stride and Ptr fields are not set by update_array_format() */
array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
array->Stride = stride;
array->StrideB = stride ? stride : array->_ElementSize;
array->Ptr = (const GLubyte *) ptr;
array->Ptr = (const GLvoid *) ptr;
_mesa_reference_buffer_object(ctx, &array->BufferObj,
ctx->Array.ArrayBufferObj);
ctx->NewState |= _NEW_ARRAY;
ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib);
/* Update the vertex buffer binding */
effectiveStride = stride != 0 ? stride : array->_ElementSize;
bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj,
(GLintptr) ptr, effectiveStride);
}
@ -569,10 +664,10 @@ _mesa_EnableVertexAttribArray(GLuint index)
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
if (!arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
/* was disabled, now being enabled */
FLUSH_VERTICES(ctx, _NEW_ARRAY);
arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE;
arrayObj->_Enabled |= VERT_BIT_GENERIC(index);
arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
}
@ -595,10 +690,10 @@ _mesa_DisableVertexAttribArray(GLuint index)
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) {
/* was enabled, now being disabled */
FLUSH_VERTICES(ctx, _NEW_ARRAY);
arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE;
arrayObj->_Enabled &= ~VERT_BIT_GENERIC(index);
arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
}
@ -614,16 +709,17 @@ static GLuint
get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
const char *caller)
{
const struct gl_client_array *array;
const struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
const struct gl_vertex_attrib_array *array;
if (index >= ctx->Const.VertexProgram.MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index);
return 0;
}
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)];
array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)];
switch (pname) {
case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
@ -637,7 +733,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
return array->Normalized;
case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB:
return array->BufferObj->Name;
return arrayObj->VertexBinding[array->VertexBinding].BufferObj->Name;
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
if ((_mesa_is_desktop_gl(ctx)
&& (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4))
@ -648,7 +744,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname,
case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB:
if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays)
|| _mesa_is_gles3(ctx)) {
return array->InstanceDivisor;
return arrayObj->VertexBinding[array->VertexBinding].InstanceDivisor;
}
goto error;
default:
@ -806,7 +902,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
*pointer = (GLvoid *) ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
*pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
}
@ -1180,9 +1276,10 @@ _mesa_PrimitiveRestartIndex(GLuint index)
void GLAPIENTRY
_mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
{
struct gl_client_array *array;
GET_CURRENT_CONTEXT(ctx);
const GLuint genericIndex = VERT_ATTRIB_GENERIC(index);
if (!ctx->Extensions.ARB_instanced_arrays) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()");
return;
@ -1194,14 +1291,21 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor)
return;
}
ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
ASSERT(genericIndex < Elements(ctx->Array.ArrayObj->VertexAttrib));
array = &ctx->Array.ArrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(index)];
if (array->InstanceDivisor != divisor) {
FLUSH_VERTICES(ctx, _NEW_ARRAY);
array->InstanceDivisor = divisor;
ctx->Array.ArrayObj->NewArrays |= VERT_BIT(VERT_ATTRIB_GENERIC(index));
}
/* The ARB_vertex_attrib_binding spec says:
*
* "The command
*
* void VertexAttribDivisor(uint index, uint divisor);
*
* is equivalent to (assuming no errors are generated):
*
* VertexAttribBinding(index, index);
* VertexBindingDivisor(index, divisor);"
*/
vertex_attrib_binding(ctx, genericIndex, genericIndex);
vertex_binding_divisor(ctx, genericIndex, divisor);
}
@ -1237,6 +1341,80 @@ void GLAPIENTRY
_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
GLsizei stride)
{
struct gl_buffer_object *vbo;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_OPERATION error is generated if no vertex array object
* is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glBindVertexBuffer(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_VALUE error is generated if <bindingindex> is greater than
* the value of MAX_VERTEX_ATTRIB_BINDINGS."
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glBindVertexBuffer(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
bindingIndex);
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "The error INVALID_VALUE is generated if <stride> or <offset>
* are negative."
*/
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glBindVertexBuffer(offset=%lld < 0)", (long long)offset);
return;
}
if (stride < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glBindVertexBuffer(stride=%d < 0)", stride);
return;
}
if (buffer != 0) {
vbo = _mesa_lookup_bufferobj(ctx, buffer);
/* From the GL_ARB_vertex_attrib_array spec:
*
* "[Core profile only:]
* An INVALID_OPERATION error is generated if buffer is not zero or a
* name returned from a previous call to GenBuffers, or if such a name
* has since been deleted with DeleteBuffers.
*
* Otherwise, we fall back to the same compat profile behavior as other
* object references (automatically gen it).
*/
if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer,
&vbo, "glBindVertexBuffer"))
return;
} else {
/* The ARB_vertex_attrib_binding spec says:
*
* "If <buffer> is zero, any buffer object attached to this
* bindpoint is detached."
*/
vbo = ctx->Shared->NullBufferObj;
}
bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex),
vbo, offset, stride);
}
@ -1244,6 +1422,50 @@ void GLAPIENTRY
_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
GLboolean normalized, GLuint relativeOffset)
{
const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
SHORT_BIT | UNSIGNED_SHORT_BIT |
INT_BIT | UNSIGNED_INT_BIT |
HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
FIXED_GL_BIT |
UNSIGNED_INT_2_10_10_10_REV_BIT |
INT_2_10_10_10_REV_BIT);
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_OPERATION error is generated under any of the following
* conditions:
* - if no vertex array object is currently bound (see section 2.10);
* - ..."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glVertexAttribFormat(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "The error INVALID_VALUE is generated if index is greater than or equal
* to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexAttribFormat(attribindex=%u > "
"GL_MAX_VERTEX_ATTRIBS)",
attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
update_array_format(ctx, "glVertexAttribFormat",
VERT_ATTRIB_GENERIC(attribIndex),
legalTypes, 1, BGRA_OR_4, size, type, normalized,
GL_FALSE, relativeOffset);
}
@ -1251,6 +1473,46 @@ void GLAPIENTRY
_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset)
{
const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT |
SHORT_BIT | UNSIGNED_SHORT_BIT |
INT_BIT | UNSIGNED_INT_BIT);
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_OPERATION error is generated under any of the following
* conditions:
* - if no vertex array object is currently bound (see section 2.10);
* - ..."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glVertexAttribIFormat(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "The error INVALID_VALUE is generated if index is greater than
* or equal to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexAttribIFormat(attribindex=%u > "
"GL_MAX_VERTEX_ATTRIBS)",
attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
update_array_format(ctx, "glVertexAttribIFormat",
VERT_ATTRIB_GENERIC(attribIndex),
legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE,
relativeOffset);
}
@ -1258,18 +1520,136 @@ void GLAPIENTRY
_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
GLuint relativeOffset)
{
const GLbitfield legalTypes = DOUBLE_BIT;
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says:
*
* "An INVALID_OPERATION error is generated under any of the following
* conditions:
* if no vertex array object is currently bound (see section 10.4);
* ..."
*
* This language is missing from the extension spec, but we assume
* that this is an oversight.
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glVertexAttribLFormat(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "The error INVALID_VALUE is generated if <attribindex> is greater than
* or equal to the value of MAX_VERTEX_ATTRIBS."
*/
if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexAttribLFormat(attribindex=%u > "
"GL_MAX_VERTEX_ATTRIBS)",
attribIndex);
return;
}
FLUSH_VERTICES(ctx, 0);
update_array_format(ctx, "glVertexAttribLFormat",
VERT_ATTRIB_GENERIC(attribIndex),
legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE,
relativeOffset);
}
void GLAPIENTRY
_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_OPERATION error is generated if no vertex array object
* is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glVertexAttribBinding(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "<attribindex> must be less than the value of MAX_VERTEX_ATTRIBS and
* <bindingindex> must be less than the value of
* MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE
* is generated."
*/
if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexAttribBinding(attribindex=%u >= "
"GL_MAX_VERTEX_ATTRIBS)",
attribIndex);
return;
}
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexAttribBinding(bindingindex=%u >= "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
bindingIndex);
return;
}
ASSERT(VERT_ATTRIB_GENERIC(attribIndex) <
Elements(ctx->Array.ArrayObj->VertexAttrib));
vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex),
VERT_ATTRIB_GENERIC(bindingIndex));
}
void GLAPIENTRY
_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
{
GET_CURRENT_CONTEXT(ctx);
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!ctx->Extensions.ARB_instanced_arrays) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_OPERATION error is generated if no vertex array object
* is bound."
*/
if (ctx->API == API_OPENGL_CORE &&
ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glVertexBindingDivisor(No array object bound)");
return;
}
/* The ARB_vertex_attrib_binding spec says:
*
* "An INVALID_VALUE error is generated if <bindingindex> is greater
* than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS."
*/
if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glVertexBindingDivisor(bindingindex=%u > "
"GL_MAX_VERTEX_ATTRIB_BINDINGS)",
bindingIndex);
return;
}
vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor);
}
@ -1296,7 +1676,36 @@ _mesa_copy_client_array(struct gl_context *ctx,
dst->_MaxElement = src->_MaxElement;
}
void
_mesa_copy_vertex_attrib_array(struct gl_context *ctx,
struct gl_vertex_attrib_array *dst,
const struct gl_vertex_attrib_array *src)
{
dst->Size = src->Size;
dst->Type = src->Type;
dst->Format = src->Format;
dst->VertexBinding = src->VertexBinding;
dst->RelativeOffset = src->RelativeOffset;
dst->Format = src->Format;
dst->Integer = src->Integer;
dst->Normalized = src->Normalized;
dst->Ptr = src->Ptr;
dst->Enabled = src->Enabled;
dst->_ElementSize = src->_ElementSize;
}
void
_mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
struct gl_vertex_buffer_binding *dst,
const struct gl_vertex_buffer_binding *src)
{
dst->Offset = src->Offset;
dst->Stride = src->Stride;
dst->InstanceDivisor = src->InstanceDivisor;
dst->_BoundArrays = src->_BoundArrays;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj);
}
/**
* Print vertex array's fields.

View file

@ -29,6 +29,7 @@
#include "glheader.h"
#include "bufferobj.h"
struct gl_client_array;
struct gl_context;
@ -64,6 +65,44 @@ _mesa_update_array_max_element(struct gl_client_array *array)
}
/**
* Returns a pointer to the vertex attribute data in a client array,
* or the offset into the vertex buffer for an array that resides in
* a vertex buffer.
*/
static inline const GLubyte *
_mesa_vertex_attrib_address(struct gl_vertex_attrib_array *array,
struct gl_vertex_buffer_binding *binding)
{
return (binding->BufferObj->Name == 0 ?
array->Ptr :
(const GLubyte *)(binding->Offset + array->RelativeOffset));
}
/**
* Sets the fields in a gl_client_array to values derived from a
* gl_vertex_attrib_array and a gl_vertex_buffer_binding.
*/
static inline void
_mesa_update_client_array(struct gl_context *ctx,
struct gl_client_array *dst,
struct gl_vertex_attrib_array *src,
struct gl_vertex_buffer_binding *binding)
{
dst->Size = src->Size;
dst->Type = src->Type;
dst->Format = src->Format;
dst->Stride = src->Stride;
dst->StrideB = binding->Stride;
dst->Ptr = _mesa_vertex_attrib_address(src, binding);
dst->Enabled = src->Enabled;
dst->Normalized = src->Normalized;
dst->Integer = src->Integer;
dst->InstanceDivisor = binding->InstanceDivisor;
dst->_ElementSize = src->_ElementSize;
_mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj);
}
extern void GLAPIENTRY
_mesa_VertexPointer(GLint size, GLenum type, GLsizei stride,
const GLvoid *ptr);
@ -278,6 +317,15 @@ _mesa_copy_client_array(struct gl_context *ctx,
struct gl_client_array *dst,
struct gl_client_array *src);
extern void
_mesa_copy_vertex_attrib_array(struct gl_context *ctx,
struct gl_vertex_attrib_array *dst,
const struct gl_vertex_attrib_array *src);
extern void
_mesa_copy_vertex_buffer_binding(struct gl_context *ctx,
struct gl_vertex_buffer_binding *dst,
const struct gl_vertex_buffer_binding *src);
extern void
_mesa_print_arrays(struct gl_context *ctx);