Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / vbo / vbo_exec_draw.c
index f665c64c7ace74fdc5891ed2f3ae7557ce7a243e..5bf3d836db57224b8bc11d45ccc12cdc2c613e93 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  5.1
+ * Version:  7.2
  *
- * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "context.h"
-#include "enums.h"
-#include "state.h"
-#include "macros.h"
+#include "main/glheader.h"
+#include "main/bufferobj.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/state.h"
+#include "main/macros.h"
 
 #include "vbo_context.h"
 
@@ -114,6 +115,11 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
         return 2;
       }
    case GL_TRIANGLE_STRIP:
+      /* no parity issue, but need to make sure the tri is not drawn twice */
+      if (nr & 1) {
+        exec->vtx.prim[exec->vtx.prim_count-1].count--;
+      }
+      /* fallthrough */
    case GL_QUAD_STRIP:
       switch (nr) {
       case 0: ovf = 0; break;
@@ -123,7 +129,7 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
       for (i = 0 ; i < ovf ; i++)
         _mesa_memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
       return i;
-   case GL_POLYGON+1:
+   case PRIM_OUTSIDE_BEGIN_END:
       return 0;
    default:
       assert(0);
@@ -132,35 +138,85 @@ static GLuint vbo_copy_vertices( struct vbo_exec_context *exec )
 }
 
 
+
 /* TODO: populate these as the vertex is defined:
  */
-static void vbo_exec_bind_arrays( struct vbo_exec_context *exec )
+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 = exec->vtx.buffer_map;
+   const GLuint *map;
    GLuint attr;
+   GLbitfield varying_inputs = 0x0;
 
-   memcpy(arrays,      exec->legacy_currval, 16 * sizeof(arrays[0]));
-   memcpy(arrays + 16, exec->mat_currval,    16 * sizeof(arrays[0]));
+   /* Install the default (ie Current) attributes first, then overlay
+    * all active ones.
+    */
+   switch (get_program_mode(exec->ctx)) {
+   case VP_NONE:
+      for (attr = 0; attr < 16; attr++) {
+         exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+      }
+      for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
+         exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr];
+      }
+      map = vbo->map_vp_none;
+      break;
+   case VP_NV:
+   case VP_ARB:
+      /* The aliasing of attributes for NV vertex programs has already
+       * occurred.  NV vertex programs cannot access material values,
+       * nor attributes greater than VERT_ATTRIB_TEX7.  
+       */
+      for (attr = 0; attr < 16; attr++) {
+         exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
+         exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
+      }
+      map = vbo->map_vp_arb;
+      break;
+   }
 
    /* Make all active attributes (including edgeflag) available as
     * arrays of floats.
     */
-   for (attr = 0; attr < VBO_ATTRIB_MAX ; attr++) {
-      if (exec->vtx.attrsz[attr]) {
-        arrays[attr].Ptr = (void *)data;
-        arrays[attr].Size = exec->vtx.attrsz[attr];
+   for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) {
+      const GLuint src = map[attr];
+
+      if (exec->vtx.attrsz[src]) {
+         /* override the default array set above */
+         exec->vtx.inputs[attr] = &arrays[attr];
+
+         if (exec->vtx.bufferobj->Name) {
+            /* a real buffer obj: Ptr is an offset, not a pointer*/
+            int offset;
+            assert(exec->vtx.bufferobj->Pointer);  /* buf should be mapped */
+            offset = (GLbyte *) data - (GLbyte *) exec->vtx.bufferobj->Pointer;
+            assert(offset >= 0);
+            arrays[attr].Ptr = (void *) offset;
+         }
+         else {
+            /* Ptr into ordinary app memory */
+            arrays[attr].Ptr = (void *) data;
+         }
+        arrays[attr].Size = exec->vtx.attrsz[src];
         arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
         arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
         arrays[attr].Type = GL_FLOAT;
         arrays[attr].Enabled = 1;
-        arrays[attr].BufferObj = exec->vtx.bufferobj; /* NullBufferObj */
+         _mesa_reference_buffer_object(ctx,
+                                       &arrays[attr].BufferObj,
+                                       exec->vtx.bufferobj);
         arrays[attr]._MaxElement = count; /* ??? */
 
-        data += exec->vtx.attrsz[attr] * sizeof(GLfloat);
+        data += exec->vtx.attrsz[src] * sizeof(GLfloat);
+         varying_inputs |= 1<<attr;
       }
    }
+
+   _mesa_set_varying_vp_inputs( ctx, varying_inputs );
 }
 
 
@@ -181,7 +237,23 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec )
       if (exec->vtx.copied.nr != exec->vtx.vert_count) {
         GLcontext *ctx = exec->ctx;
 
-        vbo_exec_bind_arrays( exec );
+        GLenum target = GL_ARRAY_BUFFER_ARB;
+        GLenum access = GL_READ_WRITE_ARB;
+        GLenum usage = GL_STREAM_DRAW_ARB;
+        GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat);
+        
+        /* Before the unmap (why?)
+         */
+        vbo_exec_bind_arrays( ctx );
+
+         if (ctx->NewState)
+            _mesa_update_state( ctx );
+
+         /* if using a real VBO, unmap it before drawing */
+         if (exec->vtx.bufferobj->Name) {
+            ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
+            exec->vtx.buffer_map = NULL;
+         }
 
         vbo_context(ctx)->draw_prims( ctx, 
                                       exec->vtx.inputs, 
@@ -189,7 +261,14 @@ void vbo_exec_vtx_flush( struct vbo_exec_context *exec )
                                       exec->vtx.prim_count,
                                       NULL,
                                       0,
-                                      exec->vtx.vert_count );
+                                      exec->vtx.vert_count - 1);
+
+        /* If using a real VBO, get new storage */
+         if (exec->vtx.bufferobj->Name) {
+            ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
+            exec->vtx.buffer_map = 
+               ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
+         }
       }
    }