Restructure code.
authorVladimir Dergachev <volodya@freedesktop.org>
Thu, 30 Dec 2004 10:11:39 +0000 (10:11 +0000)
committerVladimir Dergachev <volodya@freedesktop.org>
Thu, 30 Dec 2004 10:11:39 +0000 (10:11 +0000)
Add drawing code that uses vertex buffers - does not lockup, but does not draw correctly either.. Perhaps something to do with vertices being overwritten ?
Start using hardware state retained by the driver and cut back on direct register writes significantly.

src/mesa/drivers/dri/r300/r300_render.c

index 3007d282e427a2afbc62febff9f5607351f4c7b8..93c3a63e478864e8ab4c4453433284879123acdf 100644 (file)
@@ -63,63 +63,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 * rasterization hardware for rendering.
 **********************************************************************/
 
-static void r300_render_flat_primitive(r300ContextPtr rmesa, 
-       GLcontext *ctx,
-       int start,
-       int end,
-       int type)
-{
-   TNLcontext *tnl = TNL_CONTEXT(ctx);
-   struct vertex_buffer *VB = &tnl->vb;
-   GLuint i;
-   int k;
-   LOCAL_VARS
-               
-   if(end<=start)return; /* do we need to watch for this ? */
-   
-
-
-   start_immediate_packet(end-start, type, 8);
-
-       for(i=start;i<end;i++){
-               #if 0
-               fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n", 
-                       VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
-                       VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
-                       VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
-                       VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
-                       
-                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
-                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
-                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
-                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
-                       );
-               #endif
-               
-               /* coordinates */
-               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[0]);
-               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[1]);
-               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[2]);
-               #if 0
-               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]);
-               #else
-               efloat(2.0);
-               #endif
-               
-               /* color components */
-               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0]);
-               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1]);
-               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2]);
-               #if 0
-               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]);
-               #else
-               efloat(0.0);
-               #endif
-               }
-
-}
-
-static void r300_dispatch_flat_primitive(r300ContextPtr rmesa, 
+static int r300_get_primitive_type(r300ContextPtr rmesa, 
        GLcontext *ctx,
        int start,
        int end,
@@ -130,7 +74,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
    GLuint i;
    int type=-1;
    
-   if(end<=start)return; /* do we need to watch for this ? */
+   if(end<=start)return -1; /* do we need to watch for this ? */
    
        fprintf(stderr, "[%d-%d]", start, end);
        switch (prim & PRIM_MODE_MASK) {
@@ -139,7 +83,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_LINES;
                if(end<start+2){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_LINE_STRIP:
@@ -147,15 +91,15 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
                if(end<start+2){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_LINE_LOOP:
                fprintf(stderr, "LL ");
-               return;
+               return -1;
                if(end<start+2){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_TRIANGLES:
@@ -163,7 +107,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
                if(end<start+3){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_TRIANGLE_STRIP:
@@ -171,7 +115,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
                if(end<start+3){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_TRIANGLE_FAN:
@@ -179,7 +123,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
                if(end<start+3){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_QUADS:
@@ -187,7 +131,7 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_QUADS;
                if(end<start+4){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                case GL_QUAD_STRIP:
@@ -195,16 +139,97 @@ static void r300_dispatch_flat_primitive(r300ContextPtr rmesa,
                type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
                if(end<start+4){
                        fprintf(stderr, "Not enough vertices\n");
-                       return; /* need enough vertices for Q */
+                       return -1; /* need enough vertices for Q */
                        }
                break;
                default:
                fprintf(stderr, "Cannot handle primitive %02x ", prim & PRIM_MODE_MASK);
-               return;
+               return -1;
                break;
                }
-   r300_render_flat_primitive(rmesa, ctx, start, end, type);
-       
+   return type;
+}
+
+
+
+/* Immediate implementation - vertex data is sent via command stream */
+
+static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
+
+#define output_vector(v, i) \
+       { \
+       int _i; \
+       for(_i=0;_i<v->size;_i++){ \
+               efloat(VEC_ELT(v, GLfloat, i)[_i]); \
+               } \
+       for(_i=v->size;_i<4;_i++){ \
+                       efloat(default_vector[_i]); \
+                       } \
+       }
+
+static void r300_render_flat_primitive(r300ContextPtr rmesa, 
+       GLcontext *ctx,
+       int start,
+       int end,
+       int prim)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+   int k, type;
+   LOCAL_VARS
+               
+   type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
+   if(type<0)return;
+
+
+   start_immediate_packet(end-start, type, 8);
+
+       for(i=start;i<end;i++){
+               #if 0
+               fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n", 
+                       VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
+                       VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
+                       VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
+                       VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
+                       
+                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
+                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
+                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
+                       VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
+                       );
+               #endif
+               
+               
+               /* coordinates */
+               #if 1
+               output_vector(VB->ObjPtr, i);
+               #else
+               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[0]);
+               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[1]);
+               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[2]);
+               #if 0
+               efloat(VEC_ELT(VB->ObjPtr, GLfloat, i)[3]);
+               #else
+               efloat(2.0);
+               #endif
+               #endif
+               
+               /* color components */
+               #if 1
+               output_vector(VB->ColorPtr[0], i);
+               #else
+               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0]);
+               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1]);
+               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2]);
+               #if 0
+               efloat(VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]);
+               #else
+               efloat(0.0);
+               #endif
+               #endif
+               }
+
 }
 
 static GLboolean r300_run_flat_render(GLcontext *ctx,
@@ -214,7 +239,6 @@ static GLboolean r300_run_flat_render(GLcontext *ctx,
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLuint i;
-   ADAPTOR adaptor;
    AOS_DATA vb_arrays[2];
    LOCAL_VARS
        
@@ -231,6 +255,7 @@ static GLboolean r300_run_flat_render(GLcontext *ctx,
    vb_arrays[0].offset=0; /* Not used */
    vb_arrays[0].format=AOS_FORMAT_FLOAT;
    vb_arrays[0].ncomponents=4;
+   vb_arrays[0].reg=REG_COORDS;
 
     /* color */
    vb_arrays[1].element_size=4;
@@ -238,46 +263,205 @@ static GLboolean r300_run_flat_render(GLcontext *ctx,
    vb_arrays[1].offset=0; /* Not used */
    vb_arrays[1].format=AOS_FORMAT_FLOAT_COLOR;
    vb_arrays[1].ncomponents=4;
+   vb_arrays[1].reg=REG_COLOR0;
 
-   adaptor=TWO_PIPE_ADAPTOR;
+   r300EmitState(rmesa);
    
-   adaptor.color_offset[0]=rmesa->radeon.radeonScreen->backOffset+rmesa->radeon.radeonScreen->fbLocation;
-   adaptor.color_pitch[0]=(rmesa->radeon.radeonScreen->backPitch) | (0xc0<<16);
+   /* needed before starting 3d operation .. */
+   reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+       e32(0x0000000a);
+   
+   reg_start(0x4f18,0);
+       e32(0x00000003);
+       
+       
+   reg_start(0x20b0,0);
+       e32(0x0000043f);
+   program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
 
-   adaptor.depth_offset=rmesa->radeon.radeonScreen->depthOffset;
-   adaptor.depth_pitch=rmesa->radeon.radeonScreen->depthPitch | (0x2 << 16);
+   #if 0 /* Turn on for smooth color on teeth.. why ??.. */
+   set_cull_cntl(PASS_PREFIX 0);
+   #endif
+   reg_start(R300_RE_OCCLUSION_CNTL, 0);
+            e32(R300_OCCLUSION_ON);
+            
+//   set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
+     set_init21(PASS_PREFIX 0.0,1.0);
    
-   init_3d(PASS_PREFIX &adaptor);
-   init_flat_primitive(PASS_PREFIX &adaptor);
+   /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
+   setup_AOS(PASS_PREFIX vb_arrays, 2);
+   
+   for(i=0; i < VB->PrimitiveCount; i++){
+       GLuint prim = VB->Primitive[i].mode;
+       GLuint start = VB->Primitive[i].start;
+       GLuint length = VB->Primitive[i].count;
+       r300_render_flat_primitive(rmesa, ctx, start, start + length, prim);
+       }
+       
+   end_3d(PASS_PREFIX_VOID);
    
-   set_scissors(PASS_PREFIX 0, 0, 2647, 1941);
+   fprintf(stderr, "\n");
+   return GL_FALSE;
+}
+
+/* vertex buffer implementation */
+
+/* We use the start part of GART texture buffer for vertices */
 
-   set_cliprect(PASS_PREFIX 0, 0, 0, 2647,1941);
-   set_cliprect(PASS_PREFIX 1, 0, 0, 2647,1941);
-   set_cliprect(PASS_PREFIX 2, 0, 0, 2647,1941);
-   set_cliprect(PASS_PREFIX 3, 0, 0, 2647,1941);
+#define R300_MAX_AOS_ARRAYS            16
+
+static void upload_vertex_buffer(r300ContextPtr rmesa, 
+       GLcontext *ctx, AOS_DATA *array, int *n_arrays)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   int offset=0, idx=0;
+   int i,j;
+   radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
+   /* Not the most efficient implementation, but, for now, I just want something that
+      works */
+      /* to do - make single memcpy per column (is it possible ?) */
+      /* to do - use dirty flags to avoid redundant copies */
+#define UPLOAD_VECTOR(v, r, f)\
+       { \
+        /* Is the data dirty ? */ \
+       if (v->flags & ((1<<v->size)-1)) { \
+               fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
+               if(v->size*4==v->stride){\
+                       /* fast path */  \
+                       memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
+                       } else { \
+                       for(i=0;i<VB->Count;i++){ \
+                               /* copy one vertex at a time*/ \
+                               memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \
+                               } \
+                       } \
+               /* v->flags &= ~((1<<v->size)-1);*/ \
+               } \
+       array[idx].element_size=v->size; \
+       array[idx].stride=v->size; \
+       array[idx].format=(f); \
+       array[idx].ncomponents=v->size; \
+       array[idx].offset=rsp->gartTextures.handle+offset; \
+       array[idx].reg=r; \
+       offset+=v->size*4*VB->Count; \
+       idx++; \
+       /* Fill in the rest with the components of default_vector */\
+       /* \
+       if(v->size<4){ \
+               array[idx].element_size=4-v->size; \
+               array[idx].stride=0; \
+               array[idx].format=(f); \
+               array[idx].ncomponents=4-v->size; \
+               array[idx].offset=rsp->gartTextures.handle+v->size*4;\
+               array[idx].reg=r; \
+               idx++; \
+               } \
+       */\
+       }
+       
+/* Put a copy of default vector */
+memcpy(rsp->gartTextures.map, default_vector, 16);
+offset+=16;
+               
+UPLOAD_VECTOR(VB->ObjPtr, REG_COORDS, AOS_FORMAT_FLOAT);
+UPLOAD_VECTOR(VB->ColorPtr[0], REG_COLOR0, AOS_FORMAT_FLOAT_COLOR);
+
+*n_arrays=idx;
+if(idx>=R300_MAX_AOS_ARRAYS){
+       fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
+       exit(-1);
+       }
+}
+
+static void r300_render_vb_flat_primitive(r300ContextPtr rmesa, 
+       GLcontext *ctx,
+       int start,
+       int end,
+       int prim)
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+   int k, type, n_arrays;
+   LOCAL_VARS
+               
+   if(end<=start)return; /* do we need to watch for this ? */
+   
+   type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
+   if(type<0)return;
+
+   fire_AOS(PASS_PREFIX end-start, type);
+}
+
+static VERTEX_SHADER_FRAGMENT default_vector_vsf={
+       length: 4,
+       body: { 
+               f: {0.0, 0.0, 0.0, 1.0}
+               }
+       };
+
+static GLboolean r300_run_vb_flat_render(GLcontext *ctx,
+                                struct tnl_pipeline_stage *stage)
+{
+   r300ContextPtr rmesa = R300_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   int i, j, n_arrays;
+   AOS_DATA vb_arrays[R300_MAX_AOS_ARRAYS];
+   AOS_DATA vb_arrays2[R300_MAX_AOS_ARRAYS];
+   LOCAL_VARS
+       
+       if (RADEON_DEBUG == DEBUG_PRIMS)
+               fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* setup array of structures data */
+
+   upload_vertex_buffer(rmesa, ctx, vb_arrays, &n_arrays);
+   fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
+   
+   r300EmitState(rmesa);
+   
+   reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
+       e32(0x0000000a);
+   
+   reg_start(0x4f18,0);
+       e32(0x00000003);
+   
+   reg_start(0x20b0,0);
+       e32(0x0000043f);
+   program_pipeline(PASS_PREFIX &FLAT_COLOR_PIPELINE);
+      
+   //upload_vertex_shader_fragment(PASS_PREFIX VSF_DEST_UNKNOWN1, &default_vector_vsf);
    
    reg_start(R300_RE_OCCLUSION_CNTL, 0);
             e32(R300_OCCLUSION_ON);
-
+            
    set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
    set_init21(PASS_PREFIX 0.0,1.0);
-
-   /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
-   setup_AOS(PASS_PREFIX vb_arrays, 2);
    
    for(i=0; i < VB->PrimitiveCount; i++){
        GLuint prim = VB->Primitive[i].mode;
        GLuint start = VB->Primitive[i].start;
        GLuint length = VB->Primitive[i].count;
-       r300_dispatch_flat_primitive(rmesa, ctx, start, start + length, prim);
+       
+        /* copy arrays */
+        memcpy(vb_arrays2, vb_arrays, sizeof(AOS_DATA)*n_arrays);
+       for(j=0;j<n_arrays;j++){
+               vb_arrays2[j].offset+=vb_arrays2[j].stride*start;
+               }
+               
+        setup_AOS(PASS_PREFIX vb_arrays2, n_arrays);
+       
+       r300_render_vb_flat_primitive(rmesa, ctx, start, start + length, prim);
        }
        
    end_3d(PASS_PREFIX_VOID);
    
-   start_packet3(RADEON_CP_PACKET3_NOP, 0);
-   e32(0x0);
-   
+   /* Flush state - we are done drawing.. */
+   r300Flush(ctx);
    fprintf(stderr, "\n");
    return GL_FALSE;
 }