~ubuntu-branches/ubuntu/natty/mesa/natty-proposed

« back to all changes in this revision

Viewing changes to src/gallium/drivers/llvmpipe/lp_setup_line.c

  • Committer: Bazaar Package Importer
  • Author(s): Robert Hooker, Robert Hooker, Christopher James Halse Rogers
  • Date: 2010-09-14 08:55:40 UTC
  • mfrom: (1.2.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20100914085540-m4fpl0hdjlfd4jgz
Tags: 7.9~git20100909-0ubuntu1
[ Robert Hooker ]
* New upstream git snapshot up to commit 94118fe2d4b1e5 (LP: #631413)
* New features include ATI HD5xxx series support in r600, and a vastly
  improved glsl compiler.
* Remove pre-generated .pc's, use the ones generated at build time
  instead.
* Remove all references to mesa-utils now that its no longer shipped
  with the mesa source.
* Disable the experimental ARB_fragment_shader option by default on
  i915, it exposes incomplete functionality that breaks KDE compositing
  among other things. It can be enabled via driconf still. (LP: #628930).

[ Christopher James Halse Rogers ]
* debian/patches/04_osmesa_version.diff:
  - Refresh for new upstream
* Bugs fixed in this release:
  - Fixes severe rendering corruption in Unity on radeon (LP: #628727,
    LP: #596292, LP: #599741, LP: #630315, LP: #613694, LP: #599741).
  - Also fixes rendering in gnome-shell (LP: #578619).
  - Flickering in OpenGL apps on radeon (LP: #626943, LP: #610541).
  - Provides preliminary support for new intel chips (LP: #601052).
* debian/rules:
  - Update configure flags to match upstream reshuffling.
  - Explicitly remove gallium DRI drivers that we don't want to ship.
* Update debian/gbp.conf for this Maverick-specific packaging
* libegl1-mesa-dri-x11,kms: There are no longer separate kms or x11 drivers
  for EGL, libegl1-mesa-drivers now contains a single driver that provides
  both backends.

Show diffs side-by-side

added added

removed removed

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