tnl: Push down the gl_vertex_array inputs into tnl drivers.
[mesa.git] / src / mesa / tnl / t_draw.c
index be3f059bb567cb80d93200af9bf8bda1326a1e8f..96d6b988d3efffbbfd11c8e2c21983c175f749f8 100644 (file)
@@ -25,6 +25,8 @@
  *    Keith Whitwell <keithw@vmware.com>
  */
 
+#include <stdio.h>
+
 #include "main/glheader.h"
 #include "main/bufferobj.h"
 #include "main/condrender.h"
 #include "main/mtypes.h"
 #include "main/macros.h"
 #include "main/enums.h"
+#include "main/varray.h"
+#include "util/half_float.h"
 
 #include "t_context.h"
+#include "t_rebase.h"
 #include "tnl.h"
 
 
@@ -64,14 +69,14 @@ static void free_space(struct gl_context *ctx)
  */
 #define CONVERT( TYPE, MACRO ) do {            \
    GLuint i, j;                                        \
-   if (input->Normalized) {                    \
+   if (attrib->Normalized) {                   \
       for (i = 0; i < count; i++) {            \
         const TYPE *in = (TYPE *)ptr;          \
         for (j = 0; j < sz; j++) {             \
            *fptr++ = MACRO(*in);               \
            in++;                               \
         }                                      \
-        ptr += input->StrideB;                 \
+         ptr += binding->Stride;               \
       }                                                \
    } else {                                    \
       for (i = 0; i < count; i++) {            \
@@ -80,7 +85,7 @@ static void free_space(struct gl_context *ctx)
            *fptr++ = (GLfloat)(*in);           \
            in++;                               \
         }                                      \
-        ptr += input->StrideB;                 \
+         ptr += binding->Stride;               \
       }                                                \
    }                                           \
 } while (0)
@@ -92,25 +97,27 @@ static void free_space(struct gl_context *ctx)
  * \param fptr  output/float array
  */
 static void
