Example #1
0
vector unsigned int
reduce_word(vector unsigned int x) {
  vector unsigned int result;
  int i = 0;

  for(i; i < 4; i++) {
    result = result + x;
    x = si_rotqbyi(x, 4);
  }

  return result;
}
Example #2
0
/**
 * Sort vertices from top to bottom.
 * Compute area and determine front vs. back facing.
 * Do coarse clip test against tile bounds
 * \return  FALSE if tri is totally outside tile, TRUE otherwise
 */
static boolean
setup_sort_vertices(const qword vs)
{
   float area, sign;

#if DEBUG_VERTS
   if (spu.init.id==0) {
      fprintf(stderr, "SPU %u: Triangle:\n", spu.init.id);
      print_vertex(v0);
      print_vertex(v1);
      print_vertex(v2);
   }
#endif

   {
      /* Load the float values for various processing... */
      const qword f0 = (qword)(((const struct vertex_header*)si_to_ptr(vs))->data[0]);
      const qword f1 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 4)))->data[0]);
      const qword f2 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 8)))->data[0]);

      /* Check if triangle is completely outside the tile bounds
       * Find the min and max x and y positions of the three poits */
      const qword minf = min3fq(f0, f1, f2);
      const qword maxf = max3fq(f0, f1, f2);

      /* Compare min and max against cliprect vals */
      const qword maxsmins = si_shufb(maxf, minf, SHUFB4(A,B,a,b));
      const qword outside = si_fcgt(maxsmins, si_csflt(setup.cliprect, 0));

      /* Use a little magic to work out of the tri is visible or not */
      if(si_to_uint(si_xori(si_gb(outside), 0xc))) return FALSE;

      /* determine bottom to top order of vertices */
      /* A table of shuffle patterns for putting vertex_header pointers into
         correct order.  Quite magical. */
      const qword sort_order_patterns[] = {
         SHUFB4(A,B,C,C),
         SHUFB4(C,A,B,C),
         SHUFB4(A,C,B,C),
         SHUFB4(B,C,A,C),
         SHUFB4(B,A,C,C),
         SHUFB4(C,B,A,C) };

      /* Collate y values into two vectors for comparison.
         Using only one shuffle constant! ;) */
      const qword y_02_ = si_shufb(f0, f2, SHUFB4(0,B,b,C));
      const qword y_10_ = si_shufb(f1, f0, SHUFB4(0,B,b,C));
      const qword y_012 = si_shufb(y_02_, f1, SHUFB4(0,B,b,C));
      const qword y_120 = si_shufb(y_10_, f2, SHUFB4(0,B,b,C));

      /* Perform comparison: {y0,y1,y2} > {y1,y2,y0} */
      const qword compare = si_fcgt(y_012, y_120);
      /* Compress the result of the comparison into 4 bits */
      const qword gather = si_gb(compare);
      /* Subtract one to attain the index into the LUT.  Magical. */
      const unsigned int index = si_to_uint(gather) - 1;

      /* Load the appropriate pattern and construct the desired vector. */
      setup.vertex_headers = si_shufb(vs, vs, sort_order_patterns[index]);

      /* Using the result of the comparison, set sign.
         Very magical. */
      sign = ((si_to_uint(si_cntb(gather)) == 2) ? 1.0f : -1.0f);
   }

   setup.ebot.ds = spu_sub(setup.vmid->data[0], setup.vmin->data[0]);
   setup.emaj.ds = spu_sub(setup.vmax->data[0], setup.vmin->data[0]);
   setup.etop.ds = spu_sub(setup.vmax->data[0], setup.vmid->data[0]);

   /*
    * Compute triangle's area.  Use 1/area to compute partial
    * derivatives of attributes later.
    */
   area = setup.emaj.dx * setup.ebot.dy - setup.ebot.dx * setup.emaj.dy;

   setup.oneOverArea = 1.0f / area;

   /* The product of area * sign indicates front/back orientation (0/1).
    * Just in case someone gets the bright idea of switching the front
    * and back constants without noticing that we're assuming their
    * values in this operation, also assert that the values are
    * what we think they are.
    */
   ASSERT(CELL_FACING_FRONT == 0);
   ASSERT(CELL_FACING_BACK == 1);
   setup.facing = (area * sign > 0.0f)
      ^ (spu.rasterizer.front_winding == PIPE_WINDING_CW);

   return TRUE;
}