radeon/r600: Fix remaining warnings when building 64 bit binary.
[mesa.git] / src / mesa / vbo / vbo_save_api.c
index ade48d220e66a7ea3b577852212d95797a3df9db..cdbbc9c1876b5512e65cb525cc6f9cc126e6b588 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
 
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
 
 All Rights Reserved.
 
@@ -67,19 +67,28 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
 
-#include "glheader.h"
-#include "context.h"
-#include "dlist.h"
-#include "enums.h"
-#include "macros.h"
-#include "api_validate.h"
-#include "api_arrayelt.h"
-#include "vtxfmt.h"
-#include "dispatch.h"
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/dlist.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/api_validate.h"
+#include "main/api_arrayelt.h"
+#include "main/vtxfmt.h"
+#include "glapi/dispatch.h"
 
 #include "vbo_context.h"
 
 
+#ifdef ERROR
+#undef ERROR
+#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
@@ -166,7 +175,9 @@ static struct vbo_save_vertex_store *alloc_vertex_store( GLcontext *ctx )
     * 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, 
@@ -186,8 +197,9 @@ static void free_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *ver
 {
    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 );
 }
@@ -198,7 +210,7 @@ static GLfloat *map_vertex_store( GLcontext *ctx, struct vbo_save_vertex_store *
    assert(!vertex_store->buffer);
    vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx, 
                                                           GL_ARRAY_BUFFER_ARB, /* not used */
-                                                          GL_STATIC_DRAW_ARB, /* not used */
+                                                          GL_WRITE_ONLY, /* not used */
                                                           vertex_store->bufferobj); 
 
    assert(vertex_store->buffer);
@@ -229,7 +241,7 @@ static void _save_reset_counters( GLcontext *ctx )
    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) / 
@@ -277,11 +289,36 @@ 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);
 
    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;
@@ -331,7 +368,7 @@ static void _save_compile_vertex_list( GLcontext *ctx )
       /* 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) {
@@ -402,9 +439,9 @@ static void _save_wrap_filled_vertex( GLcontext *ctx )
    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++;
    }
 }
@@ -538,7 +575,7 @@ static void _save_upgrade_vertex( GLcontext *ctx,
         }
       }
 
-      save->vbptr = dest;
+      save->buffer_ptr = dest;
       save->vert_count += save->copied.nr;
    }
 }
@@ -610,9 +647,9 @@ do {                                                                \
       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 );                       \
@@ -630,19 +667,33 @@ do {                                                              \
  *     -- 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 )
 {
@@ -835,10 +886,15 @@ static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei co
    if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
       return;
 
+   _ae_map_vbos( ctx );
+
    vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
+
    for (i = 0; i < count; i++)
        CALL_ArrayElement(GET_DISPATCH(), (start + i));
    CALL_End(GET_DISPATCH(), ());
+
+   _ae_unmap_vbos( ctx );
 }
 
 /* Could do better by copying the arrays and element list intact and
@@ -853,6 +909,11 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
    if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
       return;
 
+   _ae_map_vbos( ctx );
+
+   if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
+      indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
+
    vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
 
    switch (type) {
@@ -874,6 +935,8 @@ static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum
    }
 
    CALL_End(GET_DISPATCH(), ());
+
+   _ae_unmap_vbos( ctx );
 }
 
 static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
@@ -1011,7 +1074,7 @@ void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
    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 );  
@@ -1021,15 +1084,41 @@ void vbo_save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
 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 )
@@ -1055,6 +1144,11 @@ static void vbo_destroy_vertex_list( GLcontext *ctx, void *data )
 
    if ( --node->prim_store->refcount == 0 )
       FREE( node->prim_store );
+
+   if (node->current_data) {
+      FREE(node->current_data);
+      node->current_data = NULL;
+   }
 }
 
 
@@ -1064,16 +1158,16 @@ static void vbo_print_vertex_list( GLcontext *ctx, void *data )
    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,
@@ -1095,7 +1189,7 @@ static void _save_current_init( GLcontext *ctx )
       save->current[i] = ctx->ListState.CurrentAttrib[j];
    }
 
-   for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_MAT_FRONT_AMBIENT; i++) {
+   for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
       const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
       ASSERT(j < MAT_ATTRIB_MAX);
       save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
@@ -1123,6 +1217,7 @@ void vbo_save_api_init( struct vbo_save_context *save )
    _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];