summaryrefslogtreecommitdiff
path: root/src/mesa/vbo/vbo_exec_array.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/vbo/vbo_exec_array.c')
-rw-r--r--src/mesa/vbo/vbo_exec_array.c353
1 files changed, 299 insertions, 54 deletions
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 2815ba3cc9..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,13 +37,13 @@
#include "vbo_context.h"
+
/**
* 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;
@@ -91,9 +92,198 @@ static void get_minmax_index( GLuint count, GLuint type,
/**
+ * 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
+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 )
+static void
+bind_array_obj(GLcontext *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
@@ -129,7 +319,8 @@ static void bind_array_obj( GLcontext *ctx )
}
-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;
@@ -237,7 +428,8 @@ static void recalculate_input_bindings( GLcontext *ctx )
}
-static void bind_arrays( GLcontext *ctx )
+static void
+bind_arrays(GLcontext *ctx)
{
#if 0
if (ctx->Array.ArrayObj.Name != exec->array.array_obj) {
@@ -282,6 +474,12 @@ 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... because we may have changed the bitmask of per-vertex varying
@@ -305,45 +503,67 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
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);
}
@@ -358,19 +578,40 @@ 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) index=%u is out of bounds (max=%u)",
- start, end, count, type, end,
- ctx->Array.ArrayObj->_MaxElement);
+ "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 );
@@ -437,7 +678,8 @@ vbo_exec_DrawRangeElements(GLenum mode,
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;
@@ -453,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,
@@ -475,7 +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;
@@ -489,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 */
}