Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /*
  29.  * Binning code for lines
  30.  */
  31.  
  32. #include "util/u_math.h"
  33. #include "util/u_memory.h"
  34. #include "lp_perf.h"
  35. #include "lp_setup_context.h"
  36. #include "lp_rast.h"
  37. #include "lp_state_fs.h"
  38. #include "lp_state_setup.h"
  39. #include "lp_context.h"
  40.  
  41. #define NUM_CHANNELS 4
  42.  
  43. struct lp_line_info {
  44.  
  45.    float dx;
  46.    float dy;
  47.    float oneoverarea;
  48.  
  49.    const float (*v1)[4];
  50.    const float (*v2)[4];
  51.  
  52.    float (*a0)[4];
  53.    float (*dadx)[4];
  54.    float (*dady)[4];
  55. };
  56.  
  57.  
  58. /**
  59.  * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
  60.  */
  61. static void constant_coef( struct lp_setup_context *setup,
  62.                            struct lp_line_info *info,
  63.                            unsigned slot,
  64.                            const float value,
  65.                            unsigned i )
  66. {
  67.    info->a0[slot][i] = value;
  68.    info->dadx[slot][i] = 0.0f;
  69.    info->dady[slot][i] = 0.0f;
  70. }
  71.  
  72.  
  73. /**
  74.  * Compute a0, dadx and dady for a linearly interpolated coefficient,
  75.  * for a triangle.
  76.  */
  77. static void linear_coef( struct lp_setup_context *setup,
  78.                          struct lp_line_info *info,
  79.                          unsigned slot,
  80.                          unsigned vert_attr,
  81.                          unsigned i)
  82. {
  83.    float a1 = info->v1[vert_attr][i];
  84.    float a2 = info->v2[vert_attr][i];
  85.      
  86.    float da21 = a1 - a2;  
  87.    float dadx = da21 * info->dx * info->oneoverarea;
  88.    float dady = da21 * info->dy * info->oneoverarea;
  89.  
  90.    info->dadx[slot][i] = dadx;
  91.    info->dady[slot][i] = dady;  
  92.    
  93.    info->a0[slot][i] = (a1 -
  94.                               (dadx * (info->v1[0][0] - setup->pixel_offset) +
  95.                                dady * (info->v1[0][1] - setup->pixel_offset)));
  96. }
  97.  
  98.  
  99. /**
  100.  * Compute a0, dadx and dady for a perspective-corrected interpolant,
  101.  * for a triangle.
  102.  * We basically multiply the vertex value by 1/w before computing
  103.  * the plane coefficients (a0, dadx, dady).
  104.  * Later, when we compute the value at a particular fragment position we'll
  105.  * divide the interpolated value by the interpolated W at that fragment.
  106.  */
  107. static void perspective_coef( struct lp_setup_context *setup,
  108.                               struct lp_line_info *info,
  109.                               unsigned slot,
  110.                               unsigned vert_attr,
  111.                               unsigned i)
  112. {
  113.    /* premultiply by 1/w  (v[0][3] is always 1/w):
  114.     */
  115.    float a1 = info->v1[vert_attr][i] * info->v1[0][3];
  116.    float a2 = info->v2[vert_attr][i] * info->v2[0][3];
  117.  
  118.    float da21 = a1 - a2;  
  119.    float dadx = da21 * info->dx * info->oneoverarea;
  120.    float dady = da21 * info->dy * info->oneoverarea;
  121.  
  122.    info->dadx[slot][i] = dadx;
  123.    info->dady[slot][i] = dady;
  124.    
  125.    info->a0[slot][i] = (a1 -
  126.                         (dadx * (info->v1[0][0] - setup->pixel_offset) +
  127.                          dady * (info->v1[0][1] - setup->pixel_offset)));
  128. }
  129.  
  130. static void
  131. setup_fragcoord_coef( struct lp_setup_context *setup,
  132.                       struct lp_line_info *info,
  133.                       unsigned slot,
  134.                       unsigned usage_mask)
  135. {
  136.    /*X*/
  137.    if (usage_mask & TGSI_WRITEMASK_X) {
  138.       info->a0[slot][0] = 0.0;
  139.       info->dadx[slot][0] = 1.0;
  140.       info->dady[slot][0] = 0.0;
  141.    }
  142.  
  143.    /*Y*/
  144.    if (usage_mask & TGSI_WRITEMASK_Y) {
  145.       info->a0[slot][1] = 0.0;
  146.       info->dadx[slot][1] = 0.0;
  147.       info->dady[slot][1] = 1.0;
  148.    }
  149.  
  150.    /*Z*/
  151.    if (usage_mask & TGSI_WRITEMASK_Z) {
  152.       linear_coef(setup, info, slot, 0, 2);
  153.    }
  154.  
  155.    /*W*/
  156.    if (usage_mask & TGSI_WRITEMASK_W) {
  157.       linear_coef(setup, info, slot, 0, 3);
  158.    }
  159. }
  160.  
  161. /**
  162.  * Compute the tri->coef[] array dadx, dady, a0 values.
  163.  */
  164. static void setup_line_coefficients( struct lp_setup_context *setup,
  165.                                      struct lp_line_info *info)
  166. {
  167.    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
  168.    unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
  169.    unsigned slot;
  170.  
  171.    /* setup interpolation for all the remaining attributes:
  172.     */
  173.    for (slot = 0; slot < key->num_inputs; slot++) {
  174.       unsigned vert_attr = key->inputs[slot].src_index;
  175.       unsigned usage_mask = key->inputs[slot].usage_mask;
  176.       unsigned i;
  177.            
  178.       switch (key->inputs[slot].interp) {
  179.       case LP_INTERP_CONSTANT:
  180.          if (key->flatshade_first) {
  181.             for (i = 0; i < NUM_CHANNELS; i++)
  182.                if (usage_mask & (1 << i))
  183.                   constant_coef(setup, info, slot+1, info->v1[vert_attr][i], i);
  184.          }
  185.          else {
  186.             for (i = 0; i < NUM_CHANNELS; i++)
  187.                if (usage_mask & (1 << i))
  188.                   constant_coef(setup, info, slot+1, info->v2[vert_attr][i], i);
  189.          }
  190.          break;
  191.  
  192.       case LP_INTERP_LINEAR:
  193.          for (i = 0; i < NUM_CHANNELS; i++)
  194.             if (usage_mask & (1 << i))
  195.                linear_coef(setup, info, slot+1, vert_attr, i);
  196.          break;
  197.  
  198.       case LP_INTERP_PERSPECTIVE:
  199.          for (i = 0; i < NUM_CHANNELS; i++)
  200.             if (usage_mask & (1 << i))
  201.                perspective_coef(setup, info, slot+1, vert_attr, i);
  202.          fragcoord_usage_mask |= TGSI_WRITEMASK_W;
  203.          break;
  204.  
  205.       case LP_INTERP_POSITION:
  206.          /*
  207.           * The generated pixel interpolators will pick up the coeffs from
  208.           * slot 0, so all need to ensure that the usage mask is covers all
  209.           * usages.
  210.           */
  211.          fragcoord_usage_mask |= usage_mask;
  212.          break;
  213.  
  214.       case LP_INTERP_FACING:
  215.          for (i = 0; i < NUM_CHANNELS; i++)
  216.             if (usage_mask & (1 << i))
  217.                constant_coef(setup, info, slot+1, 1.0, i);
  218.          break;
  219.  
  220.       default:
  221.          assert(0);
  222.       }
  223.    }
  224.  
  225.    /* The internal position input is in slot zero:
  226.     */
  227.    setup_fragcoord_coef(setup, info, 0,
  228.                         fragcoord_usage_mask);
  229. }
  230.  
  231.  
  232.  
  233. static INLINE int subpixel_snap( float a )
  234. {
  235.    return util_iround(FIXED_ONE * a);
  236. }
  237.  
  238.  
  239. /**
  240.  * Print line vertex attribs (for debug).
  241.  */
  242. static void
  243. print_line(struct lp_setup_context *setup,
  244.            const float (*v1)[4],
  245.            const float (*v2)[4])
  246. {
  247.    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
  248.    uint i;
  249.  
  250.    debug_printf("llvmpipe line\n");
  251.    for (i = 0; i < 1 + key->num_inputs; i++) {
  252.       debug_printf("  v1[%d]:  %f %f %f %f\n", i,
  253.                    v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
  254.    }
  255.    for (i = 0; i < 1 + key->num_inputs; i++) {
  256.       debug_printf("  v2[%d]:  %f %f %f %f\n", i,
  257.                    v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
  258.    }
  259. }
  260.  
  261.  
  262. static INLINE boolean sign(float x){
  263.    return x >= 0;  
  264. }  
  265.  
  266.  
  267. /* Used on positive floats only:
  268.  */
  269. static INLINE float fracf(float f)
  270. {
  271.    return f - floorf(f);
  272. }
  273.  
  274.  
  275.  
  276. static boolean
  277. try_setup_line( struct lp_setup_context *setup,
  278.                const float (*v1)[4],
  279.                const float (*v2)[4])
  280. {
  281.    struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe;
  282.    struct lp_scene *scene = setup->scene;
  283.    const struct lp_setup_variant_key *key = &setup->setup.variant->key;
  284.    struct lp_rast_triangle *line;
  285.    struct lp_rast_plane *plane;
  286.    struct lp_line_info info;
  287.    float width = MAX2(1.0, setup->line_width);
  288.    struct u_rect bbox;
  289.    unsigned tri_bytes;
  290.    int x[4];
  291.    int y[4];
  292.    int i;
  293.    int nr_planes = 4;
  294.    unsigned scissor_index = 0;
  295.    unsigned layer = 0;
  296.    
  297.    /* linewidth should be interpreted as integer */
  298.    int fixed_width = util_iround(width) * FIXED_ONE;
  299.  
  300.    float x_offset=0;
  301.    float y_offset=0;
  302.    float x_offset_end=0;
  303.    float y_offset_end=0;
  304.      
  305.    float x1diff;
  306.    float y1diff;
  307.    float x2diff;
  308.    float y2diff;
  309.    float dx, dy;
  310.    float area;
  311.  
  312.    boolean draw_start;
  313.    boolean draw_end;
  314.    boolean will_draw_start;
  315.    boolean will_draw_end;
  316.  
  317.    if (0)
  318.       print_line(setup, v1, v2);
  319.  
  320.    if (setup->scissor_test) {
  321.       nr_planes = 8;
  322.       if (setup->viewport_index_slot > 0) {
  323.          unsigned *udata = (unsigned*)v1[setup->viewport_index_slot];
  324.          scissor_index = lp_clamp_scissor_idx(*udata);
  325.       }
  326.    }
  327.    else {
  328.       nr_planes = 4;
  329.    }
  330.  
  331.    if (setup->layer_slot > 0) {
  332.       layer = *(unsigned*)v1[setup->layer_slot];
  333.       layer = MIN2(layer, scene->fb_max_layer);
  334.    }
  335.  
  336.    dx = v1[0][0] - v2[0][0];
  337.    dy = v1[0][1] - v2[0][1];
  338.    area = (dx * dx  + dy * dy);
  339.    if (area == 0) {
  340.       LP_COUNT(nr_culled_tris);
  341.       return TRUE;
  342.    }
  343.  
  344.    info.oneoverarea = 1.0f / area;
  345.    info.dx = dx;
  346.    info.dy = dy;
  347.    info.v1 = v1;
  348.    info.v2 = v2;
  349.  
  350.  
  351.    /* X-MAJOR LINE */
  352.    if (fabsf(dx) >= fabsf(dy)) {
  353.       float dydx = dy / dx;
  354.  
  355.       x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
  356.       y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
  357.       x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
  358.       y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
  359.  
  360.       if (y2diff==-0.5 && dy<0){
  361.          y2diff = 0.5;
  362.       }
  363.      
  364.       /*
  365.        * Diamond exit rule test for starting point
  366.        */    
  367.       if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
  368.          draw_start = TRUE;
  369.       }
  370.       else if (sign(x1diff) == sign(-dx)) {
  371.          draw_start = FALSE;
  372.       }
  373.       else if (sign(-y1diff) != sign(dy)) {
  374.          draw_start = TRUE;
  375.       }
  376.       else {
  377.          /* do intersection test */
  378.          float yintersect = fracf(v1[0][1]) + x1diff * dydx;
  379.          draw_start = (yintersect < 1.0 && yintersect > 0.0);
  380.       }
  381.  
  382.  
  383.       /*
  384.        * Diamond exit rule test for ending point
  385.        */    
  386.       if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
  387.          draw_end = FALSE;
  388.       }
  389.       else if (sign(x2diff) != sign(-dx)) {
  390.          draw_end = FALSE;
  391.       }
  392.       else if (sign(-y2diff) == sign(dy)) {
  393.          draw_end = TRUE;
  394.       }
  395.       else {
  396.          /* do intersection test */
  397.          float yintersect = fracf(v2[0][1]) + x2diff * dydx;
  398.          draw_end = (yintersect < 1.0 && yintersect > 0.0);
  399.       }
  400.  
  401.       /* Are we already drawing start/end?
  402.        */
  403.       will_draw_start = sign(-x1diff) != sign(dx);
  404.       will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
  405.  
  406.       if (dx < 0) {
  407.          /* if v2 is to the right of v1, swap pointers */
  408.          const float (*temp)[4] = v1;
  409.          v1 = v2;
  410.          v2 = temp;
  411.          dx = -dx;
  412.          dy = -dy;
  413.          /* Otherwise shift planes appropriately */
  414.          if (will_draw_start != draw_start) {
  415.             x_offset_end = - x1diff - 0.5;
  416.             y_offset_end = x_offset_end * dydx;
  417.  
  418.          }
  419.          if (will_draw_end != draw_end) {
  420.             x_offset = - x2diff - 0.5;
  421.             y_offset = x_offset * dydx;
  422.          }
  423.  
  424.       }
  425.       else{
  426.          /* Otherwise shift planes appropriately */
  427.          if (will_draw_start != draw_start) {
  428.             x_offset = - x1diff + 0.5;
  429.             y_offset = x_offset * dydx;
  430.          }
  431.          if (will_draw_end != draw_end) {
  432.             x_offset_end = - x2diff + 0.5;
  433.             y_offset_end = x_offset_end * dydx;
  434.          }
  435.       }
  436.  
  437.       /* x/y positions in fixed point */
  438.       x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
  439.       x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
  440.       x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset);
  441.       x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset);
  442.      
  443.       y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) - fixed_width/2;
  444.       y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) - fixed_width/2;
  445.       y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset) + fixed_width/2;
  446.       y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset) + fixed_width/2;
  447.      
  448.    }
  449.    else {
  450.       const float dxdy = dx / dy;
  451.  
  452.       /* Y-MAJOR LINE */      
  453.       x1diff = v1[0][0] - (float) floor(v1[0][0]) - 0.5;
  454.       y1diff = v1[0][1] - (float) floor(v1[0][1]) - 0.5;
  455.       x2diff = v2[0][0] - (float) floor(v2[0][0]) - 0.5;
  456.       y2diff = v2[0][1] - (float) floor(v2[0][1]) - 0.5;
  457.  
  458.       if (x2diff==-0.5 && dx<0) {
  459.          x2diff = 0.5;
  460.       }
  461.  
  462.       /*
  463.        * Diamond exit rule test for starting point
  464.        */    
  465.       if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
  466.          draw_start = TRUE;
  467.       }
  468.       else if (sign(-y1diff) == sign(dy)) {
  469.          draw_start = FALSE;
  470.       }
  471.       else if (sign(x1diff) != sign(-dx)) {
  472.          draw_start = TRUE;
  473.       }
  474.       else {
  475.          /* do intersection test */
  476.          float xintersect = fracf(v1[0][0]) + y1diff * dxdy;
  477.          draw_start = (xintersect < 1.0 && xintersect > 0.0);
  478.       }
  479.  
  480.       /*
  481.        * Diamond exit rule test for ending point
  482.        */    
  483.       if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
  484.          draw_end = FALSE;
  485.       }
  486.       else if (sign(-y2diff) != sign(dy) ) {
  487.          draw_end = FALSE;
  488.       }
  489.       else if (sign(x2diff) == sign(-dx) ) {
  490.          draw_end = TRUE;
  491.       }
  492.       else {
  493.          /* do intersection test */
  494.          float xintersect = fracf(v2[0][0]) + y2diff * dxdy;
  495.          draw_end = (xintersect < 1.0 && xintersect >= 0.0);
  496.       }
  497.  
  498.       /* Are we already drawing start/end?
  499.        */
  500.       will_draw_start = sign(y1diff) == sign(dy);
  501.       will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
  502.  
  503.       if (dy > 0) {
  504.          /* if v2 is on top of v1, swap pointers */
  505.          const float (*temp)[4] = v1;
  506.          v1 = v2;
  507.          v2 = temp;
  508.          dx = -dx;
  509.          dy = -dy;
  510.  
  511.          /* Otherwise shift planes appropriately */
  512.          if (will_draw_start != draw_start) {
  513.             y_offset_end = - y1diff + 0.5;
  514.             x_offset_end = y_offset_end * dxdy;
  515.          }
  516.          if (will_draw_end != draw_end) {
  517.             y_offset = - y2diff + 0.5;
  518.             x_offset = y_offset * dxdy;
  519.          }
  520.       }
  521.       else {
  522.          /* Otherwise shift planes appropriately */
  523.          if (will_draw_start != draw_start) {
  524.             y_offset = - y1diff - 0.5;
  525.             x_offset = y_offset * dxdy;
  526.                      
  527.          }
  528.          if (will_draw_end != draw_end) {
  529.             y_offset_end = - y2diff - 0.5;
  530.             x_offset_end = y_offset_end * dxdy;
  531.          }
  532.       }
  533.  
  534.       /* x/y positions in fixed point */
  535.       x[0] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) - fixed_width/2;
  536.       x[1] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) - fixed_width/2;
  537.       x[2] = subpixel_snap(v2[0][0] + x_offset_end - setup->pixel_offset) + fixed_width/2;
  538.       x[3] = subpixel_snap(v1[0][0] + x_offset     - setup->pixel_offset) + fixed_width/2;
  539.      
  540.       y[0] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset);
  541.       y[1] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
  542.       y[2] = subpixel_snap(v2[0][1] + y_offset_end - setup->pixel_offset);
  543.       y[3] = subpixel_snap(v1[0][1] + y_offset     - setup->pixel_offset);
  544.    }
  545.  
  546.    /* Bounding rectangle (in pixels) */
  547.    {
  548.       /* Yes this is necessary to accurately calculate bounding boxes
  549.        * with the two fill-conventions we support.  GL (normally) ends
  550.        * up needing a bottom-left fill convention, which requires
  551.        * slightly different rounding.
  552.        */
  553.       int adj = (setup->pixel_offset != 0) ? 1 : 0;
  554.  
  555.       bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
  556.       bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
  557.       bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
  558.       bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
  559.  
  560.       /* Inclusive coordinates:
  561.        */
  562.       bbox.x1--;
  563.       bbox.y1--;
  564.    }
  565.  
  566.    if (bbox.x1 < bbox.x0 ||
  567.        bbox.y1 < bbox.y0) {
  568.       if (0) debug_printf("empty bounding box\n");
  569.       LP_COUNT(nr_culled_tris);
  570.       return TRUE;
  571.    }
  572.  
  573.    if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
  574.       if (0) debug_printf("offscreen\n");
  575.       LP_COUNT(nr_culled_tris);
  576.       return TRUE;
  577.    }
  578.  
  579.    /* Can safely discard negative regions:
  580.     */
  581.    bbox.x0 = MAX2(bbox.x0, 0);
  582.    bbox.y0 = MAX2(bbox.y0, 0);
  583.  
  584.    line = lp_setup_alloc_triangle(scene,
  585.                                   key->num_inputs,
  586.                                   nr_planes,
  587.                                   &tri_bytes);
  588.    if (!line)
  589.       return FALSE;
  590.  
  591. #ifdef DEBUG
  592.    line->v[0][0] = v1[0][0];
  593.    line->v[1][0] = v2[0][0];  
  594.    line->v[0][1] = v1[0][1];
  595.    line->v[1][1] = v2[0][1];
  596. #endif
  597.  
  598.    LP_COUNT(nr_tris);
  599.  
  600.    if (lp_context->active_statistics_queries) {
  601.       lp_context->pipeline_statistics.c_primitives++;
  602.    }
  603.  
  604.    /* calculate the deltas */
  605.    plane = GET_PLANES(line);
  606.    plane[0].dcdy = x[0] - x[1];
  607.    plane[1].dcdy = x[1] - x[2];
  608.    plane[2].dcdy = x[2] - x[3];
  609.    plane[3].dcdy = x[3] - x[0];
  610.  
  611.    plane[0].dcdx = y[0] - y[1];
  612.    plane[1].dcdx = y[1] - y[2];
  613.    plane[2].dcdx = y[2] - y[3];
  614.    plane[3].dcdx = y[3] - y[0];
  615.  
  616.  
  617.    /* Setup parameter interpolants:
  618.     */
  619.    info.a0 = GET_A0(&line->inputs);
  620.    info.dadx = GET_DADX(&line->inputs);
  621.    info.dady = GET_DADY(&line->inputs);
  622.    setup_line_coefficients(setup, &info);
  623.  
  624.    line->inputs.frontfacing = TRUE;
  625.    line->inputs.disable = FALSE;
  626.    line->inputs.opaque = FALSE;
  627.    line->inputs.layer = layer;
  628.  
  629.    for (i = 0; i < 4; i++) {
  630.  
  631.       /* half-edge constants, will be interated over the whole render
  632.        * target.
  633.        */
  634.       plane[i].c = plane[i].dcdx * x[i] - plane[i].dcdy * y[i];
  635.  
  636.      
  637.       /* correct for top-left vs. bottom-left fill convention.  
  638.        */        
  639.       if (plane[i].dcdx < 0) {
  640.          /* both fill conventions want this - adjust for left edges */
  641.          plane[i].c++;            
  642.       }
  643.       else if (plane[i].dcdx == 0) {
  644.          if (setup->pixel_offset == 0) {
  645.             /* correct for top-left fill convention:
  646.              */
  647.             if (plane[i].dcdy > 0) plane[i].c++;
  648.          }
  649.          else {
  650.             /* correct for bottom-left fill convention:
  651.              */
  652.             if (plane[i].dcdy < 0) plane[i].c++;
  653.          }
  654.       }
  655.  
  656.       plane[i].dcdx *= FIXED_ONE;
  657.       plane[i].dcdy *= FIXED_ONE;
  658.  
  659.       /* find trivial reject offsets for each edge for a single-pixel
  660.        * sized block.  These will be scaled up at each recursive level to
  661.        * match the active blocksize.  Scaling in this way works best if
  662.        * the blocks are square.
  663.        */
  664.       plane[i].eo = 0;
  665.       if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx;
  666.       if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy;
  667.    }
  668.  
  669.  
  670.    /*
  671.     * When rasterizing scissored tris, use the intersection of the
  672.     * triangle bounding box and the scissor rect to generate the
  673.     * scissor planes.
  674.     *
  675.     * This permits us to cut off the triangle "tails" that are present
  676.     * in the intermediate recursive levels caused when two of the
  677.     * triangles edges don't diverge quickly enough to trivially reject
  678.     * exterior blocks from the triangle.
  679.     *
  680.     * It's not really clear if it's worth worrying about these tails,
  681.     * but since we generate the planes for each scissored tri, it's
  682.     * free to trim them in this case.
  683.     *
  684.     * Note that otherwise, the scissor planes only vary in 'C' value,
  685.     * and even then only on state-changes.  Could alternatively store
  686.     * these planes elsewhere.
  687.     */
  688.    if (nr_planes == 8) {
  689.       const struct u_rect *scissor =
  690.          &setup->scissors[scissor_index];
  691.  
  692.       plane[4].dcdx = -1;
  693.       plane[4].dcdy = 0;
  694.       plane[4].c = 1-scissor->x0;
  695.       plane[4].eo = 1;
  696.  
  697.       plane[5].dcdx = 1;
  698.       plane[5].dcdy = 0;
  699.       plane[5].c = scissor->x1+1;
  700.       plane[5].eo = 0;
  701.  
  702.       plane[6].dcdx = 0;
  703.       plane[6].dcdy = 1;
  704.       plane[6].c = 1-scissor->y0;
  705.       plane[6].eo = 1;
  706.  
  707.       plane[7].dcdx = 0;
  708.       plane[7].dcdy = -1;
  709.       plane[7].c = scissor->y1+1;
  710.       plane[7].eo = 0;
  711.    }
  712.  
  713.    return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index);
  714. }
  715.  
  716.  
  717. static void lp_setup_line( struct lp_setup_context *setup,
  718.                            const float (*v0)[4],
  719.                            const float (*v1)[4] )
  720. {
  721.    if (!try_setup_line( setup, v0, v1 ))
  722.    {
  723.       if (!lp_setup_flush_and_restart(setup))
  724.          return;
  725.  
  726.       if (!try_setup_line( setup, v0, v1 ))
  727.          return;
  728.    }
  729. }
  730.  
  731.  
  732. void lp_setup_choose_line( struct lp_setup_context *setup )
  733. {
  734.    setup->line = lp_setup_line;
  735. }
  736.  
  737.  
  738.