Cell: draw smooth-shaded triangle
authorBrian <brian.paul@tungstengraphics.com>
Wed, 12 Dec 2007 01:26:52 +0000 (18:26 -0700)
committerBrian <brian.paul@tungstengraphics.com>
Wed, 12 Dec 2007 01:26:52 +0000 (18:26 -0700)
src/mesa/pipe/cell/common.h
src/mesa/pipe/cell/ppu/cell_surface.c
src/mesa/pipe/cell/spu/main.c
src/mesa/pipe/cell/spu/tri.c

index c986b59..f7f1e2e 100644 (file)
@@ -75,10 +75,8 @@ struct cell_command_clear_tiles
 
 struct cell_command_triangle
 {
-   float x0, y0;
-   float x1, y1;
-   float x2, y2;
-   uint color;
+   float vert[3][4];
+   float color[3][4];
 } ALIGN16_ATTRIB;
 
 
index 143f554..185eeb2 100644 (file)
@@ -69,20 +69,31 @@ cell_clear_surface(struct pipe_context *pipe, struct pipe_surface *ps,
 #if 1
    /* XXX Draw a test triangle over the cleared surface */
    for (i = 0; i < cell->num_spus; i++) {
-      /* Same triangle data for all SPUs, of course: */
+      /* Same triangle data for all SPUs */
       struct cell_command_triangle *tri = &cell_global.command[i].tri;
+      tri->vert[0][0] = 20.0;
+      tri->vert[0][1] = ps->height - 20;
 
-      tri->x0 = 20.0;
-      tri->y0 = ps->height - 20;
+      tri->vert[1][0] = ps->width - 20.0;
+      tri->vert[1][1] = ps->height - 20;
 
-      tri->x1 = ps->width - 20.0;
-      tri->y1 = ps->height - 20;
+      tri->vert[2][0] = ps->width / 2;
+      tri->vert[2][1] = 20.0;
 
-      tri->x2 = ps->width / 2;
-      tri->y2 = 20.0;
+      tri->color[0][0] = 1.0;
+      tri->color[0][1] = 0.0;
+      tri->color[0][2] = 0.0;
+      tri->color[0][3] = 0.0;
 
-      /* XXX color varies per SPU */
-      tri->color = 0xffff00 | ((i*40)<<24);  /* yellow */
+      tri->color[1][0] = 0.0;
+      tri->color[1][1] = 1.0;
+      tri->color[1][2] = 0.0;
+      tri->color[1][3] = 0.0;
+
+      tri->color[2][0] = 0.0;
+      tri->color[2][1] = 0.0;
+      tri->color[2][2] = 1.0;
+      tri->color[2][3] = 0.0;
 
       send_mbox_message(cell_global.spe_contexts[i], CELL_CMD_TRIANGLE);
    }
index 6a77e3e..cc5eddb 100644 (file)
@@ -138,13 +138,13 @@ triangle(const struct cell_command_triangle *tri)
    struct prim_header prim;
    uint i;
 
-   prim.v[0].data[0][0] = tri->x0;
-   prim.v[0].data[0][1] = tri->y0;
-   prim.v[1].data[0][0] = tri->x1;
-   prim.v[1].data[0][1] = tri->y1;
-   prim.v[2].data[0][0] = tri->x2;
-   prim.v[2].data[0][1] = tri->y2;
-   prim.color = tri->color;
+   COPY_4V(prim.v[0].data[0], tri->vert[0]);
+   COPY_4V(prim.v[1].data[0], tri->vert[1]);
+   COPY_4V(prim.v[2].data[0], tri->vert[2]);
+
+   COPY_4V(prim.v[0].data[1], tri->color[0]);
+   COPY_4V(prim.v[1].data[1], tri->color[1]);
+   COPY_4V(prim.v[2].data[1], tri->color[2]);
 
    for (i = init.id; i < num_tiles; i += init.num_spus) {
       uint tx = i % fb.width_tiles;
@@ -212,11 +212,7 @@ main_loop(void)
          clear_tiles(&cmd.clear);
          break;
       case CELL_CMD_TRIANGLE:
-         printf("SPU %u: TRIANGLE (%g,%g) (%g,%g) (%g,%g)\n",
-                init.id,
-                cmd.tri.x0, cmd.tri.y0,
-                cmd.tri.x1, cmd.tri.y1,
-                cmd.tri.x2, cmd.tri.y2);
+         printf("SPU %u: TRIANGLE\n", init.id);
          triangle(&cmd.tri);
          break;
       case CELL_CMD_FINISH:
index 60a62fd..90452f1 100644 (file)
 #include "main.h"
 #include "tri.h"
 
+/*
+#include <vmx2spu.h>
+#include <spu_internals.h>
+*/
+
 
 #if 1
 
@@ -64,6 +69,8 @@
 #define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
 #define MASK_ALL          0xf
 
+#define PIPE_MAX_SHADER_INPUTS 8 /* XXX temp */
+
 static int cliprect_minx, cliprect_maxx, cliprect_miny, cliprect_maxy;
 
 static uint tile[TILE_SIZE][TILE_SIZE] ALIGN16_ATTRIB;
@@ -85,6 +92,13 @@ struct edge {
 };
 
 
+struct interp_coef
+{
+   float a0[4];
+   float dadx[4];
+   float dady[4];
+};
+
 /**
  * Triangle setup info (derived from draw_stage).
  * Also used for line drawing (taking some liberties).
@@ -113,7 +127,10 @@ struct setup_stage {
 
 #if 0
    struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
+#else
+   struct interp_coef coef[PIPE_MAX_SHADER_INPUTS];
 #endif
+
 #if 0
    struct quad_header quad; 
 #endif
@@ -189,6 +206,41 @@ clip_emit_quad(struct setup_stage *setup)
 #endif
 
 /**
+ * Evaluate attribute coefficients (plane equations) to compute
+ * attribute values for the four fragments in a quad.
+ * Eg: four colors will be compute.
+ */
+static INLINE void
+eval_coeff( struct setup_stage *setup, uint slot,
+            float x, float y, float result[4][4])
+{
+   uint i;
+   const float *dadx = setup->coef[slot].dadx;
+   const float *dady = setup->coef[slot].dady;
+
+   /* loop over XYZW comps */
+   for (i = 0; i < 4; i++) {
+      result[QUAD_TOP_LEFT][i] = setup->coef[slot].a0[i] + x * dadx[i] + y * dady[i];
+      result[QUAD_TOP_RIGHT][i] = result[0][i] + dadx[i];
+      result[QUAD_BOTTOM_LEFT][i] = result[0][i] + dady[i];
+      result[QUAD_BOTTOM_RIGHT][i] = result[0][i] + dadx[i] + dady[i];
+   }
+}
+
+
+static INLINE uint
+pack_color(const float color[4])
+{
+   uint r = (uint) (color[0] * 255.0);
+   uint g = (uint) (color[1] * 255.0);
+   uint b = (uint) (color[2] * 255.0);
+   uint a = (uint) (color[3] * 255.0);
+   uint icolor = (b << 24) | (g << 16) | (r << 8) | a;
+   return icolor;
+}
+
+
+/**
  * Emit a quad (pass to next stage).  No clipping is done.
  */
 static INLINE void
@@ -204,14 +256,18 @@ emit_quad( struct setup_stage *setup, int x, int y, unsigned mask )
    /* Cell: "write" quad fragments to the tile by setting prim color */
    int ix = x - cliprect_minx;
    int iy = y - cliprect_miny;
+   float colors[4][4];
+
+   eval_coeff(setup, 1, (float) x, (float) y, colors);
+
    if (mask & MASK_TOP_LEFT)
-      tile[iy][ix] = setup->color;
+      tile[iy][ix] = pack_color(colors[QUAD_TOP_LEFT]);
    if (mask & MASK_TOP_RIGHT)
-      tile[iy][ix+1] = setup->color;
+      tile[iy][ix+1] = pack_color(colors[QUAD_TOP_RIGHT]);
    if (mask & MASK_BOTTOM_LEFT)
-      tile[iy+1][ix] = setup->color;
+      tile[iy+1][ix] = pack_color(colors[QUAD_BOTTOM_LEFT]);
    if (mask & MASK_BOTTOM_RIGHT)
-      tile[iy+1][ix+1] = setup->color;
+      tile[iy+1][ix+1] = pack_color(colors[QUAD_BOTTOM_RIGHT]);
 #endif
 }
 
@@ -445,41 +501,41 @@ static void const_coeff( struct setup_stage *setup,
 #endif
 
 
-#if 0
 /**
  * Compute a0, dadx and dady for a linearly interpolated coefficient,
  * for a triangle.
  */
 static void tri_linear_coeff( struct setup_stage *setup,
-                              unsigned slot,
-                              unsigned i)
+                              unsigned slot )
 {
-   float botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
-   float majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
-   float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
-   float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
+   uint i;
+   for (i = 0; i < 4; i++) {
+      float botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
+      float majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
+      float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
+      float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
    
-   assert(slot < PIPE_MAX_SHADER_INPUTS);
-   assert(i <= 3);
+      assert(slot < PIPE_MAX_SHADER_INPUTS);
 
-   setup->coef[slot].dadx[i] = a * setup->oneoverarea;
-   setup->coef[slot].dady[i] = b * setup->oneoverarea;
+      setup->coef[slot].dadx[i] = a * setup->oneoverarea;
+      setup->coef[slot].dady[i] = b * setup->oneoverarea;
 
-   /* calculate a0 as the value which would be sampled for the
-    * fragment at (0,0), taking into account that we want to sample at
-    * pixel centers, in other words (0.5, 0.5).
-    *
-    * this is neat but unfortunately not a good way to do things for
-    * triangles with very large values of dadx or dady as it will
-    * result in the subtraction and re-addition from a0 of a very
-    * large number, which means we'll end up loosing a lot of the
-    * fractional bits and precision from a0.  the way to fix this is
-    * to define a0 as the sample at a pixel center somewhere near vmin
-    * instead - i'll switch to this later.
-    */
-   setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] - 
-                           (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) + 
-                            setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
+      /* calculate a0 as the value which would be sampled for the
+       * fragment at (0,0), taking into account that we want to sample at
+       * pixel centers, in other words (0.5, 0.5).
+       *
+       * this is neat but unfortunately not a good way to do things for
+       * triangles with very large values of dadx or dady as it will
+       * result in the subtraction and re-addition from a0 of a very
+       * large number, which means we'll end up loosing a lot of the
+       * fractional bits and precision from a0.  the way to fix this is
+       * to define a0 as the sample at a pixel center somewhere near vmin
+       * instead - i'll switch to this later.
+       */
+      setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] - 
+                                 (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) + 
+                                  setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
+   }
 
    /*
    _mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
@@ -489,7 +545,6 @@ static void tri_linear_coeff( struct setup_stage *setup,
                setup->coef[slot].dady[i]);
    */
 }
-#endif
 
 
 #if 0
@@ -536,13 +591,13 @@ static void tri_persp_coeff( struct setup_stage *setup,
 #endif
 
 
-#if 0
 /**
  * Compute the setup->coef[] array dadx, dady, a0 values.
  * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
  */
 static void setup_tri_coefficients( struct setup_stage *setup )
 {
+#if 0
    const enum interp_mode *interp = setup->softpipe->vertex_info.interp_mode;
    unsigned slot, j;
 
@@ -575,8 +630,10 @@ static void setup_tri_coefficients( struct setup_stage *setup )
          assert(0);
       }
    }
-}
+#else
+   tri_linear_coeff(setup, 1);  /* slot 1 = color */
 #endif
+}
 
 
 static void setup_tri_edges( struct setup_stage *setup )
@@ -710,9 +767,7 @@ static void setup_tri(
    */
 
    setup_sort_vertices( setup, prim );
-#if 0
    setup_tri_coefficients( setup );
-#endif
    setup_tri_edges( setup );
 
 #if 0