aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/main
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/main')
-rw-r--r--mesalib/src/mesa/main/api_arrayelt.c43
-rw-r--r--mesalib/src/mesa/main/arrayobj.c73
-rw-r--r--mesalib/src/mesa/main/arrayobj.h5
-rw-r--r--mesalib/src/mesa/main/attrib.c7
-rw-r--r--mesalib/src/mesa/main/bufferobj.c28
-rw-r--r--mesalib/src/mesa/main/bufferobj.h9
-rw-r--r--mesalib/src/mesa/main/context.c6
-rw-r--r--mesalib/src/mesa/main/dd.h9
-rw-r--r--mesalib/src/mesa/main/enable.c2
-rw-r--r--mesalib/src/mesa/main/extensions.c2
-rw-r--r--mesalib/src/mesa/main/get.c30
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py18
-rw-r--r--mesalib/src/mesa/main/getstring.c49
-rw-r--r--mesalib/src/mesa/main/glformats.c5
-rw-r--r--mesalib/src/mesa/main/mtypes.h76
-rw-r--r--mesalib/src/mesa/main/state.c4
-rw-r--r--mesalib/src/mesa/main/streaming-load-memcpy.c85
-rw-r--r--mesalib/src/mesa/main/streaming-load-memcpy.h33
-rw-r--r--mesalib/src/mesa/main/varray.c699
-rw-r--r--mesalib/src/mesa/main/varray.h77
20 files changed, 1098 insertions, 162 deletions
diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c
index ea0923837..6822465e8 100644
--- a/mesalib/src/mesa/main/api_arrayelt.c
+++ b/mesalib/src/mesa/main/api_arrayelt.c
@@ -35,6 +35,7 @@
*/
#include "glheader.h"
+#include "arrayobj.h"
#include "api_arrayelt.h"
#include "bufferobj.h"
#include "context.h"
@@ -1485,46 +1486,52 @@ _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];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX];
aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG];
aa->offset = _gloffset_EdgeFlagv;
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL];
aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0];
aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1];
aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- if (arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_FOG];
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_FOG];
aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
struct gl_client_array *attribArray =
- &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)];
+ &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)];
if (attribArray->Enabled) {
/* NOTE: we use generic glVertexAttribNV functions here.
* If we ever remove GL_NV_vertex_program this will have to change.
@@ -1543,7 +1550,7 @@ _ae_update_state(struct gl_context *ctx)
/* generic vertex attribute arrays */
for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { /* skip zero! */
struct gl_client_array *attribArray =
- &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)];
+ &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)];
if (attribArray->Enabled) {
GLint intOrNorm;
at->array = attribArray;
@@ -1570,18 +1577,18 @@ _ae_update_state(struct gl_context *ctx)
}
/* finally, vertex position */
- if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) {
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) {
/* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's
* issued as the last (provoking) attribute).
*/
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0];
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0];
assert(aa->array->Size >= 2); /* XXX fix someday? */
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
}
- else if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) {
- aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_POS];
+ else if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) {
+ aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_POS];
aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)];
check_vbo(actx, aa->array->BufferObj);
aa++;
diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c
index 5d50d29f8..dbf8fdc73 100644
--- a/mesalib/src/mesa/main/arrayobj.c
+++ b/mesalib/src/mesa/main/arrayobj.c
@@ -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,8 +81,11 @@ unbind_array_object_vbos(struct gl_context *ctx, struct gl_array_object *obj)
{
GLuint i;
- for (i = 0; i < Elements(obj->VertexAttrib); i++)
- _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj, NULL);
+ 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);
}
@@ -215,31 +228,31 @@ _mesa_initialize_array_object( struct gl_context *ctx,
obj->RefCount = 1;
/* Init the individual arrays */
- for (i = 0; i < Elements(obj->VertexAttrib); i++) {
+ 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;
}
}
@@ -279,7 +292,7 @@ remove_array_object( struct gl_context *ctx, struct gl_array_object *obj )
/**
* Helper for _mesa_update_array_object_max_element().
- * \return min(arrayObj->VertexAttrib[*]._MaxElement).
+ * \return min(arrayObj->_VertexAttrib[*]._MaxElement).
*/
static GLuint
compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled)
@@ -291,7 +304,7 @@ compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled)
GLint attrib = ffsll(enabled) - 1;
enabled ^= BITFIELD64_BIT(attrib);
- client_array = &arrayObj->VertexAttrib[attrib];
+ client_array = &arrayObj->_VertexAttrib[attrib];
assert(client_array->Enabled);
_mesa_update_array_max_element(client_array);
min = MIN2(min, client_array->_MaxElement);
@@ -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 */
/**********************************************************************/
diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h
index 492ef3501..7c3720242 100644
--- a/mesalib/src/mesa/main/arrayobj.h
+++ b/mesalib/src/mesa/main/arrayobj.h
@@ -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
diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c
index ca617f744..c9332bd52 100644
--- a/mesalib/src/mesa/main/attrib.c
+++ b/mesalib/src/mesa/main/attrib.c
@@ -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++)
- _mesa_copy_client_array(ctx, &dest->VertexAttrib[i], &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;
diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c
index f8312bbb4..351934433 100644
--- a/mesalib/src/mesa/main/bufferobj.c
+++ b/mesalib/src/mesa/main/bufferobj.c
@@ -655,16 +655,17 @@ _mesa_free_buffer_objects( struct gl_context *ctx )
}
}
-static bool
-handle_bind_buffer_gen(struct gl_context *ctx,
- GLenum target,
- GLuint buffer,
- struct gl_buffer_object **buf_handle)
+bool
+_mesa_handle_bind_buffer_gen(struct gl_context *ctx,
+ GLenum target,
+ GLuint buffer,
+ struct gl_buffer_object **buf_handle,
+ const char *caller)
{
struct gl_buffer_object *buf = *buf_handle;
if (!buf && ctx->API == API_OPENGL_CORE) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "glBindBuffer(non-gen name)");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller);
return false;
}
@@ -675,7 +676,7 @@ handle_bind_buffer_gen(struct gl_context *ctx,
ASSERT(ctx->Driver.NewBufferObject);
buf = ctx->Driver.NewBufferObject(ctx, buffer, target);
if (!buf) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
return false;
}
_mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf);
@@ -719,7 +720,8 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer)
else {
/* non-default buffer object */
newBufObj = _mesa_lookup_bufferobj(ctx, buffer);
- if (!handle_bind_buffer_gen(ctx, target, buffer, &newBufObj))
+ if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
+ &newBufObj, "glBindBuffer"))
return;
}
@@ -862,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) {
@@ -2181,7 +2183,8 @@ _mesa_BindBufferRange(GLenum target, GLuint index,
} else {
bufObj = _mesa_lookup_bufferobj(ctx, buffer);
}
- if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj))
+ if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
+ &bufObj, "glBindBufferRange"))
return;
if (!bufObj) {
@@ -2227,7 +2230,8 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer)
} else {
bufObj = _mesa_lookup_bufferobj(ctx, buffer);
}
- if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj))
+ if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer,
+ &bufObj, "glBindBufferBase"))
return;
if (!bufObj) {
diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h
index 9b582f8c1..0b898a21b 100644
--- a/mesalib/src/mesa/main/bufferobj.h
+++ b/mesalib/src/mesa/main/bufferobj.h
@@ -28,7 +28,7 @@
#ifndef BUFFEROBJ_H
#define BUFFEROBJ_H
-
+#include <stdbool.h>
#include "mtypes.h"
@@ -62,6 +62,13 @@ _mesa_init_buffer_objects( struct gl_context *ctx );
extern void
_mesa_free_buffer_objects( struct gl_context *ctx );
+extern bool
+_mesa_handle_bind_buffer_gen(struct gl_context *ctx,
+ GLenum target,
+ GLuint buffer,
+ struct gl_buffer_object **buf_handle,
+ const char *caller);
+
extern void
_mesa_update_default_objects_buffer_objects(struct gl_context *ctx);
diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c
index 6cdeed19b..d005d2370 100644
--- a/mesalib/src/mesa/main/context.c
+++ b/mesalib/src/mesa/main/context.c
@@ -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;
}
@@ -804,7 +808,7 @@ init_attrib_groups(struct gl_context *ctx)
ctx->NewState = _NEW_ALL;
ctx->NewDriverState = ~0;
ctx->ErrorValue = GL_NO_ERROR;
- ctx->ResetStatus = GL_NO_ERROR;
+ ctx->ShareGroupReset = false;
ctx->varying_vp_inputs = VERT_BIT_ALL;
return GL_TRUE;
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index d7c432713..b5b874f47 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -890,6 +890,15 @@ struct dd_function_table {
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
const GLvoid *vdpSurface, GLuint index);
+
+ /**
+ * Query reset status for GL_ARB_robustness
+ *
+ * Per \c glGetGraphicsResetStatusARB, this function should return a
+ * non-zero value once after a reset. If a reset is non-atomic, the
+ * non-zero status should be returned for the duration of the reset.
+ */
+ GLenum (*GetGraphicsResetStatus)(struct gl_context *ctx);
};
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
index dd6a772f9..c047f5df2 100644
--- a/mesalib/src/mesa/main/enable.c
+++ b/mesalib/src/mesa/main/enable.c
@@ -135,6 +135,8 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state)
else
arrayObj->_Enabled &= ~flag;
+ arrayObj->NewArrays |= flag;
+
if (ctx->Driver.Enable) {
ctx->Driver.Enable( ctx, cap, state );
}
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 48c4e9f1b..104618c23 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -165,9 +165,11 @@ static const struct extension extension_table[] = {
{ "GL_ARB_uniform_buffer_object", o(ARB_uniform_buffer_object), GL, 2009 },
{ "GL_ARB_vertex_array_bgra", o(EXT_vertex_array_bgra), GL, 2008 },
{ "GL_ARB_vertex_array_object", o(dummy_true), GL, 2006 },
+ { "GL_ARB_vertex_attrib_binding", o(dummy_true), GL, 2012 },
{ "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 },
{ "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 },
{ "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 },
+ { "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 },
{ "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 },
{ "GL_ARB_window_pos", o(dummy_true), GLL, 2001 },
/* EXT extensions */
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 6a0de0c16..eee855007 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -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) {
@@ -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:
@@ -1740,6 +1740,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v)
goto invalid_value;
v->value_int64 = ctx->AtomicBufferBindings[index].Size;
return TYPE_INT64;
+
+ case GL_VERTEX_BINDING_DIVISOR:
+ if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_instanced_arrays)
+ goto invalid_enum;
+ if (index >= ctx->Const.VertexProgram.MaxAttribs)
+ goto invalid_value;
+ v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor;
+ return TYPE_INT;
+
+ case GL_VERTEX_BINDING_OFFSET:
+ if (!_mesa_is_desktop_gl(ctx))
+ goto invalid_enum;
+ if (index >= ctx->Const.VertexProgram.MaxAttribs)
+ goto invalid_value;
+ v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset;
+ return TYPE_INT;
+
+ case GL_VERTEX_BINDING_STRIDE:
+ if (!_mesa_is_desktop_gl(ctx))
+ goto invalid_enum;
+ if (index >= ctx->Const.VertexProgram.MaxAttribs)
+ goto invalid_value;
+ v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride;
+ return TYPE_INT;
}
invalid_enum:
diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py
index 0851b7b70..c961feeee 100644
--- a/mesalib/src/mesa/main/get_hash_params.py
+++ b/mesalib/src/mesa/main/get_hash_params.py
@@ -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
@@ -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
@@ -737,6 +737,10 @@ descriptor=[
[ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ],
[ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ],
[ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ],
+
+# GL_ARB_vertex_attrib_binding
+ [ "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "CONTEXT_ENUM(Const.MaxVertexAttribRelativeOffset), NO_EXTRA" ],
+ [ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ],
]},
# Enums restricted to OpenGL Core profile
diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c
index 0e075427f..d8189115a 100644
--- a/mesalib/src/mesa/main/getstring.c
+++ b/mesalib/src/mesa/main/getstring.c
@@ -23,7 +23,7 @@
*/
-
+#include <stdbool.h>
#include "glheader.h"
#include "context.h"
#include "get.h"
@@ -305,11 +305,50 @@ GLenum GLAPIENTRY
_mesa_GetGraphicsResetStatusARB( void )
{
GET_CURRENT_CONTEXT(ctx);
- GLenum status = ctx->ResetStatus;
+ GLenum status = GL_NO_ERROR;
+
+ /* The ARB_robustness specification says:
+ *
+ * "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB,
+ * then the implementation will never deliver notification of reset
+ * events, and GetGraphicsResetStatusARB will always return NO_ERROR."
+ */
+ if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) {
+ if (MESA_VERBOSE & VERBOSE_API)
+ _mesa_debug(ctx,
+ "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
+ "because reset notifictation was not requested at context "
+ "creation.\n");
+
+ return GL_NO_ERROR;
+ }
- if (MESA_VERBOSE & VERBOSE_API)
- _mesa_debug(ctx, "glGetGraphicsResetStatusARB"
- "(always returns GL_NO_ERROR)\n");
+ if (ctx->Driver.GetGraphicsResetStatus) {
+ /* Query the reset status of this context from the driver core.
+ */
+ status = ctx->Driver.GetGraphicsResetStatus(ctx);
+
+ _glthread_LOCK_MUTEX(ctx->Shared->Mutex);
+
+ /* If this context has not been affected by a GPU reset, check to see if
+ * some other context in the share group has been affected by a reset.
+ * If another context saw a reset but this context did not, assume that
+ * this context was not guilty.
+ */
+ if (status != GL_NO_ERROR) {
+ ctx->Shared->ShareGroupReset = true;
+ } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) {
+ status = GL_INNOCENT_CONTEXT_RESET_ARB;
+ }
+
+ ctx->ShareGroupReset = ctx->Shared->ShareGroupReset;
+ _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex);
+ }
+
+ if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API))
+ _mesa_debug(ctx,
+ "glGetGraphicsResetStatusARB always returns GL_NO_ERROR "
+ "because the driver doesn't track reset status.\n");
return status;
}
diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c
index dfee6f196..740faa890 100644
--- a/mesalib/src/mesa/main/glformats.c
+++ b/mesalib/src/mesa/main/glformats.c
@@ -345,6 +345,11 @@ _mesa_bytes_per_vertex_attrib(GLint comps, GLenum type)
return sizeof(GLuint);
else
return -1;
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ if (comps == 3)
+ return sizeof(GLuint);
+ else
+ return -1;
default:
return -1;
}
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index b5c5583d6..ae96e2326 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -35,6 +35,7 @@
#include <stdint.h> /* uint32_t */
+#include <stdbool.h>
#include "main/glheader.h"
#include "main/config.h"
@@ -1474,6 +1475,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,12 +1546,21 @@ struct gl_array_object
*/
GLboolean EverBound;
+ /** Derived vertex attribute arrays */
+ struct gl_client_array _VertexAttrib[VERT_ATTRIB_MAX];
+
/** Vertex attribute arrays */
- struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX];
+ 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;
+ /** Mask of VERT_BIT_* values indicating changed/dirty arrays */
+ GLbitfield64 NewArrays;
+
/**
* Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs
* we can determine the max legal (in bounds) glDrawElements array index.
@@ -2765,6 +2813,17 @@ struct gl_shared_state
/** GL_ARB_sampler_objects */
struct _mesa_HashTable *SamplerObjects;
+
+ /**
+ * Some context in this share group was affected by a GPU reset
+ *
+ * On the next call to \c glGetGraphicsResetStatus, contexts that have not
+ * been affected by a GPU reset must also return
+ * \c GL_INNOCENT_CONTEXT_RESET_ARB.
+ *
+ * Once this field becomes true, it is never reset to false.
+ */
+ bool ShareGroupReset;
};
@@ -3213,6 +3272,10 @@ struct gl_constants
GLuint MaxAtomicBufferSize;
GLuint MaxCombinedAtomicBuffers;
GLuint MaxCombinedAtomicCounters;
+
+ /** GL_ARB_vertex_attrib_binding */
+ GLint MaxVertexAttribRelativeOffset;
+ GLint MaxVertexAttribBindings;
};
@@ -3291,6 +3354,7 @@ struct gl_extensions
GLboolean ARB_uniform_buffer_object;
GLboolean ARB_vertex_program;
GLboolean ARB_vertex_shader;
+ GLboolean ARB_vertex_type_10f_11f_11f_rev;
GLboolean ARB_vertex_type_2_10_10_10_rev;
GLboolean EXT_blend_color;
GLboolean EXT_blend_equation_separate;
@@ -3851,9 +3915,6 @@ struct gl_context
GLenum ErrorValue; /**< Last error code */
- /* GL_ARB_robustness */
- GLenum ResetStatus;
-
/**
* Recognize and silence repeated error debug messages in buggy apps.
*/
@@ -3918,6 +3979,13 @@ struct gl_context
const void *vdpGetProcAddress;
struct set *vdpSurfaces;
/*@}*/
+
+ /**
+ * Has this context observed a GPU reset in any context in the share group?
+ *
+ * Once this field becomes true, it is never reset to false.
+ */
+ GLboolean ShareGroupReset;
};
diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c
index 23926410b..33070b7e0 100644
--- a/mesalib/src/mesa/main/state.c
+++ b/mesalib/src/mesa/main/state.c
@@ -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);
@@ -430,6 +433,7 @@ _mesa_update_state_locked( struct gl_context *ctx )
new_state = ctx->NewState | new_prog_state;
ctx->NewState = 0;
ctx->Driver.UpdateState(ctx, new_state);
+ ctx->Array.ArrayObj->NewArrays = 0x0;
}
diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.c b/mesalib/src/mesa/main/streaming-load-memcpy.c
new file mode 100644
index 000000000..d7147afdc
--- /dev/null
+++ b/mesalib/src/mesa/main/streaming-load-memcpy.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Matt Turner <mattst88@gmail.com>
+ *
+ */
+
+#include "main/macros.h"
+#include "main/streaming-load-memcpy.h"
+#include <smmintrin.h>
+
+/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming
+ * read performance from uncached memory.
+ */
+void
+_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len)
+{
+ char *restrict d = dst;
+ char *restrict s = src;
+
+ /* If dst and src are not co-aligned, fallback to memcpy(). */
+ if (((uintptr_t)d & 15) != ((uintptr_t)s & 15)) {
+ memcpy(d, s, len);
+ return;
+ }
+
+ /* memcpy() the misaligned header. At the end of this if block, <d> and <s>
+ * are aligned to a 16-byte boundary or <len> == 0.
+ */
+ if ((uintptr_t)d & 15) {
+ uintptr_t bytes_before_alignment_boundary = 16 - ((uintptr_t)d & 15);
+ assert(bytes_before_alignment_boundary < 16);
+
+ memcpy(d, s, MIN2(bytes_before_alignment_boundary, len));
+
+ d = (char *)ALIGN((uintptr_t)d, 16);
+ s = (char *)ALIGN((uintptr_t)s, 16);
+ len -= MIN2(bytes_before_alignment_boundary, len);
+ }
+
+ while (len >= 64) {
+ __m128i *dst_cacheline = (__m128i *)d;
+ __m128i *src_cacheline = (__m128i *)s;
+
+ __m128i temp1 = _mm_stream_load_si128(src_cacheline + 0);
+ __m128i temp2 = _mm_stream_load_si128(src_cacheline + 1);
+ __m128i temp3 = _mm_stream_load_si128(src_cacheline + 2);
+ __m128i temp4 = _mm_stream_load_si128(src_cacheline + 3);
+
+ _mm_store_si128(dst_cacheline + 0, temp1);
+ _mm_store_si128(dst_cacheline + 1, temp2);
+ _mm_store_si128(dst_cacheline + 2, temp3);
+ _mm_store_si128(dst_cacheline + 3, temp4);
+
+ d += 64;
+ s += 64;
+ len -= 64;
+ }
+
+ /* memcpy() the tail. */
+ if (len) {
+ memcpy(d, s, len);
+ }
+}
diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.h b/mesalib/src/mesa/main/streaming-load-memcpy.h
new file mode 100644
index 000000000..41eeeeca0
--- /dev/null
+++ b/mesalib/src/mesa/main/streaming-load-memcpy.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors:
+ * Eric Anholt <eric@anholt.net>
+ * Matt Turner <mattst88@gmail.com>
+ *
+ */
+
+/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming
+ * read performance from uncached memory.
+ */
+void
+_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len);
diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c
index dee476abb..d17d698d3 100644
--- a/mesalib/src/mesa/main/varray.c
+++ b/mesalib/src/mesa/main/varray.c
@@ -60,6 +60,7 @@
#define FIXED_GL_BIT 0x800
#define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000
#define INT_2_10_10_10_REV_BIT 0x2000
+#define UNSIGNED_INT_10F_11F_11F_REV_BIT 0x4000
/** Convert GL datatype enum into a <type>_BIT value seen above */
@@ -96,6 +97,8 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
return UNSIGNED_INT_2_10_10_10_REV_BIT;
case GL_INT_2_10_10_10_REV:
return INT_2_10_10_10_REV_BIT;
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ return UNSIGNED_INT_10F_11F_11F_REV_BIT;
default:
return 0;
}
@@ -103,54 +106,110 @@ type_to_bit(const struct gl_context *ctx, GLenum type)
/**
- * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
- * functions.
- *
- * \param func name of calling function used for error reporting
- * \param attrib the attribute array index to update
- * \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 stride stride between elements, in elements
- * \param normalized are integer types converted to floats in [-1, 1]?
- * \param integer integer-valued values (will not be normalized to [-1,1])
- * \param ptr the address (or offset inside VBO) of the array data
+ * Sets the VertexBinding field in the vertex attribute given by attribIndex.
*/
static void
-update_array(struct gl_context *ctx,
- const char *func,
- GLuint attrib, GLbitfield legalTypesMask,
- GLint sizeMin, GLint sizeMax,
- GLint size, GLenum type, GLsizei stride,
- GLboolean normalized, GLboolean integer,
- const GLvoid *ptr)
+vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex,
+ GLuint bindingIndex)
{
- struct gl_client_array *array;
- GLbitfield typeBit;
- GLsizei elementSize;
- GLenum format = GL_RGBA;
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex];
- /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
- *
- * "Client vertex arrays - all vertex array attribute pointers must
- * refer to buffer objects (section 2.9.2). The default vertex array
- * object (the name zero) is also deprecated. Calling
- * VertexAttribPointer when no buffer object or no vertex array object
- * is bound will generate an INVALID_OPERATION error..."
- *
- * The check for VBOs is handled below.
- */
- if (ctx->API == API_OPENGL_CORE
- && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
- func);
- return;
+ 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() 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 relativeOffset Offset of the first element relative to the binding offset.
+ */
+static bool
+update_array_format(struct gl_context *ctx,
+ const char *func,
+ GLuint attrib, GLbitfield legalTypesMask,
+ GLint sizeMin, GLint sizeMax,
+ GLint size, GLenum type,
+ GLboolean normalized, GLboolean integer,
+ GLuint relativeOffset)
+{
+ struct gl_vertex_attrib_array *array;
+ GLbitfield typeBit;
+ GLuint elementSize;
+ GLenum format = GL_RGBA;
if (_mesa_is_gles(ctx)) {
- legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT);
+ legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT | UNSIGNED_INT_10F_11F_11F_REV_BIT);
/* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
* 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or
@@ -180,13 +239,16 @@ update_array(struct gl_context *ctx,
if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
INT_2_10_10_10_REV_BIT);
+
+ if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev)
+ legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT;
}
typeBit = type_to_bit(ctx, type);
if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
_mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
func, _mesa_lookup_enum_by_nr(type));
- return;
+ return false;
}
/* Do size parameter checking.
@@ -206,26 +268,26 @@ update_array(struct gl_context *ctx,
* ...
* • size is BGRA and normalized is FALSE;"
*/
- GLboolean bgra_error = GL_FALSE;
+ bool bgra_error = false;
if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
type != GL_INT_2_10_10_10_REV &&
type != GL_UNSIGNED_BYTE)
- bgra_error = GL_TRUE;
+ bgra_error = true;
} else if (type != GL_UNSIGNED_BYTE)
- bgra_error = GL_TRUE;
+ bgra_error = true;
if (bgra_error) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)",
func, _mesa_lookup_enum_by_nr(type));
- return;
+ return false;
}
if (!normalized) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(size=GL_BGRA and normalized=GL_FALSE)", func);
- return;
+ return false;
}
format = GL_BGRA;
@@ -233,18 +295,106 @@ update_array(struct gl_context *ctx,
}
else if (size < sizeMin || size > sizeMax || size > 4) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
- return;
+ return false;
}
if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
(type == GL_UNSIGNED_INT_2_10_10_10_REV ||
type == GL_INT_2_10_10_10_REV) && size != 4) {
_mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
- return;
+ 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 false;
+ }
+
+ if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev &&
+ type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
+ return false;
}
ASSERT(size <= 4);
+ elementSize = _mesa_bytes_per_vertex_attrib(size, type);
+ assert(elementSize != -1);
+
+ 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;
+}
+
+
+/**
+ * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
+ * functions.
+ *
+ * \param func name of calling function used for error reporting
+ * \param attrib the attribute array index to update
+ * \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 stride stride between elements, in elements
+ * \param normalized are integer types converted to floats in [-1, 1]?
+ * \param integer integer-valued values (will not be normalized to [-1,1])
+ * \param ptr the address (or offset inside VBO) of the array data
+ */
+static void
+update_array(struct gl_context *ctx,
+ const char *func,
+ GLuint attrib, GLbitfield legalTypesMask,
+ GLint sizeMin, GLint sizeMax,
+ GLint size, GLenum type, GLsizei stride,
+ GLboolean normalized, GLboolean integer,
+ const GLvoid *ptr)
+{
+ struct gl_vertex_attrib_array *array;
+ GLsizei effectiveStride;
+
+ /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says:
+ *
+ * "Client vertex arrays - all vertex array attribute pointers must
+ * refer to buffer objects (section 2.9.2). The default vertex array
+ * object (the name zero) is also deprecated. Calling
+ * VertexAttribPointer when no buffer object or no vertex array object
+ * is bound will generate an INVALID_OPERATION error..."
+ *
+ * The check for VBOs is handled below.
+ */
+ if (ctx->API == API_OPENGL_CORE
+ && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)",
+ func);
+ return;
+ }
+
+ if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax,
+ size, type, normalized, integer, 0)) {
+ return;
+ }
+
if (stride < 0) {
_mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
return;
@@ -268,24 +418,18 @@ update_array(struct gl_context *ctx,
return;
}
- elementSize = _mesa_bytes_per_vertex_attrib(size, type);
- assert(elementSize != -1);
+ /* 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->Size = size;
- array->Type = type;
- array->Format = format;
array->Stride = stride;
- array->StrideB = stride ? stride : elementSize;
- array->Normalized = normalized;
- array->Integer = integer;
- array->Ptr = (const GLubyte *) ptr;
- array->_ElementSize = elementSize;
+ array->Ptr = (const GLvoid *) ptr;
- _mesa_reference_buffer_object(ctx, &array->BufferObj,
- ctx->Array.ArrayBufferObj);
-
- ctx->NewState |= _NEW_ARRAY;
+ /* Update the vertex buffer binding */
+ effectiveStride = stride != 0 ? stride : array->_ElementSize;
+ bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj,
+ (GLintptr) ptr, effectiveStride);
}
@@ -473,7 +617,8 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type,
HALF_BIT | FLOAT_BIT | DOUBLE_BIT |
FIXED_ES_BIT | FIXED_GL_BIT |
UNSIGNED_INT_2_10_10_10_REV_BIT |
- INT_2_10_10_10_REV_BIT);
+ INT_2_10_10_10_REV_BIT |
+ UNSIGNED_INT_10F_11F_11F_REV_BIT);
GET_CURRENT_CONTEXT(ctx);
if (index >= ctx->Const.VertexProgram.MaxAttribs) {
@@ -530,13 +675,14 @@ _mesa_EnableVertexAttribArray(GLuint index)
arrayObj = ctx->Array.ArrayObj;
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
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->_Enabled |= VERT_BIT_GENERIC(index);
+ arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
}
}
@@ -555,13 +701,14 @@ _mesa_DisableVertexAttribArray(GLuint index)
arrayObj = ctx->Array.ArrayObj;
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib));
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->_Enabled &= ~VERT_BIT_GENERIC(index);
+ arrayObj->NewArrays |= VERT_BIT_GENERIC(index);
}
}
@@ -575,16 +722,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:
@@ -598,7 +746,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))
@@ -609,7 +757,17 @@ 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;
+ case GL_VERTEX_ATTRIB_BINDING:
+ if (_mesa_is_desktop_gl(ctx)) {
+ return array->VertexBinding - VERT_ATTRIB_GENERIC0;
+ }
+ goto error;
+ case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ if (_mesa_is_desktop_gl(ctx)) {
+ return array->RelativeOffset;
}
goto error;
default:
@@ -643,7 +801,7 @@ get_current_attrib(struct gl_context *ctx, GLuint index, const char *function)
return NULL;
}
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
FLUSH_CURRENT(ctx, 0);
return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)];
@@ -765,7 +923,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer)
return;
}
- ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib));
+ ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib));
*pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr;
}
@@ -1141,9 +1299,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;
@@ -1155,13 +1314,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;
- }
+ /* 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);
}
@@ -1191,6 +1358,329 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type)
/**
+ * GL_ARB_vertex_attrib_binding
+ */
+void GLAPIENTRY
+_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ const struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ struct gl_buffer_object *vbo;
+
+ 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 == arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) {
+ vbo = arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj;
+ } else 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);
+}
+
+
+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 |
+ UNSIGNED_INT_10F_11F_11F_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);
+}
+
+
+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);
+}
+
+
+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);
+}
+
+
+/**
* Copy one client vertex array to another.
*/
void
@@ -1213,7 +1703,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.
@@ -1245,18 +1764,18 @@ _mesa_print_arrays(struct gl_context *ctx)
_mesa_update_array_object_max_element(ctx, arrayObj);
printf("Array Object %u\n", arrayObj->Name);
- if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled)
- print_array("Vertex", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]);
- if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
- print_array("Normal", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]);
- if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
- print_array("Color", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]);
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled)
+ print_array("Vertex", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]);
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled)
+ print_array("Normal", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]);
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled)
+ print_array("Color", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]);
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++)
- if (arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
- print_array("TexCoord", i, &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]);
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled)
+ print_array("TexCoord", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]);
for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++)
- if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
- print_array("Attrib", i, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
+ if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled)
+ print_array("Attrib", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]);
printf(" _MaxElement = %u\n", arrayObj->_MaxElement);
}
diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h
index 7e611e8c7..8a9487c6e 100644
--- a/mesalib/src/mesa/main/varray.h
+++ b/mesalib/src/mesa/main/varray.h
@@ -29,6 +29,7 @@
#include "glheader.h"
+#include "bufferobj.h"
struct gl_client_array;
struct gl_context;
@@ -50,8 +51,10 @@ _mesa_update_array_max_element(struct gl_client_array *array)
GLsizeiptrARB bufSize = (GLsizeiptrARB) array->BufferObj->Size;
if (offset < bufSize) {
- array->_MaxElement = (bufSize - offset + array->StrideB
- - array->_ElementSize) / array->StrideB;
+ const GLuint stride = array->StrideB ?
+ array->StrideB : array->_ElementSize;
+ array->_MaxElement = (bufSize - offset + stride
+ - array->_ElementSize) / stride;
}
else {
array->_MaxElement = 0;
@@ -64,6 +67,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);
@@ -250,11 +291,43 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor);
extern unsigned
_mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type);
+extern void GLAPIENTRY
+_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset,
+ GLsizei stride);
+
+extern void GLAPIENTRY
+_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLboolean normalized, GLuint relativeOffset);
+
+extern void GLAPIENTRY
+_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
+_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type,
+ GLuint relativeOffset);
+
+extern void GLAPIENTRY
+_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex);
+
+extern void GLAPIENTRY
+_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor);
+
+
extern void
_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);