/**************************************************************************
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
#include "main/glheader.h"
+#include "main/bufferobj.h"
#include "main/context.h"
#include "main/dlist.h"
#include "main/enums.h"
#endif
+/* An interesting VBO number/name to help with debugging */
+#define VBO_BUF_ID 12345
+
+
/*
* NOTE: Old 'parity' issue is gone, but copying can still be
* wrong-footed on replay.
* user. Perhaps there could be a special number for internal
* buffers:
*/
- vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB);
+ vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
+ VBO_BUF_ID,
+ GL_ARRAY_BUFFER_ARB);
ctx->Driver.BufferData( ctx,
GL_ARRAY_BUFFER_ARB,
{
assert(!vertex_store->buffer);
- if (vertex_store->bufferobj)
- ctx->Driver.DeleteBuffer( ctx, vertex_store->bufferobj );
+ if (vertex_store->bufferobj) {
+ _mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
+ }
FREE( vertex_store );
}
save->buffer = (save->vertex_store->buffer +
save->vertex_store->used);
- assert(save->buffer == save->vbptr);
+ assert(save->buffer == save->buffer_ptr);
if (save->vertex_size)
save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
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);
if (save->dangling_attr_ref)
- ctx->ListState.CurrentList->flags |= MESA_DLIST_DANGLING_REFS;
+ ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
save->vertex_store->used += save->vertex_size * node->count;
save->prim_store->used += node->prim_count;
/* Allocate and map new store:
*/
save->vertex_store = alloc_vertex_store( ctx );
- save->vbptr = map_vertex_store( ctx, save->vertex_store );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
}
if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
assert(save->max_vert - save->vert_count > save->copied.nr);
for (i = 0 ; i < save->copied.nr ; i++) {
- _mesa_memcpy( save->vbptr, data, save->vertex_size * sizeof(GLfloat));
+ _mesa_memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
data += save->vertex_size;
- save->vbptr += save->vertex_size;
+ save->buffer_ptr += save->vertex_size;
save->vert_count++;
}
}
}
}
- save->vbptr = dest;
+ save->buffer_ptr = dest;
save->vert_count += save->copied.nr;
}
}
GLuint i; \
\
for (i = 0; i < save->vertex_size; i++) \
- save->vbptr[i] = save->vertex[i]; \
+ save->buffer_ptr[i] = save->vertex[i]; \
\
- save->vbptr += save->vertex_size; \
+ save->buffer_ptr += save->vertex_size; \
\
if (++save->vert_count >= save->max_vert) \
_save_wrap_filled_vertex( ctx ); \
* -- Flush current buffer
* -- Fallback to opcodes for the rest of the begin/end object.
*/
-#define DO_FALLBACK(ctx) \
-do { \
- struct vbo_save_context *save = &vbo_context(ctx)->save; \
- \
- if (save->vert_count || save->prim_count) \
- _save_compile_vertex_list( ctx ); \
- \
- _save_copy_to_current( ctx ); \
- _save_reset_vertex( ctx ); \
- _save_reset_counters( ctx ); \
- _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \
- ctx->Driver.SaveNeedFlush = 0; \
-} while (0)
+static void DO_FALLBACK( GLcontext *ctx )
+{
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ if (save->vert_count || save->prim_count) {
+ GLint i = save->prim_count - 1;
+
+ /* Close off in-progress primitive.
+ */
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+
+ /* Need to replay this display list with loopback,
+ * unfortunately, otherwise this primitive won't be handled
+ * properly:
+ */
+ save->dangling_attr_ref = 1;
+
+ _save_compile_vertex_list( ctx );
+ }
+
+ _save_copy_to_current( ctx );
+ _save_reset_vertex( ctx );
+ _save_reset_counters( ctx );
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ ctx->Driver.SaveNeedFlush = 0;
+}
static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
{
_ae_map_vbos( ctx );
- if (ctx->Array.ElementArrayBufferObj->Name)
+ if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
if (!save->vertex_store)
save->vertex_store = alloc_vertex_store( ctx );
- save->vbptr = map_vertex_store( ctx, save->vertex_store );
+ save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
_save_reset_vertex( ctx );
_save_reset_counters( ctx );
void vbo_save_EndList( GLcontext *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
+
+ /* EndList called inside a (saved) Begin/End pair?
+ */
+ if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
+
+ if (save->prim_count > 0) {
+ GLint i = save->prim_count - 1;
+ ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
+ save->prim[i].end = 0;
+ save->prim[i].count = (save->vert_count -
+ save->prim[i].start);
+ }
+
+ /* Make sure this vertex list gets replayed by the "loopback"
+ * mechanism:
+ */
+ save->dangling_attr_ref = 1;
+ vbo_save_SaveFlushVertices( ctx );
+
+ /* Swap out this vertex format while outside begin/end. Any color,
+ * etc. received between here and the next begin will be compiled
+ * as opcodes.
+ */
+ _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
+ }
+
unmap_vertex_store( ctx, save->vertex_store );
assert(save->vertex_size == 0);
}
-void vbo_save_BeginCallList( GLcontext *ctx, struct mesa_display_list *dlist )
+void vbo_save_BeginCallList( GLcontext *ctx, struct gl_display_list *dlist )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- save->replay_flags |= dlist->flags;
+ save->replay_flags |= dlist->Flags;
}
void vbo_save_EndCallList( GLcontext *ctx )
if ( --node->prim_store->refcount == 0 )
FREE( node->prim_store );
+
+ if (node->current_data) {
+ FREE(node->current_data);
+ node->current_data = NULL;
+ }
}
GLuint i;
(void) ctx;
- _mesa_debug(NULL, "VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
- node->count,
- node->prim_count,
- node->vertex_size);
+ _mesa_printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
+ node->count,
+ node->prim_count,
+ node->vertex_size);
for (i = 0 ; i < node->prim_count ; i++) {
struct _mesa_prim *prim = &node->prim[i];
_mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
i,
- _mesa_lookup_enum_by_nr(prim->mode),
+ _mesa_lookup_prim_by_nr(prim->mode),
prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
_save_vtxfmt_init( ctx );
_save_current_init( ctx );
+ /* These will actually get set again when binding/drawing */
for (i = 0; i < VBO_ATTRIB_MAX; i++)
save->inputs[i] = &save->arrays[i];