summaryrefslogtreecommitdiff
path: root/src/mesa/vbo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r--src/mesa/vbo/vbo_attrib_tmp.h16
-rw-r--r--src/mesa/vbo/vbo_context.c11
-rw-r--r--src/mesa/vbo/vbo_context.h18
-rw-r--r--src/mesa/vbo/vbo_exec.h10
-rw-r--r--src/mesa/vbo/vbo_exec_api.c40
-rw-r--r--src/mesa/vbo/vbo_exec_array.c405
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c81
-rw-r--r--src/mesa/vbo/vbo_rebase.c2
-rw-r--r--src/mesa/vbo/vbo_save.h7
-rw-r--r--src/mesa/vbo/vbo_save_api.c25
-rw-r--r--src/mesa/vbo/vbo_save_draw.c31
-rw-r--r--src/mesa/vbo/vbo_split_copy.c177
-rw-r--r--src/mesa/vbo/vbo_split_inplace.c2
13 files changed, 613 insertions, 212 deletions
diff --git a/src/mesa/vbo/vbo_attrib_tmp.h b/src/mesa/vbo/vbo_attrib_tmp.h
index ff11c7d59a..7a889b8e2f 100644
--- a/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/src/mesa/vbo/vbo_attrib_tmp.h
@@ -265,7 +265,7 @@ static void GLAPIENTRY TAG(VertexAttrib1fARB)( GLuint index, GLfloat x )
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR1F(0, x);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
else
ERROR();
@@ -277,7 +277,7 @@ static void GLAPIENTRY TAG(VertexAttrib1fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR1FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -289,7 +289,7 @@ static void GLAPIENTRY TAG(VertexAttrib2fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR2F(0, x, y);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
else
ERROR();
@@ -301,7 +301,7 @@ static void GLAPIENTRY TAG(VertexAttrib2fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR2FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -313,7 +313,7 @@ static void GLAPIENTRY TAG(VertexAttrib3fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR3F(0, x, y, z);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
else
ERROR();
@@ -325,7 +325,7 @@ static void GLAPIENTRY TAG(VertexAttrib3fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR3FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
@@ -338,7 +338,7 @@ static void GLAPIENTRY TAG(VertexAttrib4fARB)( GLuint index, GLfloat x,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR4F(0, x, y, z, w);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
else
ERROR();
@@ -350,7 +350,7 @@ static void GLAPIENTRY TAG(VertexAttrib4fvARB)( GLuint index,
GET_CURRENT_CONTEXT( ctx );
if (index == 0)
ATTR4FV(0, v);
- else if (index < MAX_VERTEX_ATTRIBS)
+ else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index ca8190fd05..90025f62fc 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -28,6 +28,7 @@
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/api_arrayelt.h"
+#include "main/bufferobj.h"
#include "math/m_eval.h"
#include "vbo.h"
#include "vbo_context.h"
@@ -81,7 +82,8 @@ static void init_legacy_currval(GLcontext *ctx)
cl->Type = GL_FLOAT;
cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[i];
- cl->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
}
}
@@ -106,7 +108,8 @@ static void init_generic_currval(GLcontext *ctx)
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
- cl->BufferObj = ctx->Array.NullBufferObj;
+ _mesa_reference_buffer_object(ctx, &cl->BufferObj,
+ ctx->Shared->NullBufferObj);
}
}
@@ -150,7 +153,7 @@ static void init_mat_currval(GLcontext *ctx)
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
- cl->BufferObj = ctx->Array.NullBufferObj;
+ cl->BufferObj = ctx->Shared->NullBufferObj;
}
}
@@ -211,7 +214,7 @@ GLboolean _vbo_CreateContext( GLcontext *ctx )
for (i = 0; i < 4; i++)
vbo->map_vp_none[28+i] = i;
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ for (i = 0; i < Elements(vbo->map_vp_arb); i++)
vbo->map_vp_arb[i] = i;
}
diff --git a/src/mesa/vbo/vbo_context.h b/src/mesa/vbo/vbo_context.h
index bf405eb693..8b726dc8ac 100644
--- a/src/mesa/vbo/vbo_context.h
+++ b/src/mesa/vbo/vbo_context.h
@@ -68,8 +68,8 @@ struct vbo_context {
struct gl_client_array *generic_currval;
struct gl_client_array *mat_currval;
- GLuint map_vp_none[32];
- GLuint map_vp_arb[32];
+ GLuint map_vp_none[VERT_ATTRIB_MAX];
+ GLuint map_vp_arb[VERT_ATTRIB_MAX];
GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
GLfloat CurrentFloatEdgeFlag;
@@ -92,16 +92,18 @@ static INLINE struct vbo_context *vbo_context(GLcontext *ctx)
return (struct vbo_context *)(ctx->swtnl_im);
}
-enum {
- VP_NONE = 1,
- VP_NV,
- VP_ARB
-};
-static INLINE GLuint get_program_mode( GLcontext *ctx )
+/**
+ * Return VP_x token to indicate whether we're running fixed-function
+ * vertex transformation, an NV vertex program or ARB vertex program/shader.
+ */
+static INLINE enum vp_mode
+get_program_mode( GLcontext *ctx )
{
if (!ctx->VertexProgram._Current)
return VP_NONE;
+ else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
+ return VP_NONE;
else if (ctx->VertexProgram._Current->IsNVProgram)
return VP_NV;
else
diff --git a/src/mesa/vbo/vbo_exec.h b/src/mesa/vbo/vbo_exec.h
index 100bb8a5de..e0f44892cf 100644
--- a/src/mesa/vbo/vbo_exec.h
+++ b/src/mesa/vbo/vbo_exec.h
@@ -48,6 +48,12 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_ATTRIB 16
+/** Current vertex program mode */
+enum vp_mode {
+ VP_NONE, /**< fixed function */
+ VP_NV, /**< NV vertex program */
+ VP_ARB /**< ARB vertex program or GLSL vertex shader */
+};
struct vbo_exec_eval1_map {
@@ -103,7 +109,7 @@ struct vbo_exec_context
* values are squashed down to the 32 attributes passed to the
* vertex program below:
*/
- GLuint program_mode;
+ enum vp_mode program_mode;
GLuint enabled_flags;
const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
} vtx;
@@ -116,7 +122,7 @@ struct vbo_exec_context
} eval;
struct {
- GLuint program_mode;
+ enum vp_mode program_mode;
GLuint enabled_flags;
GLuint array_obj;
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index 5d35ec9c11..b746a77bc1 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -51,6 +51,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#endif
+/** ID/name for immediate-mode VBO */
+#define IMM_BUFFER_NAME 0xaabbccdd
+
+
static void reset_attrfv( struct vbo_exec_context *exec );
@@ -665,13 +669,13 @@ void vbo_use_buffer_objects(GLcontext *ctx)
/* Any buffer name but 0 can be used here since this bufferobj won't
* go into the bufferobj hashtable.
*/
- GLuint bufName = 0xaabbccdd;
+ GLuint bufName = IMM_BUFFER_NAME;
GLenum target = GL_ARRAY_BUFFER_ARB;
GLenum usage = GL_STREAM_DRAW_ARB;
GLsizei size = VBO_VERT_BUFFER_SIZE;
/* Make sure this func is only used once */
- assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj);
+ assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
if (exec->vtx.buffer_map) {
_mesa_align_free(exec->vtx.buffer_map);
exec->vtx.buffer_map = NULL;
@@ -697,7 +701,7 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
*/
_mesa_reference_buffer_object(ctx,
&exec->vtx.bufferobj,
- ctx->Array.NullBufferObj);
+ ctx->Shared->NullBufferObj);
ASSERT(!exec->vtx.buffer_map);
exec->vtx.buffer_map = (GLfloat *)ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE, 64);
@@ -727,19 +731,33 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
{
- if (exec->vtx.bufferobj->Name) {
- /* using a real VBO for vertex data */
- GLcontext *ctx = exec->ctx;
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
- }
- else {
- /* just using malloc'd space for vertex data */
- if (exec->vtx.buffer_map) {
+ /* using a real VBO for vertex data */
+ GLcontext *ctx = exec->ctx;
+ unsigned i;
+
+ /* True VBOs should already be unmapped
+ */
+ if (exec->vtx.buffer_map) {
+ ASSERT(exec->vtx.bufferobj->Name == 0 ||
+ exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
+ if (exec->vtx.bufferobj->Name == 0) {
ALIGN_FREE(exec->vtx.buffer_map);
exec->vtx.buffer_map = NULL;
exec->vtx.buffer_ptr = NULL;
}
}
+
+ /* Drop any outstanding reference to the vertex buffer
+ */
+ for (i = 0; i < Elements(exec->vtx.arrays); i++) {
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.arrays[i].BufferObj,
+ NULL);
+ }
+
+ /* Free the vertex buffer:
+ */
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
}
void vbo_exec_BeginVertices( GLcontext *ctx )
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 0d4cbe9a1e..f4b9b2f744 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -36,12 +37,13 @@
#include "vbo_context.h"
-/* Compute min and max elements for drawelements calls.
+
+/**
+ * Compute min and max elements for glDraw[Range]Elements() calls.
*/
-static void get_minmax_index( GLuint count, GLuint type,
- const GLvoid *indices,
- GLuint *min_index,
- GLuint *max_index)
+static void
+get_minmax_index(GLuint count, GLuint type, const GLvoid *indices,
+ GLuint *min_index, GLuint *max_index)
{
GLuint i;
@@ -89,9 +91,199 @@ static void get_minmax_index( GLuint count, GLuint type,
}
-/* Just translate the arrayobj into a sane layout.
+/**
+ * Check that element 'j' of the array has reasonable data.
+ * Map VBO if needed.
+ */
+static void
+check_array_data(GLcontext *ctx, struct gl_client_array *array,
+ GLuint attrib, GLuint j)
+{
+ if (array->Enabled) {
+ const void *data = array->Ptr;
+ if (array->BufferObj->Name) {
+ if (!array->BufferObj->Pointer) {
+ /* need to map now */
+ array->BufferObj->Pointer = ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ array->BufferObj);
+ }
+ data = ADD_POINTERS(data, array->BufferObj->Pointer);
+ }
+ switch (array->Type) {
+ case GL_FLOAT:
+ {
+ GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
+ GLuint k;
+ for (k = 0; k < array->Size; k++) {
+ if (IS_INF_OR_NAN(f[k]) ||
+ f[k] >= 1.0e20 || f[k] <= -1.0e10) {
+ _mesa_printf("Bad array data:\n");
+ _mesa_printf(" Element[%u].%u = %f\n", j, k, f[k]);
+ _mesa_printf(" Array %u at %p\n", attrib, (void* ) array);
+ _mesa_printf(" Type 0x%x, Size %d, Stride %d\n",
+ array->Type, array->Size, array->Stride);
+ _mesa_printf(" Address/offset %p in Buffer Object %u\n",
+ array->Ptr, array->BufferObj->Name);
+ f[k] = 1.0; /* XXX replace the bad value! */
+ }
+ //assert(!IS_INF_OR_NAN(f[k]));
+ }
+ }
+ break;
+ default:
+ ;
+ }
+ }
+}
+
+
+/**
+ * Unmap the buffer object referenced by given array, if mapped.
+ */
+static void
+unmap_array_buffer(GLcontext *ctx, struct gl_client_array *array)
+{
+ if (array->Enabled &&
+ array->BufferObj->Name &&
+ array->BufferObj->Pointer) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ARRAY_BUFFER_ARB,
+ array->BufferObj);
+ }
+}
+
+
+/**
+ * Examine the array's data for NaNs, etc.
*/
-static void bind_array_obj( GLcontext *ctx )
+static void
+check_draw_elements_data(GLcontext *ctx, GLsizei count, GLenum elemType,
+ const void *elements)
+{
+ struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
+ const void *elemMap;
+ GLint i, k;
+
+ if (ctx->Array.ElementArrayBufferObj->Name) {
+ elemMap = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ elements = ADD_POINTERS(elements, elemMap);
+ }
+
+ for (i = 0; i < count; i++) {
+ GLuint j;
+
+ /* j = element[i] */
+ switch (elemType) {
+ case GL_UNSIGNED_BYTE:
+ j = ((const GLubyte *) elements)[i];
+ break;
+ case GL_UNSIGNED_SHORT:
+ j = ((const GLushort *) elements)[i];
+ break;
+ case GL_UNSIGNED_INT:
+ j = ((const GLuint *) elements)[i];
+ break;
+ default:
+ assert(0);
+ }
+
+ /* check element j of each enabled array */
+ check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
+ check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
+ check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
+ check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ check_array_data(ctx, &arrayObj->VertexAttrib[k], VERT_ATTRIB_GENERIC0 + k, j);
+ }
+ }
+
+ if (ctx->Array.ElementArrayBufferObj->Name) {
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+ }
+
+ unmap_array_buffer(ctx, &arrayObj->Vertex);
+ unmap_array_buffer(ctx, &arrayObj->Normal);
+ unmap_array_buffer(ctx, &arrayObj->Color);
+ for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
+ unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
+ }
+ for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
+ unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
+ }
+}
+
+
+/**
+ * Check array data, looking for NaNs, etc.
+ */
+static void
+check_draw_arrays_data(GLcontext *ctx, GLint start, GLsizei count)
+{
+ /* TO DO */
+}
+
+
+/**
+ * Print info/data for glDrawArrays().
+ */
+static void
+print_draw_arrays(GLcontext *ctx, struct vbo_exec_context *exec,
+ GLenum mode, GLint start, GLsizei count)
+{
+ int i;
+
+ _mesa_printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
+ mode, start, count);
+
+ for (i = 0; i < 32; i++) {
+ GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
+ GLint stride = exec->array.inputs[i]->Stride;
+ _mesa_printf("attr %2d: size %d stride %d enabled %d "
+ "ptr %p Bufobj %u\n",
+ i,
+ exec->array.inputs[i]->Size,
+ stride,
+ /*exec->array.inputs[i]->Enabled,*/
+ exec->array.legacy_array[i]->Enabled,
+ exec->array.inputs[i]->Ptr,
+ bufName);
+
+ if (bufName) {
+ struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
+ GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY_ARB, buf);
+ int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
+ float *f = (float *) (p + offset);
+ int *k = (int *) f;
+ int i;
+ int n = (count * stride) / 4;
+ if (n > 32)
+ n = 32;
+ _mesa_printf(" Data at offset %d:\n", offset);
+ for (i = 0; i < n; i++) {
+ _mesa_printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
+ }
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
+ }
+ }
+}
+
+
+/**
+ * Just translate the arrayobj into a sane layout.
+ */
+static void
+bind_array_obj(GLcontext *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
@@ -103,7 +295,7 @@ static void bind_array_obj( GLcontext *ctx )
* go away.
*/
exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
- exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &vbo->legacy_currval[VERT_ATTRIB_WEIGHT];
+ exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
@@ -115,16 +307,20 @@ static void bind_array_obj( GLcontext *ctx )
}
exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
- for (i = 0; i < 8; i++)
+ for (i = 0; i < Elements(arrayObj->TexCoord); i++)
exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
- for (i = 0; i < VERT_ATTRIB_MAX; i++)
+ for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
+ assert(i < Elements(exec->array.generic_array));
exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
+ }
exec->array.array_obj = arrayObj->Name;
}
-static void recalculate_input_bindings( GLcontext *ctx )
+
+static void
+recalculate_input_bindings(GLcontext *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
@@ -137,9 +333,10 @@ static void recalculate_input_bindings( GLcontext *ctx )
switch (exec->array.program_mode) {
case VP_NONE:
- /* When no vertex program is active, we put the material values
- * into the generic slots. This is the only situation where
- * material values are available as per-vertex attributes.
+ /* When no vertex program is active (or the vertex program is generated
+ * from fixed-function state). We put the material values into the
+ * generic slots. This is the only situation where material values
+ * are available as per-vertex attributes.
*/
for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
@@ -162,8 +359,8 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
-
break;
+
case VP_NV:
/* NV_vertex_program - attribute arrays alias and override
* conventional, legacy arrays. No materials, and the generic
@@ -187,11 +384,11 @@ static void recalculate_input_bindings( GLcontext *ctx )
inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
const_inputs |= 1 << i;
}
-
break;
+
case VP_ARB:
- /* ARB_vertex_program - Only the attribute zero (position) array
- * aliases and overrides the legacy position array.
+ /* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
+ * attribute array aliases and overrides the legacy position array.
*
* Otherwise, legacy attributes available in the legacy slots,
* generic attributes in the generic slots and materials are not
@@ -206,7 +403,6 @@ static void recalculate_input_bindings( GLcontext *ctx )
const_inputs |= 1 << 0;
}
-
for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
@@ -216,7 +412,7 @@ static void recalculate_input_bindings( GLcontext *ctx )
}
}
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
if (exec->array.generic_array[i]->Enabled)
inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
else {
@@ -231,7 +427,9 @@ static void recalculate_input_bindings( GLcontext *ctx )
_mesa_set_varying_vp_inputs( ctx, ~const_inputs );
}
-static void bind_arrays( GLcontext *ctx )
+
+static void
+bind_arrays(GLcontext *ctx)
{
#if 0
if (ctx->Array.ArrayObj.Name != exec->array.array_obj) {
@@ -276,9 +474,18 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
return;
}
+#if 0
+ check_draw_arrays_data(ctx, start, count);
+#else
+ (void) check_draw_arrays_data;
+#endif
+
bind_arrays( ctx );
- /* Again...
+ /* Again... because we may have changed the bitmask of per-vertex varying
+ * attributes. If we regenerate the fixed-function vertex program now
+ * we may be able to prune down the number of vertex attributes which we
+ * need in the shader.
*/
if (ctx->NewState)
_mesa_update_state( ctx );
@@ -292,50 +499,72 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
prim[0].count = count;
prim[0].indexed = 0;
- vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 );
+ vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL,
+ start, start + count - 1 );
#if 0
- {
- int i;
-
- _mesa_printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
- mode, start, count);
-
- for (i = 0; i < 32; i++) {
- GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
- GLint stride = exec->array.inputs[i]->Stride;
- _mesa_printf("attr %2d: size %d stride %d enabled %d "
- "ptr %p Bufobj %u\n",
- i,
- exec->array.inputs[i]->Size,
- stride,
- /*exec->array.inputs[i]->Enabled,*/
- exec->array.legacy_array[i]->Enabled,
- exec->array.inputs[i]->Ptr,
- bufName);
-
- if (bufName) {
- struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
- GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
- GL_READ_ONLY_ARB, buf);
- int offset = (int) exec->array.inputs[i]->Ptr;
- float *f = (float *) (p + offset);
- int *k = (int *) f;
- int i;
- int n = (count * stride) / 4;
- if (n > 32)
- n = 32;
- _mesa_printf(" Data at offset %d:\n", offset);
- for (i = 0; i < n; i++) {
- _mesa_printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
- }
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
+ print_draw_arrays(ctx, exec, mode, start, count);
+#else
+ (void) print_draw_arrays;
+#endif
+}
+
+
+/**
+ * Map GL_ELEMENT_ARRAY_BUFFER and print contents.
+ */
+static void
+dump_element_buffer(GLcontext *ctx, GLenum type)
+{
+ const GLvoid *map = ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ const GLubyte *us = (const GLubyte *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
+ _mesa_printf("%02x ", us[i]);
+ if (i % 32 == 31)
+ _mesa_printf("\n");
}
+ _mesa_printf("\n");
}
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ const GLushort *us = (const GLushort *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
+ _mesa_printf("%04x ", us[i]);
+ if (i % 16 == 15)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ const GLuint *us = (const GLuint *) map;
+ GLuint i;
+ for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
+ _mesa_printf("%08x ", us[i]);
+ if (i % 8 == 7)
+ _mesa_printf("\n");
+ }
+ _mesa_printf("\n");
+ }
+ break;
+ default:
+ ;
}
-#endif
-}
+ ctx->Driver.UnmapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ ctx->Array.ElementArrayBufferObj);
+}
static void GLAPIENTRY
@@ -349,9 +578,41 @@ vbo_exec_DrawRangeElements(GLenum mode,
struct _mesa_index_buffer ib;
struct _mesa_prim prim[1];
- if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices ))
+ if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
+ type, indices ))
return;
+ if (end >= ctx->Array.ArrayObj->_MaxElement) {
+ /* the max element is out of bounds of one or more enabled arrays */
+ _mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
+ "type 0x%x, indices=%p)\n"
+ "\tindex=%u is out of bounds (max=%u) "
+ "Element Buffer %u (size %d)",
+ start, end, count, type, indices, end,
+ ctx->Array.ArrayObj->_MaxElement - 1,
+ ctx->Array.ElementArrayBufferObj->Name,
+ ctx->Array.ElementArrayBufferObj->Size);
+
+ if (0)
+ dump_element_buffer(ctx, type);
+
+ if (0)
+ _mesa_print_arrays(ctx);
+ return;
+ }
+ else if (0) {
+ _mesa_printf("glDraw[Range]Elements"
+ "(start %u, end %u, type 0x%x, count %d) ElemBuf %u\n",
+ start, end, type, count,
+ ctx->Array.ElementArrayBufferObj->Name);
+ }
+
+#if 0
+ check_draw_elements_data(ctx, count, type, indices);
+#else
+ (void) check_draw_elements_data;
+#endif
+
FLUSH_CURRENT( ctx, 0 );
if (ctx->NewState)
@@ -415,8 +676,10 @@ vbo_exec_DrawRangeElements(GLenum mode,
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end );
}
+
static void GLAPIENTRY
-vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices)
+vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
GLuint min_index = 0;
@@ -432,11 +695,12 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind
if (ctx->Array.ElementArrayBufferObj->Name) {
const GLvoid *map = ctx->Driver.MapBuffer(ctx,
- GL_ELEMENT_ARRAY_BUFFER_ARB,
- GL_READ_ONLY,
- ctx->Array.ElementArrayBufferObj);
+ GL_ELEMENT_ARRAY_BUFFER_ARB,
+ GL_READ_ONLY,
+ ctx->Array.ElementArrayBufferObj);
- get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index);
+ get_minmax_index(count, type, ADD_POINTERS(map, indices),
+ &min_index, &max_index);
ctx->Driver.UnmapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
@@ -454,10 +718,8 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind
* Initialization
*/
-
-
-
-void vbo_exec_array_init( struct vbo_exec_context *exec )
+void
+vbo_exec_array_init( struct vbo_exec_context *exec )
{
#if 1
exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
@@ -471,7 +733,8 @@ void vbo_exec_array_init( struct vbo_exec_context *exec )
}
-void vbo_exec_array_destroy( struct vbo_exec_context *exec )
+void
+vbo_exec_array_destroy( struct vbo_exec_context *exec )
{
/* nothing to do */
}
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 5381cc4d92..c939b7b633 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -35,7 +35,8 @@
#include "vbo_context.h"
-static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
+static void
+vbo_exec_debug_verts( struct vbo_exec_context *exec )
{
GLuint count = exec->vtx.vert_count;
GLuint i;
@@ -64,19 +65,19 @@ static void vbo_exec_debug_verts( struct vbo_exec_context *exec )
* NOTE: Need to have calculated primitives by this point -- do it on the fly.
* NOTE: Old 'parity' issue is gone.
*/
-static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
+static GLuint
+vbo_copy_vertices( struct vbo_exec_context *exec )
{
GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
GLuint ovf, i;
GLuint sz = exec->vtx.vertex_size;
GLfloat *dst = exec->vtx.copied.buffer;
- GLfloat *src = (exec->vtx.buffer_map +
- exec->vtx.prim[exec->vtx.prim_count-1].start *
- exec->vtx.vertex_size);
+ const GLfloat *src = (exec->vtx.buffer_map +
+ exec->vtx.prim[exec->vtx.prim_count-1].start *
+ exec->vtx.vertex_size);
- switch( exec->ctx->Driver.CurrentExecPrimitive )
- {
+ switch (exec->ctx->Driver.CurrentExecPrimitive) {
case GL_POINTS:
return 0;
case GL_LINES:
@@ -95,8 +96,9 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
_mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case GL_LINE_STRIP:
- if (nr == 0)
+ if (nr == 0) {
return 0;
+ }
else {
_mesa_memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 1;
@@ -104,12 +106,14 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
- if (nr == 0)
+ if (nr == 0) {
return 0;
+ }
else if (nr == 1) {
_mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
return 1;
- } else {
+ }
+ else {
_mesa_memcpy( dst, src+0, sz * sizeof(GLfloat) );
_mesa_memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 2;
@@ -122,9 +126,15 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
/* fallthrough */
case GL_QUAD_STRIP:
switch (nr) {
- case 0: ovf = 0; break;
- case 1: ovf = 1; break;
- default: ovf = 2 + (nr&1); break;
+ case 0:
+ ovf = 0;
+ break;
+ case 1:
+ ovf = 1;
+ break;
+ default:
+ ovf = 2 + (nr & 1);
+ break;
}
for (i = 0 ; i < ovf ; i++)
_mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
@@ -141,13 +151,14 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
/* TODO: populate these as the vertex is defined:
*/
-static void vbo_exec_bind_arrays( GLcontext *ctx )
+static void
+vbo_exec_bind_arrays( GLcontext *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct gl_client_array *arrays = exec->vtx.arrays;
- GLuint count = exec->vtx.vert_count;
- GLubyte *data = (GLubyte *)exec->vtx.buffer_map;
+ const GLuint count = exec->vtx.vert_count;
+ const GLubyte *data = (GLubyte *) exec->vtx.buffer_map;
const GLuint *map;
GLuint attr;
GLbitfield varying_inputs = 0x0;
@@ -185,6 +196,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
(ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
exec->vtx.inputs[16] = exec->vtx.inputs[0];
exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
+ exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
exec->vtx.attrsz[0] = 0;
}
break;
@@ -226,7 +238,7 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
arrays[attr]._MaxElement = count; /* ??? */
data += exec->vtx.attrsz[src] * sizeof(GLfloat);
- varying_inputs |= 1<<attr;
+ varying_inputs |= 1 << attr;
}
}
@@ -234,18 +246,19 @@ static void vbo_exec_bind_arrays( GLcontext *ctx )
}
-static void vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
+static void
+vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
{
GLenum target = GL_ARRAY_BUFFER_ARB;
if (exec->vtx.bufferobj->Name) {
GLcontext *ctx = exec->ctx;
- if(ctx->Driver.FlushMappedBufferRange) {
+ if (ctx->Driver.FlushMappedBufferRange) {
GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
- if(length)
+ if (length)
ctx->Driver.FlushMappedBufferRange(ctx, target,
offset, length,
exec->vtx.bufferobj);
@@ -264,7 +277,9 @@ static void vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
}
}
-void vbo_exec_vtx_map( struct vbo_exec_context *exec )
+
+void
+vbo_exec_vtx_map( struct vbo_exec_context *exec )
{
GLcontext *ctx = exec->ctx;
GLenum target = GL_ARRAY_BUFFER_ARB;
@@ -281,8 +296,7 @@ void vbo_exec_vtx_map( struct vbo_exec_context *exec )
}
if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
- ctx->Driver.MapBufferRange)
- {
+ ctx->Driver.MapBufferRange) {
exec->vtx.buffer_map =
(GLfloat *)ctx->Driver.MapBufferRange(ctx,
target,
@@ -304,12 +318,13 @@ void vbo_exec_vtx_map( struct vbo_exec_context *exec )
VBO_VERT_BUFFER_SIZE,
NULL, usage, exec->vtx.bufferobj);
- exec->vtx.buffer_map =
- (GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+ exec->vtx.buffer_map = (GLfloat *)
+ ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
}
- if (0) _mesa_printf("map %d..\n", exec->vtx.buffer_used);
+ if (0)
+ _mesa_printf("map %d..\n", exec->vtx.buffer_used);
}
@@ -317,13 +332,12 @@ void vbo_exec_vtx_map( struct vbo_exec_context *exec )
/**
* Execute the buffer and save copied verts.
*/
-void vbo_exec_vtx_flush( struct vbo_exec_context *exec,
- GLboolean unmap )
+void
+vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
{
if (0)
vbo_exec_debug_verts( exec );
-
if (exec->vtx.prim_count &&
exec->vtx.vert_count) {
@@ -344,8 +358,9 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec,
vbo_exec_vtx_unmap( exec );
}
- if (0) _mesa_printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
- exec->vtx.vert_count);
+ if (0)
+ _mesa_printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
+ exec->vtx.vert_count);
vbo_context(ctx)->draw_prims( ctx,
exec->vtx.inputs,
@@ -359,7 +374,7 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec,
*/
if (exec->vtx.bufferobj->Name && !unmap) {
vbo_exec_vtx_map( exec );
- }
+ }
}
}
@@ -371,14 +386,12 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec,
vbo_exec_vtx_unmap( exec );
}
-
if (unmap)
exec->vtx.max_vert = 0;
else
exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
(exec->vtx.vertex_size * sizeof(GLfloat)));
-
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
exec->vtx.prim_count = 0;
exec->vtx.vert_count = 0;
diff --git a/src/mesa/vbo/vbo_rebase.c b/src/mesa/vbo/vbo_rebase.c
index dae778e741..ea87dede64 100644
--- a/src/mesa/vbo/vbo_rebase.c
+++ b/src/mesa/vbo/vbo_rebase.c
@@ -161,7 +161,7 @@ void vbo_rebase_prims( GLcontext *ctx,
GL_ELEMENT_ARRAY_BUFFER,
ib->obj);
- tmp_ib.obj = ctx->Array.NullBufferObj;
+ tmp_ib.obj = ctx->Shared->NullBufferObj;
tmp_ib.ptr = tmp_indices;
tmp_ib.count = ib->count;
tmp_ib.type = ib->type;
diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h
index 9558f83883..86bbd24f7b 100644
--- a/src/mesa/vbo/vbo_save.h
+++ b/src/mesa/vbo/vbo_save.h
@@ -64,6 +64,13 @@ struct vbo_save_vertex_list {
GLubyte attrsz[VBO_ATTRIB_MAX];
GLuint vertex_size;
+ /* Copy of the final vertex from node->vertex_store->bufferobj.
+ * Keep this in regular (non-VBO) memory to avoid repeated
+ * map/unmap of the VBO when updating GL current data.
+ */
+ GLfloat *current_data;
+ GLuint current_size;
+
GLuint buffer_offset;
GLuint count;
GLuint wrap_count; /* number of copied vertices at start */
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c
index 52b6f1884e..868226075a 100644
--- a/src/mesa/vbo/vbo_save_api.c
+++ b/src/mesa/vbo/vbo_save_api.c
@@ -289,6 +289,31 @@ static void _save_compile_vertex_list( GLcontext *ctx )
node->vertex_store->refcount++;
node->prim_store->refcount++;
+
+ node->current_size = node->vertex_size - node->attrsz[0];
+ node->current_data = NULL;
+
+ if (node->current_size) {
+ /* If the malloc fails, we just pull the data out of the VBO
+ * later instead.
+ */
+ node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
+ if (node->current_data) {
+ const char *buffer = (const char *)save->vertex_store->buffer;
+ unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
+ unsigned vertex_offset = 0;
+
+ if (node->count)
+ vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
+
+ memcpy( node->current_data,
+ buffer + node->buffer_offset + vertex_offset + attr_offset,
+ node->current_size * sizeof(GLfloat) );
+ }
+ }
+
+
+
assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
node->count == 0);
diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c
index f59e1036d0..5110648c28 100644
--- a/src/mesa/vbo/vbo_save_draw.c
+++ b/src/mesa/vbo/vbo_save_draw.c
@@ -46,20 +46,31 @@ static void _playback_copy_to_current( GLcontext *ctx,
const struct vbo_save_vertex_list *node )
{
struct vbo_context *vbo = vbo_context(ctx);
- GLfloat vertex[VBO_ATTRIB_MAX * 4], *data = vertex;
+ GLfloat vertex[VBO_ATTRIB_MAX * 4];
+ GLfloat *data;
GLuint i, offset;
- if (node->count)
- offset = (node->buffer_offset +
- (node->count-1) * node->vertex_size * sizeof(GLfloat));
- else
- offset = node->buffer_offset;
+ if (node->current_size == 0)
+ return;
- ctx->Driver.GetBufferSubData( ctx, 0, offset,
- node->vertex_size * sizeof(GLfloat),
- data, node->vertex_store->bufferobj );
+ if (node->current_data) {
+ data = node->current_data;
+ }
+ else {
+ data = vertex;
+
+ if (node->count)
+ offset = (node->buffer_offset +
+ (node->count-1) * node->vertex_size * sizeof(GLfloat));
+ else
+ offset = node->buffer_offset;
- data += node->attrsz[0]; /* skip vertex position */
+ ctx->Driver.GetBufferSubData( ctx, 0, offset,
+ node->vertex_size * sizeof(GLfloat),
+ data, node->vertex_store->bufferobj );
+
+ data += node->attrsz[0]; /* skip vertex position */
+ }
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (node->attrsz[i]) {
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index 5fb66d3318..dcb14c868b 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -31,6 +31,7 @@
#include "main/glheader.h"
#include "main/imports.h"
+#include "main/image.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/mtypes.h"
@@ -41,7 +42,8 @@
#define ELT_TABLE_SIZE 16
-/* Used for vertex-level splitting of indexed buffers. Note that
+/**
+ * Used for vertex-level splitting of indexed buffers. Note that
* non-indexed primitives may be converted to indexed in some cases
* (eg loops, fans) in order to use this splitting path.
*/
@@ -73,23 +75,21 @@ struct copy_context {
GLuint *translated_elt_buf;
const GLuint *srcelt;
- /* A baby hash table to avoid re-emitting (some) duplicate
+ /** A baby hash table to avoid re-emitting (some) duplicate
* vertices when splitting indexed primitives.
*/
struct {
GLuint in;
GLuint out;
} vert_cache[ELT_TABLE_SIZE];
-
GLuint vertex_size;
GLubyte *dstbuf;
- GLubyte *dstptr; /* dstptr == dstbuf + dstelt_max * vertsize */
- GLuint dstbuf_size; /* in vertices */
- GLuint dstbuf_nr; /* count of emitted vertices, also the
- * largest value in dstelt. Our
- * MaxIndex.
- */
+ GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
+ GLuint dstbuf_size; /**< in vertices */
+ GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
+ * in dstelt. Our MaxIndex.
+ */
GLuint *dstelt;
GLuint dstelt_nr;
@@ -102,32 +102,19 @@ struct copy_context {
};
-static GLuint type_size( GLenum type )
-{
- switch(type) {
- case GL_BYTE: return sizeof(GLbyte);
- case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
- case GL_SHORT: return sizeof(GLshort);
- case GL_UNSIGNED_SHORT: return sizeof(GLushort);
- case GL_INT: return sizeof(GLint);
- case GL_UNSIGNED_INT: return sizeof(GLuint);
- case GL_FLOAT: return sizeof(GLfloat);
- case GL_DOUBLE: return sizeof(GLdouble);
- default: return 0;
- }
-}
-
static GLuint attr_size( const struct gl_client_array *array )
{
- return array->Size * type_size(array->Type);
+ return array->Size * _mesa_sizeof_type(array->Type);
}
-/* Starts returning true slightly before the buffer fills, to ensure
+/**
+ * Starts returning true slightly before the buffer fills, to ensure
* that there is sufficient room for any remaining vertices to finish
* off the prim:
*/
-static GLboolean check_flush( struct copy_context *copy )
+static GLboolean
+check_flush( struct copy_context *copy )
{
GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
@@ -145,7 +132,44 @@ static GLboolean check_flush( struct copy_context *copy )
return GL_FALSE;
}
-static void flush( struct copy_context *copy )
+
+/**
+ * Dump the parameters/info for a vbo->draw() call.
+ */
+static void
+dump_draw_info(GLcontext *ctx,
+ const struct gl_client_array **arrays,
+ const struct _mesa_prim *prims,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ GLuint i, j;
+
+ _mesa_printf("VBO Draw:\n");
+ for (i = 0; i < nr_prims; i++) {
+ _mesa_printf("Prim %u of %u\n", i, nr_prims);
+ _mesa_printf(" Prim mode 0x%x\n", prims[i].mode);
+ _mesa_printf(" IB: %p\n", (void*) ib);
+ for (j = 0; j < VERT_ATTRIB_MAX; j++) {
+ _mesa_printf(" array %d at %p:\n", j, (void*) arrays[j]);
+ _mesa_printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
+ arrays[j]->Enabled, arrays[j]->Ptr,
+ arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
+ if (0) {
+ GLint k = prims[i].start + prims[i].count - 1;
+ GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
+ _mesa_printf(" last: %f %f %f\n",
+ last[0], last[1], last[2]);
+ }
+ }
+ }
+}
+
+
+static void
+flush( struct copy_context *copy )
{
GLuint i;
@@ -153,6 +177,18 @@ static void flush( struct copy_context *copy )
*/
copy->dstib.count = copy->dstelt_nr;
+#if 0
+ dump_draw_info(copy->ctx,
+ copy->dstarray_ptr,
+ copy->dstprim,
+ copy->dstprim_nr,
+ &copy->dstib,
+ 0,
+ copy->dstbuf_nr);
+#else
+ (void) dump_draw_info;
+#endif
+
copy->draw( copy->ctx,
copy->dstarray_ptr,
copy->dstprim,
@@ -175,8 +211,11 @@ static void flush( struct copy_context *copy )
}
-
-static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
+/**
+ * Called at begin of each primitive during replay.
+ */
+static void
+begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
@@ -187,10 +226,12 @@ static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag
}
-/* Use a hashtable to attempt to identify recently-emitted vertices
+/**
+ * Use a hashtable to attempt to identify recently-emitted vertices
* and avoid re-emitting them.
*/
-static GLuint elt(struct copy_context *copy, GLuint elt_idx)
+static GLuint
+elt(struct copy_context *copy, GLuint elt_idx)
{
GLuint elt = copy->srcelt[elt_idx];
GLuint slot = elt & (ELT_TABLE_SIZE-1);
@@ -213,6 +254,17 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
memcpy(csr, srcptr, copy->varying[i].size);
csr += copy->varying[i].size;
+#ifdef NAN_CHECK
+ if (srcarray->Type == GL_FLOAT) {
+ GLuint k;
+ GLfloat *f = (GLfloat *) srcptr;
+ for (k = 0; k < srcarray->Size; k++) {
+ assert(!IS_INF_OR_NAN(f[k]));
+ assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
+ }
+ }
+#endif
+
if (0)
{
const GLuint *f = (const GLuint *)srcptr;
@@ -222,7 +274,6 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
_mesa_printf("%x ", f[j]);
_mesa_printf("\n");
}
-
}
copy->vert_cache[slot].in = elt;
@@ -230,9 +281,8 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
copy->dstptr += copy->vertex_size;
assert(csr == copy->dstptr);
- assert(copy->dstptr == (copy->dstbuf +
- copy->dstbuf_nr *
- copy->vertex_size));
+ assert(copy->dstptr == (copy->dstbuf +
+ copy->dstbuf_nr * copy->vertex_size));
}
/* else */
/* _mesa_printf(" --> reuse vertex\n"); */
@@ -242,7 +292,12 @@ static GLuint elt(struct copy_context *copy, GLuint elt_idx)
return check_flush(copy);
}
-static void end( struct copy_context *copy, GLboolean end_flag )
+
+/**
+ * Called at end of each primitive during replay.
+ */
+static void
+end( struct copy_context *copy, GLboolean end_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
@@ -257,8 +312,8 @@ static void end( struct copy_context *copy, GLboolean end_flag )
}
-
-static void replay_elts( struct copy_context *copy )
+static void
+replay_elts( struct copy_context *copy )
{
GLuint i, j, k;
GLboolean split;
@@ -362,7 +417,8 @@ static void replay_elts( struct copy_context *copy )
}
-static void replay_init( struct copy_context *copy )
+static void
+replay_init( struct copy_context *copy )
{
GLcontext *ctx = copy->ctx;
GLuint i;
@@ -388,10 +444,7 @@ static void replay_init( struct copy_context *copy )
copy->vertex_size += attr_size(copy->array[i]);
if (vbo->Name && !vbo->Pointer)
- ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB,
- GL_WRITE_ONLY, /* XXX */
- vbo);
+ ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
copy->array[i]->Ptr);
@@ -405,12 +458,11 @@ static void replay_init( struct copy_context *copy )
* do it internally.
*/
if (copy->ib->obj->Name && !copy->ib->obj->Pointer)
- ctx->Driver.MapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB, /* XXX */
- GL_WRITE_ONLY, /* XXX */
+ ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
copy->ib->obj);
- srcptr = (const GLubyte *)ADD_POINTERS(copy->ib->obj->Pointer, copy->ib->ptr);
+ srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
+ copy->ib->ptr);
switch (copy->ib->type) {
case GL_UNSIGNED_BYTE:
@@ -434,7 +486,6 @@ static void replay_init( struct copy_context *copy )
copy->srcelt = (const GLuint *)srcptr;
break;
}
-
/* Figure out the maximum allowed vertex buffer size:
*/
@@ -449,8 +500,7 @@ static void replay_init( struct copy_context *copy )
*
* XXX: This should be a VBO!
*/
- copy->dstbuf = _mesa_malloc(copy->dstbuf_size *
- copy->vertex_size);
+ copy->dstbuf = _mesa_malloc(copy->dstbuf_size * copy->vertex_size);
copy->dstptr = copy->dstbuf;
/* Setup new vertex arrays to point into the output buffer:
@@ -467,7 +517,7 @@ static void replay_init( struct copy_context *copy )
dst->Ptr = copy->dstbuf + offset;
dst->Enabled = GL_TRUE;
dst->Normalized = src->Normalized;
- dst->BufferObj = ctx->Array.NullBufferObj;
+ dst->BufferObj = ctx->Shared->NullBufferObj;
dst->_MaxElement = copy->dstbuf_size; /* may be less! */
offset += copy->varying[i].size;
@@ -487,12 +537,16 @@ static void replay_init( struct copy_context *copy )
*/
copy->dstib.count = 0; /* duplicates dstelt_nr */
copy->dstib.type = GL_UNSIGNED_INT;
- copy->dstib.obj = ctx->Array.NullBufferObj;
+ copy->dstib.obj = ctx->Shared->NullBufferObj;
copy->dstib.ptr = copy->dstelt;
}
-static void replay_finish( struct copy_context *copy )
+/**
+ * Free up everything allocated during split/replay.
+ */
+static void
+replay_finish( struct copy_context *copy )
{
GLcontext *ctx = copy->ctx;
GLuint i;
@@ -502,25 +556,26 @@ static void replay_finish( struct copy_context *copy )
_mesa_free(copy->translated_elt_buf);
_mesa_free(copy->dstbuf);
_mesa_free(copy->dstelt);
-
+
/* Unmap VBO's
*/
for (i = 0; i < copy->nr_varying; i++) {
struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
-
if (vbo->Name && vbo->Pointer)
- ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, vbo);
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
}
/* Unmap index buffer:
*/
if (copy->ib->obj->Name && copy->ib->obj->Pointer) {
- ctx->Driver.UnmapBuffer(ctx,
- GL_ARRAY_BUFFER_ARB, /* XXX */
- copy->ib->obj);
+ ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
}
}
+
+/**
+ * Split VBO into smaller pieces, draw the pieces.
+ */
void vbo_split_copy( GLcontext *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
@@ -546,13 +601,11 @@ void vbo_split_copy( GLcontext *ctx,
copy.draw = draw;
copy.limits = limits;
-
/* Clear the vertex cache:
*/
for (i = 0; i < ELT_TABLE_SIZE; i++)
copy.vert_cache[i].in = ~0;
-
replay_init(&copy);
replay_elts(&copy);
replay_finish(&copy);
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
index fbc856e93b..3ed6b34fbf 100644
--- a/src/mesa/vbo/vbo_split_inplace.c
+++ b/src/mesa/vbo/vbo_split_inplace.c
@@ -221,7 +221,7 @@ static void split_prims( struct split_context *split)
ib.count = count;
ib.type = GL_UNSIGNED_INT;
- ib.obj = split->ctx->Array.NullBufferObj;
+ ib.obj = split->ctx->Shared->NullBufferObj;
ib.ptr = elts;
tmpprim = *prim;