summaryrefslogtreecommitdiff
path: root/src/mesa/vbo
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r--src/mesa/vbo/vbo_context.c12
-rw-r--r--src/mesa/vbo/vbo_exec.c3
-rw-r--r--src/mesa/vbo/vbo_exec_api.c12
-rw-r--r--src/mesa/vbo/vbo_exec_array.c57
-rw-r--r--src/mesa/vbo/vbo_exec_draw.c1
-rw-r--r--src/mesa/vbo/vbo_save.c13
-rw-r--r--src/mesa/vbo/vbo_save_loopback.c1
-rw-r--r--src/mesa/vbo/vbo_split.c4
-rw-r--r--src/mesa/vbo/vbo_split_copy.c3
-rw-r--r--src/mesa/vbo/vbo_split_inplace.c114
10 files changed, 133 insertions, 87 deletions
diff --git a/src/mesa/vbo/vbo_context.c b/src/mesa/vbo/vbo_context.c
index 75c32e0b9b..a5b0070bd3 100644
--- a/src/mesa/vbo/vbo_context.c
+++ b/src/mesa/vbo/vbo_context.c
@@ -249,17 +249,25 @@ void _vbo_InvalidateState( GLcontext *ctx, GLuint new_state )
void _vbo_DestroyContext( GLcontext *ctx )
{
+ struct vbo_context *vbo = vbo_context(ctx);
+
if (ctx->aelt_context) {
_ae_destroy_context( ctx );
ctx->aelt_context = NULL;
}
- if (vbo_context(ctx)) {
+ if (vbo) {
+ GLuint i;
+
+ for (i = 0; i < VBO_ATTRIB_MAX; i++) {
+ _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
+ }
+
vbo_exec_destroy(ctx);
#if FEATURE_dlist
vbo_save_destroy(ctx);
#endif
- FREE(vbo_context(ctx));
+ FREE(vbo);
ctx->swtnl_im = NULL;
}
}
diff --git a/src/mesa/vbo/vbo_exec.c b/src/mesa/vbo/vbo_exec.c
index e168a89ea5..a057befed0 100644
--- a/src/mesa/vbo/vbo_exec.c
+++ b/src/mesa/vbo/vbo_exec.c
@@ -28,9 +28,6 @@
#include "main/api_arrayelt.h"
#include "main/glheader.h"
-#include "main/imports.h"
-#include "main/context.h"
-#include "main/macros.h"
#include "main/mtypes.h"
#include "main/vtxfmt.h"
diff --git a/src/mesa/vbo/vbo_exec_api.c b/src/mesa/vbo/vbo_exec_api.c
index f0a7eeadd0..8ee14be261 100644
--- a/src/mesa/vbo/vbo_exec_api.c
+++ b/src/mesa/vbo/vbo_exec_api.c
@@ -759,6 +759,7 @@ void vbo_use_buffer_objects(GLcontext *ctx)
}
/* Allocate a real buffer object now */
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
}
@@ -803,8 +804,19 @@ void vbo_exec_vtx_init( struct vbo_exec_context *exec )
{
struct gl_client_array *arrays = exec->vtx.arrays;
+ unsigned i;
+
memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+
+ for (i = 0; i < 16; ++i) {
+ arrays[i ].BufferObj = NULL;
+ arrays[i + 16].BufferObj = NULL;
+ _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
+ vbo->legacy_currval[i].BufferObj);
+ _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
+ vbo->generic_currval[i].BufferObj);
+ }
}
exec->vtx.vertex_size = 0;
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index 6de8f059b7..88502f3d35 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -35,7 +35,6 @@
#include "main/bufferobj.h"
#include "main/enums.h"
#include "main/macros.h"
-#include "glapi/dispatch.h"
#include "vbo_context.h"
@@ -50,7 +49,7 @@ vbo_get_minmax_index(GLcontext *ctx,
GLuint *min_index, GLuint *max_index)
{
GLuint i;
- GLsizei count = prim->count;
+ GLuint count = prim->count;
const void *indices;
if (_mesa_is_bufferobj(ib->obj)) {
@@ -133,7 +132,7 @@ check_array_data(GLcontext *ctx, struct gl_client_array *array,
case GL_FLOAT:
{
GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
- GLuint k;
+ GLint k;
for (k = 0; k < array->Size; k++) {
if (IS_INF_OR_NAN(f[k]) ||
f[k] >= 1.0e20 || f[k] <= -1.0e10) {
@@ -444,6 +443,13 @@ recalculate_input_bindings(GLcontext *ctx)
}
+/**
+ * Examine the enabled vertex arrays to set the exec->array.inputs[] values.
+ * These will point to the arrays to actually use for drawing. Some will
+ * be user-provided arrays, other will be zero-stride const-valued arrays.
+ * Note that this might set the _NEW_ARRAY dirty flag so state validation
+ * must be done after this call.
+ */
static void
bind_arrays(GLcontext *ctx)
{
@@ -485,9 +491,6 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
FLUSH_CURRENT( ctx, 0 );
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
return;
}
@@ -543,7 +546,7 @@ dump_element_buffer(GLcontext *ctx, GLenum type)
case GL_UNSIGNED_BYTE:
{
const GLubyte *us = (const GLubyte *) map;
- GLuint i;
+ GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
_mesa_printf("%02x ", us[i]);
if (i % 32 == 31)
@@ -555,7 +558,7 @@ dump_element_buffer(GLcontext *ctx, GLenum type)
case GL_UNSIGNED_SHORT:
{
const GLushort *us = (const GLushort *) map;
- GLuint i;
+ GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
_mesa_printf("%04x ", us[i]);
if (i % 16 == 15)
@@ -567,7 +570,7 @@ dump_element_buffer(GLcontext *ctx, GLenum type)
case GL_UNSIGNED_INT:
{
const GLuint *us = (const GLuint *) map;
- GLuint i;
+ GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
_mesa_printf("%08x ", us[i]);
if (i % 8 == 7)
@@ -601,18 +604,16 @@ vbo_validated_drawrangeelements(GLcontext *ctx, GLenum mode,
FLUSH_CURRENT( ctx, 0 );
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
return;
}
+ bind_arrays( ctx );
+
+ /* check for dirty state again */
if (ctx->NewState)
_mesa_update_state( ctx );
- bind_arrays( ctx );
-
ib.count = count;
ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
@@ -689,6 +690,16 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
* or we can read/write out of memory in several different places!
*/
+ /* Catch/fix some potential user errors */
+ if (type == GL_UNSIGNED_BYTE) {
+ start = MIN2(start, 0xff);
+ end = MIN2(end, 0xff);
+ }
+ else if (type == GL_UNSIGNED_SHORT) {
+ start = MIN2(start, 0xffff);
+ end = MIN2(end, 0xffff);
+ }
+
if (end >= ctx->Array.ArrayObj->_MaxElement) {
/* the max element is out of bounds of one or more enabled arrays */
warnCount++;
@@ -713,8 +724,7 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
#ifdef DEBUG
/* 'end' was out of bounds, but now let's check the actual array
- * indexes to see if any of them are out of bounds. If so, warn
- * and skip the draw to avoid potential segfault, etc.
+ * indexes to see if any of them are out of bounds.
*/
{
GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
@@ -731,7 +741,6 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
ctx->Array.ElementArrayBufferObj->Name,
ctx->Array.ElementArrayBufferObj->Size);
}
- return;
}
/* XXX we could also find the min index and compare to 'start'
* to see if start is correct. But it's more likely to get the
@@ -739,6 +748,10 @@ vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
*/
}
#endif
+
+ /* Set 'end' to the max possible legal value */
+ assert(ctx->Array.ArrayObj->_MaxElement >= 1);
+ end = ctx->Array.ArrayObj->_MaxElement - 1;
}
else if (0) {
_mesa_printf("glDraw[Range]Elements{,BaseVertex}"
@@ -837,16 +850,10 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
FLUSH_CURRENT( ctx, 0 );
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
return;
}
- if (ctx->NewState)
- _mesa_update_state( ctx );
-
prim = _mesa_calloc(primcount * sizeof(*prim));
if (prim == NULL) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
@@ -858,6 +865,10 @@ vbo_validated_multidrawelements(GLcontext *ctx, GLenum mode,
*/
bind_arrays( ctx );
+ /* check for dirty state again */
+ if (ctx->NewState)
+ _mesa_update_state( ctx );
+
switch (type) {
case GL_UNSIGNED_INT:
index_type_size = 4;
diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c
index 4f43856016..d7dbbceb1b 100644
--- a/src/mesa/vbo/vbo_exec_draw.c
+++ b/src/mesa/vbo/vbo_exec_draw.c
@@ -30,7 +30,6 @@
#include "main/context.h"
#include "main/enums.h"
#include "main/state.h"
-#include "main/macros.h"
#include "vbo_context.h"
diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c
index 9757c3d9f6..fd9a130270 100644
--- a/src/mesa/vbo/vbo_save.c
+++ b/src/mesa/vbo/vbo_save.c
@@ -28,8 +28,6 @@
#include "main/mtypes.h"
#include "main/bufferobj.h"
-#include "main/dlist.h"
-#include "main/vtxfmt.h"
#include "main/imports.h"
#include "vbo_context.h"
@@ -60,8 +58,19 @@ void vbo_save_init( GLcontext *ctx )
{
struct gl_client_array *arrays = save->arrays;
+ unsigned i;
+
memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+
+ for (i = 0; i < 16; ++i) {
+ arrays[i ].BufferObj = NULL;
+ arrays[i + 16].BufferObj = NULL;
+ _mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
+ vbo->legacy_currval[i].BufferObj);
+ _mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
+ vbo->generic_currval[i].BufferObj);
+ }
}
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c
index b7a74e4535..f13a16e3b5 100644
--- a/src/mesa/vbo/vbo_save_loopback.c
+++ b/src/mesa/vbo/vbo_save_loopback.c
@@ -29,7 +29,6 @@
#include "main/glheader.h"
#include "main/enums.h"
#include "main/imports.h"
-#include "main/macros.h"
#include "main/mtypes.h"
#include "glapi/dispatch.h"
#include "glapi/glapi.h"
diff --git a/src/mesa/vbo/vbo_split.c b/src/mesa/vbo/vbo_split.c
index c445acca7d..ce40cbbcc3 100644
--- a/src/mesa/vbo/vbo_split.c
+++ b/src/mesa/vbo/vbo_split.c
@@ -108,12 +108,14 @@ void vbo_split_prims( GLcontext *ctx,
vbo_draw_func draw,
const struct split_limits *limits )
{
- GLuint max_basevertex = prim->basevertex;
+ GLint max_basevertex = prim->basevertex;
GLuint i;
for (i = 1; i < nr_prims; i++)
max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
+ /* XXX max_basevertex is computed but not used, why? */
+
if (ib) {
if (limits->max_indices == 0) {
/* Could traverse the indices, re-emitting vertices in turn.
diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c
index c45190b9dd..2ca111217c 100644
--- a/src/mesa/vbo/vbo_split_copy.c
+++ b/src/mesa/vbo/vbo_split_copy.c
@@ -34,7 +34,6 @@
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
-#include "main/enums.h"
#include "main/mtypes.h"
#include "vbo_split.h"
@@ -221,8 +220,6 @@ begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
-/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_prim_by_nr(mode), begin_flag); */
-
prim->mode = mode;
prim->begin = begin_flag;
}
diff --git a/src/mesa/vbo/vbo_split_inplace.c b/src/mesa/vbo/vbo_split_inplace.c
index da84eaa6ea..2fc866c577 100644
--- a/src/mesa/vbo/vbo_split_inplace.c
+++ b/src/mesa/vbo/vbo_split_inplace.c
@@ -30,12 +30,15 @@
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/enums.h"
+#include "main/image.h"
#include "vbo_split.h"
#define MAX_PRIM 32
-/* Used for splitting without copying.
+/* Used for splitting without copying. No attempt is made to handle
+ * too large indexed vertex buffers: In general you need to copy to do
+ * that.
*/
struct split_context {
GLcontext *ctx;
@@ -48,6 +51,7 @@ struct split_context {
vbo_draw_func draw;
const struct split_limits *limits;
+ GLuint limit;
struct _mesa_prim dstprim[MAX_PRIM];
GLuint dstprim_nr;
@@ -58,38 +62,38 @@ struct split_context {
static void flush_vertex( struct split_context *split )
{
- GLuint min_index, max_index;
+ struct _mesa_index_buffer ib;
GLuint i;
if (!split->dstprim_nr)
return;
- min_index = split->dstprim[0].start;
- max_index = min_index + split->dstprim[0].count - 1;
+ if (split->ib) {
+ ib = *split->ib;
- for (i = 1; i < split->dstprim_nr; i++) {
- GLuint tmp_min = split->dstprim[i].start;
- GLuint tmp_max = tmp_min + split->dstprim[i].count - 1;
+ ib.count = split->max_index - split->min_index + 1;
+ ib.ptr = (const void *)((const char *)ib.ptr +
+ split->min_index * _mesa_sizeof_type(ib.type));
- if (tmp_min < min_index)
- min_index = tmp_min;
-
- if (tmp_max > max_index)
- max_index = tmp_max;
+ /* Rebase the primitives to save index buffer entries. */
+ for (i = 0; i < split->dstprim_nr; i++)
+ split->dstprim[i].start -= split->min_index;
}
- assert(max_index >= min_index);
+ assert(split->max_index >= split->min_index);
- split->draw( split->ctx,
- split->array,
- split->dstprim,
- split->dstprim_nr,
- NULL,
- GL_TRUE,
- min_index,
- max_index);
+ split->draw(split->ctx,
+ split->array,
+ split->dstprim,
+ split->dstprim_nr,
+ split->ib ? &ib : NULL,
+ !split->ib,
+ split->min_index,
+ split->max_index);
split->dstprim_nr = 0;
+ split->min_index = ~0;
+ split->max_index = 0;
}
@@ -106,62 +110,67 @@ static struct _mesa_prim *next_outprim( struct split_context *split )
}
}
-static int align(int value, int alignment)
+static void update_index_bounds(struct split_context *split,
+ const struct _mesa_prim *prim)
{
- return (value + alignment - 1) & ~(alignment - 1);
+ split->min_index = MIN2(split->min_index, prim->start);
+ split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
}
-
+/* Return the maximum amount of vertices that can be emitted for a
+ * primitive starting at 'prim->start', depending on the previous
+ * index bounds.
+ */
+static GLuint get_max_vertices(struct split_context *split,
+ const struct _mesa_prim *prim)
+{
+ if ((prim->start > split->min_index &&
+ prim->start - split->min_index >= split->limit) ||
+ (prim->start < split->max_index &&
+ split->max_index - prim->start >= split->limit))
+ /* "prim" starts too far away from the old range. */
+ return 0;
+
+ return MIN2(split->min_index, prim->start) + split->limit - prim->start;
+}
/* Break large primitives into smaller ones. If not possible, convert
* the primitive to indexed and pass to split_elts().
*/
static void split_prims( struct split_context *split)
{
- GLuint csr = 0;
GLuint i;
for (i = 0; i < split->nr_prims; i++) {
const struct _mesa_prim *prim = &split->prim[i];
GLuint first, incr;
GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
- GLuint count;
-
- /* Always wrap on an even numbered vertex to avoid problems with
- * triangle strips.
- */
- GLuint available = align(split->limits->max_verts - csr - 1, 2);
- assert(split->limits->max_verts >= csr);
+ GLuint available = get_max_vertices(split, prim);
+ GLuint count = prim->count - (prim->count - first) % incr;
if (prim->count < first)
continue;
-
- count = prim->count - (prim->count - first) % incr;
-
- if ((available < count && !split_inplace) ||
+ if ((available < count && !split_inplace) ||
(available < first && split_inplace)) {
flush_vertex(split);
- csr = 0;
- available = align(split->limits->max_verts - csr - 1, 2);
+ available = get_max_vertices(split, prim);
}
if (available >= count) {
struct _mesa_prim *outprim = next_outprim(split);
+
*outprim = *prim;
- csr += prim->count;
- available = align(split->limits->max_verts - csr - 1, 2);
- }
+ update_index_bounds(split, outprim);
+ }
else if (split_inplace) {
GLuint j, nr;
-
for (j = 0 ; j < count ; ) {
GLuint remaining = count - j;
struct _mesa_prim *outprim = next_outprim(split);
nr = MIN2( available, remaining );
-
nr -= (nr - first) % incr;
outprim->mode = prim->mode;
@@ -169,21 +178,20 @@ static void split_prims( struct split_context *split)
outprim->end = (nr == remaining && prim->end);
outprim->start = prim->start + j;
outprim->count = nr;
-
+
+ update_index_bounds(split, outprim);
+
if (nr == remaining) {
/* Finished.
*/
- j += nr;
- csr += nr;
- available = align(split->limits->max_verts - csr - 1, 2);
+ j += nr;
}
else {
/* Wrapped the primitive:
*/
j += nr - (first - incr);
flush_vertex(split);
- csr = 0;
- available = align(split->limits->max_verts - csr - 1, 2);
+ available = get_max_vertices(split, prim);
}
}
}
@@ -260,10 +268,14 @@ void vbo_split_inplace( GLcontext *ctx,
split.prim = prim;
split.nr_prims = nr_prims;
split.ib = ib;
- split.min_index = min_index;
- split.max_index = max_index;
+
+ /* Empty interval, makes calculations simpler. */
+ split.min_index = ~0;
+ split.max_index = 0;
+
split.draw = draw;
split.limits = limits;
+ split.limit = ib ? limits->max_indices : limits->max_verts;
split_prims( &split );
}