-convert_bgra_to_float(const struct gl_client_array *input,
+convert_bgra_to_float(const struct gl_vertex_buffer_binding *binding,
+                      const struct gl_array_attributes *attrib,
                       const GLubyte *ptr, GLfloat *fptr,
                       GLuint count )
 {
    GLuint i;
-   assert(input->Normalized);
-   assert(input->Size == 4);
+   assert(attrib->Normalized);
+   assert(attrib->Size == 4);
    for (i = 0; i < count; i++) {
       const GLubyte *in = (GLubyte *) ptr;  /* in is in BGRA order */
       *fptr++ = UBYTE_TO_FLOAT(in[2]);  /* red */
       *fptr++ = UBYTE_TO_FLOAT(in[1]);  /* green */
       *fptr++ = UBYTE_TO_FLOAT(in[0]);  /* blue */
       *fptr++ = UBYTE_TO_FLOAT(in[3]);  /* alpha */
-      ptr += input->StrideB;
+      ptr += binding->Stride;
    }
 }
 
 static void
-convert_half_to_float(const struct gl_client_array *input,
+convert_half_to_float(const struct gl_vertex_buffer_binding *binding,
+                      const struct gl_array_attributes *attrib,
                      const GLubyte *ptr, GLfloat *fptr,
                      GLuint count, GLuint sz)
 {
@@ -122,7 +129,7 @@ convert_half_to_float(const struct gl_client_array *input,
       for (j = 0; j < sz; j++) {
         *fptr++ = _mesa_half_to_float(in[j]);
       }
-      ptr += input->StrideB;
+      ptr += binding->Stride;
    }
 }
 
@@ -137,21 +144,22 @@ convert_half_to_float(const struct gl_client_array *input,
  * is used to map the fixed-point numbers into the range [-1, 1].
  */
 static void
-convert_fixed_to_float(const struct gl_client_array *input,
+convert_fixed_to_float(const struct gl_vertex_buffer_binding *binding,
+                       const struct gl_array_attributes *attrib,
                        const GLubyte *ptr, GLfloat *fptr,
                        GLuint count)
 {
    GLuint i;
    GLint j;
-   const GLint size = input->Size;
+   const GLint size = attrib->Size;
 
-   if (input->Normalized) {
+   if (attrib->Normalized) {
       for (i = 0; i < count; ++i) {
          const GLfixed *in = (GLfixed *) ptr;
          for (j = 0; j < size; ++j) {
             *fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
          }
-         ptr += input->StrideB;
+         ptr += binding->Stride;
       }
    } else {
       for (i = 0; i < count; ++i) {
@@ -159,7 +167,7 @@ convert_fixed_to_float(const struct gl_client_array *input,
          for (j = 0; j < size; ++j) {
             *fptr++ = in[j] / (GLfloat) (1 << 16);
          }
-         ptr += input->StrideB;
+         ptr += binding->Stride;
       }
    }
 }
@@ -168,28 +176,29 @@ convert_fixed_to_float(const struct gl_client_array *input,
  * floating point, populate VB->AttribPtr[].
  */
 static void _tnl_import_array( struct gl_context *ctx,
-                              GLuint attrib,
+                               GLuint attr,
                               GLuint count,
-                              const struct gl_client_array *input,
+                               const struct gl_vertex_buffer_binding *binding,
+                               const struct gl_array_attributes *attrib,
                               const GLubyte *ptr )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
-   GLuint stride = input->StrideB;
+   GLuint stride = binding->Stride;
 
-   if (input->Type != GL_FLOAT) {
-      const GLuint sz = input->Size;
+   if (attrib->Type != GL_FLOAT) {
+      const GLuint sz = attrib->Size;
       GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
       GLfloat *fptr = (GLfloat *)buf;
 
-      switch (input->Type) {
+      switch (attrib->Type) {
       case GL_BYTE: 
         CONVERT(GLbyte, BYTE_TO_FLOAT); 
         break;
       case GL_UNSIGNED_BYTE: 
-         if (input->Format == GL_BGRA) {
+         if (attrib->Format == GL_BGRA) {
             /* See GL_EXT_vertex_array_bgra */
-            convert_bgra_to_float(input, ptr, fptr, count);
+            convert_bgra_to_float(binding, attrib, ptr, fptr, count);
          }
          else {
             CONVERT(GLubyte, UBYTE_TO_FLOAT); 
@@ -211,10 +220,10 @@ static void _tnl_import_array( struct gl_context *ctx,
         CONVERT(GLdouble, (GLfloat)); 
         break;
       case GL_HALF_FLOAT:
-        convert_half_to_float(input, ptr, fptr, count, sz);
+        convert_half_to_float(binding, attrib, ptr, fptr, count, sz);
         break;
       case GL_FIXED:
-         convert_fixed_to_float(input, ptr, fptr, count);
+         convert_fixed_to_float(binding, attrib, ptr, fptr, count);
          break;
       default:
         assert(0);
@@ -225,20 +234,20 @@ static void _tnl_import_array( struct gl_context *ctx,
       stride = sz * sizeof(GLfloat);
    }
 
-   VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib];
-   VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr;
-   VB->AttribPtr[attrib]->start = (GLfloat *)ptr;
-   VB->AttribPtr[attrib]->count = count;
-   VB->AttribPtr[attrib]->stride = stride;
-   VB->AttribPtr[attrib]->size = input->Size;
+   VB->AttribPtr[attr] = &tnl->tmp_inputs[attr];
+   VB->AttribPtr[attr]->data = (GLfloat (*)[4])ptr;
+   VB->AttribPtr[attr]->start = (GLfloat *)ptr;
+   VB->AttribPtr[attr]->count = count;
+   VB->AttribPtr[attr]->stride = stride;
+   VB->AttribPtr[attr]->size = attrib->Size;
 
    /* This should die, but so should the whole GLvector4f concept: 
     */
-   VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | 
+   VB->AttribPtr[attr]->flags = (((1<<attrib->Size)-1) |
                                   VEC_NOT_WRITEABLE |
                                   (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
    
-   VB->AttribPtr[attrib]->storage = NULL;
+   VB->AttribPtr[attr]->storage = NULL;
 }
 
 #define CLIPVERTS  ((6 + MAX_CLIP_PLANES) * 2)
@@ -255,7 +264,7 @@ static GLboolean *_tnl_import_edgeflag( struct gl_context *ctx,
    GLuint i;
 
    for (i = 0; i < count; i++) {
-      *bptr++ = ((GLfloat *)ptr)[0] == 1.0;
+      *bptr++ = ((GLfloat *)ptr)[0] == 1.0F;
       ptr += stride;
    }
 
@@ -264,7 +273,7 @@ static GLboolean *_tnl_import_edgeflag( struct gl_context *ctx,
 
 
 static void bind_inputs( struct gl_context *ctx, 
-                        const struct gl_client_array *inputs[],
+                        const struct gl_vertex_array *inputs,
                         GLint count,
                         struct gl_buffer_object **bo,
                         GLuint *nr_bo )
@@ -276,25 +285,28 @@ static void bind_inputs( struct gl_context *ctx,
    /* Map all the VBOs
     */
    for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      const struct gl_vertex_array *array = &inputs[i];
+      const struct gl_vertex_buffer_binding *binding = array->BufferBinding;
+      const struct gl_array_attributes *attrib = array->VertexAttrib;
       const void *ptr;
 
-      if (inputs[i]->BufferObj->Name) { 
-        if (!inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer) {
-           bo[*nr_bo] = inputs[i]->BufferObj;
+      if (_mesa_is_bufferobj(binding->BufferObj)) {
+        if (!binding->BufferObj->Mappings[MAP_INTERNAL].Pointer) {
+           bo[*nr_bo] = binding->BufferObj;
            (*nr_bo)++;
-           ctx->Driver.MapBufferRange(ctx, 0, inputs[i]->BufferObj->Size,
+           ctx->Driver.MapBufferRange(ctx, 0, binding->BufferObj->Size,
                                       GL_MAP_READ_BIT,
-                                      inputs[i]->BufferObj,
+                                       binding->BufferObj,
                                        MAP_INTERNAL);
            
-           assert(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer);
+            assert(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer);
         }
         
-        ptr = ADD_POINTERS(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer,
-                           inputs[i]->Ptr);
+         ptr = ADD_POINTERS(binding->BufferObj->Mappings[MAP_INTERNAL].Pointer,
+                            binding->Offset + attrib->RelativeOffset);
       }
       else
-        ptr = inputs[i]->Ptr;
+         ptr = attrib->Ptr;
 
       /* Just make sure the array is floating point, otherwise convert to
        * temporary storage.  
@@ -302,7 +314,7 @@ static void bind_inputs( struct gl_context *ctx,
        * XXX: remove the GLvector4f type at some stage and just use
        * client arrays.
        */
-      _tnl_import_array(ctx, i, count, inputs[i], ptr);
+      _tnl_import_array(ctx, i, count, binding, attrib, ptr);
    }
 
    /* We process only the vertices between min & max index:
@@ -355,7 +367,7 @@ static void bind_indices( struct gl_context *ctx,
       bo[*nr_bo] = ib->obj;
       (*nr_bo)++;
       ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr,
-                                       ib->count * vbo_sizeof_ib_type(ib->type),
+                                       ib->count * ib->index_size,
                                       GL_MAP_READ_BIT, ib->obj,
                                        MAP_INTERNAL);
       assert(ib->obj->Mappings[MAP_INTERNAL].Pointer);
@@ -364,19 +376,19 @@ static void bind_indices( struct gl_context *ctx,
       ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].Pointer, ib->ptr);
    }
 
-   if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) {
+   if (ib->index_size == 4 && VB->Primitive[0].basevertex == 0) {
       VB->Elts = (GLuint *) ptr;
    }
    else {
       GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
       VB->Elts = elts;
 
-      if (ib->type == GL_UNSIGNED_INT) {
+      if (ib->index_size == 4) {
         const GLuint *in = (GLuint *)ptr;
         for (i = 0; i < ib->count; i++)
            *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
       }
-      else if (ib->type == GL_UNSIGNED_SHORT) {
+      else if (ib->index_size == 2) {
         const GLushort *in = (GLushort *)ptr;
         for (i = 0; i < ib->count; i++) 
            *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
@@ -411,9 +423,7 @@ static void unmap_vbos( struct gl_context *ctx,
 }
 
 
-/* This is the main entrypoint into the slimmed-down software tnl
- * module.  In a regular swtnl driver, this can be plugged straight
- * into the vbo->Driver.DrawPrims() callback.
+/* This is the main workhorse doing all the rendering work.
  */
 void _tnl_draw_prims(struct gl_context *ctx,
                         const struct _mesa_prim *prim,
@@ -423,10 +433,11 @@ void _tnl_draw_prims(struct gl_context *ctx,
                         GLuint min_index,
                         GLuint max_index,
                         struct gl_transform_feedback_object *tfb_vertcount,
+                         unsigned stream,
                         struct gl_buffer_object *indirect)
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
-   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
+   const struct gl_vertex_array *arrays = ctx->Array._DrawArrays;
    const GLuint TEST_SPLIT = 0;
    const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
    GLint max_basevertex = prim->basevertex;
@@ -446,10 +457,10 @@ void _tnl_draw_prims(struct gl_context *ctx,
 
    if (0)
    {
-      printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+      printf("%s %d..%d\n", __func__, min_index, max_index);
       for (i = 0; i < nr_prims; i++)
         printf("prim %d: %s start %d count %d\n", i, 
-               _mesa_lookup_enum_by_nr(prim[i].mode),
+               _mesa_enum_to_string(prim[i].mode),
                prim[i].start,
                prim[i].count);
    }
@@ -457,9 +468,9 @@ void _tnl_draw_prims(struct gl_context *ctx,
    if (min_index) {
       /* We always translate away calls with min_index != 0. 
        */
-      vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, 
-                       min_index, max_index,
-                       _tnl_draw_prims );
+      t_rebase_prims( ctx, arrays, prim, nr_prims, ib,
+                      min_index, max_index,
+                      _tnl_draw_prims );
       return;
    }
    else if ((GLint)max_index + max_basevertex > max) {
@@ -525,3 +536,40 @@ void _tnl_draw_prims(struct gl_context *ctx,
    }
 }
 
+
+void
+_tnl_bind_inputs( struct gl_context *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   _mesa_set_drawing_arrays(ctx, tnl->draw_arrays.inputs);
+   _vbo_update_inputs(ctx, &tnl->draw_arrays);
+}
+
+
+/* This is the main entrypoint into the slimmed-down software tnl
+ * module.  In a regular swtnl driver, this can be plugged straight
+ * into the ctx->Driver.Draw() callback.
+ */
+void
+_tnl_draw(struct gl_context *ctx,
+          const struct _mesa_prim *prim, GLuint nr_prims,
+          const struct _mesa_index_buffer *ib,
+          GLboolean index_bounds_valid, GLuint min_index, GLuint max_index,
+          struct gl_transform_feedback_object *tfb_vertcount,
+          unsigned stream, struct gl_buffer_object *indirect)
+{
+   /* Update TNLcontext::draw_arrays and set that pointer
+    * into Array._DrawArrays.
+    */
+   _tnl_bind_inputs(ctx);
+
+   _tnl_draw_prims(ctx, prim, nr_prims, ib, index_bounds_valid,
+                   min_index, max_index, tfb_vertcount, stream, indirect);
+}
+
+
+void
+_tnl_init_driver_draw_function(struct dd_function_table *functions)
+{
+   functions->Draw = _tnl_draw;
+}