Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/llvmpipe/lp_setup_line.c
4570 views
1
/**************************************************************************
2
*
3
* Copyright 2007 VMware, Inc.
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 VMWARE 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
#include "draw/draw_context.h"
41
42
#define NUM_CHANNELS 4
43
44
struct lp_line_info {
45
46
float dx;
47
float dy;
48
float oneoverarea;
49
boolean frontfacing;
50
51
const float (*v1)[4];
52
const float (*v2)[4];
53
54
float (*a0)[4];
55
float (*dadx)[4];
56
float (*dady)[4];
57
};
58
59
60
/**
61
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
62
*/
63
static void constant_coef( struct lp_setup_context *setup,
64
struct lp_line_info *info,
65
unsigned slot,
66
const float value,
67
unsigned i )
68
{
69
info->a0[slot][i] = value;
70
info->dadx[slot][i] = 0.0f;
71
info->dady[slot][i] = 0.0f;
72
}
73
74
75
/**
76
* Compute a0, dadx and dady for a linearly interpolated coefficient,
77
* for a triangle.
78
*/
79
static void linear_coef( struct lp_setup_context *setup,
80
struct lp_line_info *info,
81
unsigned slot,
82
unsigned vert_attr,
83
unsigned i)
84
{
85
float a1 = info->v1[vert_attr][i];
86
float a2 = info->v2[vert_attr][i];
87
88
float da21 = a1 - a2;
89
float dadx = da21 * info->dx * info->oneoverarea;
90
float dady = da21 * info->dy * info->oneoverarea;
91
92
info->dadx[slot][i] = dadx;
93
info->dady[slot][i] = dady;
94
95
info->a0[slot][i] = (a1 -
96
(dadx * (info->v1[0][0] - setup->pixel_offset) +
97
dady * (info->v1[0][1] - setup->pixel_offset)));
98
}
99
100
101
/**
102
* Compute a0, dadx and dady for a perspective-corrected interpolant,
103
* for a triangle.
104
* We basically multiply the vertex value by 1/w before computing
105
* the plane coefficients (a0, dadx, dady).
106
* Later, when we compute the value at a particular fragment position we'll
107
* divide the interpolated value by the interpolated W at that fragment.
108
*/
109
static void perspective_coef( struct lp_setup_context *setup,
110
struct lp_line_info *info,
111
unsigned slot,
112
unsigned vert_attr,
113
unsigned i)
114
{
115
/* premultiply by 1/w (v[0][3] is always 1/w):
116
*/
117
float a1 = info->v1[vert_attr][i] * info->v1[0][3];
118
float a2 = info->v2[vert_attr][i] * info->v2[0][3];
119
120
float da21 = a1 - a2;
121
float dadx = da21 * info->dx * info->oneoverarea;
122
float dady = da21 * info->dy * info->oneoverarea;
123
124
info->dadx[slot][i] = dadx;
125
info->dady[slot][i] = dady;
126
127
info->a0[slot][i] = (a1 -
128
(dadx * (info->v1[0][0] - setup->pixel_offset) +
129
dady * (info->v1[0][1] - setup->pixel_offset)));
130
}
131
132
static void
133
setup_fragcoord_coef( struct lp_setup_context *setup,
134
struct lp_line_info *info,
135
unsigned slot,
136
unsigned usage_mask)
137
{
138
/*X*/
139
if (usage_mask & TGSI_WRITEMASK_X) {
140
info->a0[slot][0] = 0.0;
141
info->dadx[slot][0] = 1.0;
142
info->dady[slot][0] = 0.0;
143
}
144
145
/*Y*/
146
if (usage_mask & TGSI_WRITEMASK_Y) {
147
info->a0[slot][1] = 0.0;
148
info->dadx[slot][1] = 0.0;
149
info->dady[slot][1] = 1.0;
150
}
151
152
/*Z*/
153
if (usage_mask & TGSI_WRITEMASK_Z) {
154
linear_coef(setup, info, slot, 0, 2);
155
}
156
157
/*W*/
158
if (usage_mask & TGSI_WRITEMASK_W) {
159
linear_coef(setup, info, slot, 0, 3);
160
}
161
}
162
163
/**
164
* Compute the tri->coef[] array dadx, dady, a0 values.
165
*/
166
static void setup_line_coefficients( struct lp_setup_context *setup,
167
struct lp_line_info *info)
168
{
169
const struct lp_setup_variant_key *key = &setup->setup.variant->key;
170
unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
171
unsigned slot;
172
173
/* setup interpolation for all the remaining attributes:
174
*/
175
for (slot = 0; slot < key->num_inputs; slot++) {
176
unsigned vert_attr = key->inputs[slot].src_index;
177
unsigned usage_mask = key->inputs[slot].usage_mask;
178
unsigned i;
179
180
switch (key->inputs[slot].interp) {
181
case LP_INTERP_CONSTANT:
182
if (key->flatshade_first) {
183
for (i = 0; i < NUM_CHANNELS; i++)
184
if (usage_mask & (1 << i))
185
constant_coef(setup, info, slot+1, info->v1[vert_attr][i], i);
186
}
187
else {
188
for (i = 0; i < NUM_CHANNELS; i++)
189
if (usage_mask & (1 << i))
190
constant_coef(setup, info, slot+1, info->v2[vert_attr][i], i);
191
}
192
break;
193
194
case LP_INTERP_LINEAR:
195
for (i = 0; i < NUM_CHANNELS; i++)
196
if (usage_mask & (1 << i))
197
linear_coef(setup, info, slot+1, vert_attr, i);
198
break;
199
200
case LP_INTERP_PERSPECTIVE:
201
for (i = 0; i < NUM_CHANNELS; i++)
202
if (usage_mask & (1 << i))
203
perspective_coef(setup, info, slot+1, vert_attr, i);
204
fragcoord_usage_mask |= TGSI_WRITEMASK_W;
205
break;
206
207
case LP_INTERP_POSITION:
208
/*
209
* The generated pixel interpolators will pick up the coeffs from
210
* slot 0, so all need to ensure that the usage mask is covers all
211
* usages.
212
*/
213
fragcoord_usage_mask |= usage_mask;
214
break;
215
216
case LP_INTERP_FACING:
217
for (i = 0; i < NUM_CHANNELS; i++)
218
if (usage_mask & (1 << i))
219
constant_coef(setup, info, slot+1,
220
info->frontfacing ? 1.0f : -1.0f, i);
221
break;
222
223
default:
224
assert(0);
225
}
226
}
227
228
/* The internal position input is in slot zero:
229
*/
230
setup_fragcoord_coef(setup, info, 0,
231
fragcoord_usage_mask);
232
}
233
234
235
236
static inline int subpixel_snap( float a )
237
{
238
return util_iround(FIXED_ONE * a);
239
}
240
241
242
/**
243
* Print line vertex attribs (for debug).
244
*/
245
static void
246
print_line(struct lp_setup_context *setup,
247
const float (*v1)[4],
248
const float (*v2)[4])
249
{
250
const struct lp_setup_variant_key *key = &setup->setup.variant->key;
251
uint i;
252
253
debug_printf("llvmpipe line\n");
254
for (i = 0; i < 1 + key->num_inputs; i++) {
255
debug_printf(" v1[%d]: %f %f %f %f\n", i,
256
v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
257
}
258
for (i = 0; i < 1 + key->num_inputs; i++) {
259
debug_printf(" v2[%d]: %f %f %f %f\n", i,
260
v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
261
}
262
}
263
264
265
static inline boolean sign(float x){
266
return x >= 0;
267
}
268
269
270
/* Used on positive floats only:
271
*/
272
static inline float fracf(float f)
273
{
274
return f - floorf(f);
275
}
276
277
278
279
static boolean
280
try_setup_line( struct lp_setup_context *setup,
281
const float (*v1)[4],
282
const float (*v2)[4])
283
{
284
struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe;
285
struct lp_scene *scene = setup->scene;
286
const struct lp_setup_variant_key *key = &setup->setup.variant->key;
287
struct lp_rast_triangle *line;
288
struct lp_rast_plane *plane;
289
struct lp_line_info info;
290
float width = MAX2(1.0, setup->line_width);
291
const struct u_rect *scissor;
292
struct u_rect bbox, bboxpos;
293
boolean s_planes[4];
294
unsigned tri_bytes;
295
int x[4];
296
int y[4];
297
int i;
298
int nr_planes = 4;
299
unsigned viewport_index = 0;
300
unsigned layer = 0;
301
float pixel_offset = setup->multisample ? 0.0 : setup->pixel_offset;
302
/* linewidth should be interpreted as integer */
303
int fixed_width = util_iround(width) * FIXED_ONE;
304
305
float x_offset=0;
306
float y_offset=0;
307
float x_offset_end=0;
308
float y_offset_end=0;
309
310
float x1diff;
311
float y1diff;
312
float x2diff;
313
float y2diff;
314
float dx, dy;
315
float area;
316
const float (*pv)[4];
317
318
boolean draw_start;
319
boolean draw_end;
320
boolean will_draw_start;
321
boolean will_draw_end;
322
323
if (lp_context->active_statistics_queries) {
324
lp_context->pipeline_statistics.c_primitives++;
325
}
326
327
if (0)
328
print_line(setup, v1, v2);
329
330
if (setup->flatshade_first) {
331
pv = v1;
332
}
333
else {
334
pv = v2;
335
}
336
if (setup->viewport_index_slot > 0) {
337
unsigned *udata = (unsigned*)pv[setup->viewport_index_slot];
338
viewport_index = lp_clamp_viewport_idx(*udata);
339
}
340
if (setup->layer_slot > 0) {
341
layer = *(unsigned*)pv[setup->layer_slot];
342
layer = MIN2(layer, scene->fb_max_layer);
343
}
344
345
dx = v1[0][0] - v2[0][0];
346
dy = v1[0][1] - v2[0][1];
347
area = (dx * dx + dy * dy);
348
if (area == 0) {
349
LP_COUNT(nr_culled_tris);
350
return TRUE;
351
}
352
353
info.oneoverarea = 1.0f / area;
354
info.dx = dx;
355
info.dy = dy;
356
info.v1 = v1;
357
info.v2 = v2;
358
359
360
if (setup->rectangular_lines) {
361
float scale = (setup->line_width * 0.5f) / sqrtf(area);
362
int tx = subpixel_snap(-dy * scale);
363
int ty = subpixel_snap(+dx * scale);
364
365
x[0] = subpixel_snap(v1[0][0] - pixel_offset) - tx;
366
x[1] = subpixel_snap(v2[0][0] - pixel_offset) - tx;
367
x[2] = subpixel_snap(v2[0][0] - pixel_offset) + tx;
368
x[3] = subpixel_snap(v1[0][0] - pixel_offset) + tx;
369
370
y[0] = subpixel_snap(v1[0][1] - pixel_offset) - ty;
371
y[1] = subpixel_snap(v2[0][1] - pixel_offset) - ty;
372
y[2] = subpixel_snap(v2[0][1] - pixel_offset) + ty;
373
y[3] = subpixel_snap(v1[0][1] - pixel_offset) + ty;
374
} else if (fabsf(dx) >= fabsf(dy)) {
375
float dydx = dy / dx;
376
377
/* X-MAJOR LINE */
378
x1diff = v1[0][0] - floorf(v1[0][0]) - 0.5f;
379
y1diff = v1[0][1] - floorf(v1[0][1]) - 0.5f;
380
x2diff = v2[0][0] - floorf(v2[0][0]) - 0.5f;
381
y2diff = v2[0][1] - floorf(v2[0][1]) - 0.5f;
382
383
if (y2diff==-0.5 && dy<0){
384
y2diff = 0.5;
385
}
386
387
/*
388
* Diamond exit rule test for starting point
389
*/
390
if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
391
draw_start = TRUE;
392
}
393
else if (sign(x1diff) == sign(-dx)) {
394
draw_start = FALSE;
395
}
396
else if (sign(-y1diff) != sign(dy)) {
397
draw_start = TRUE;
398
}
399
else {
400
/* do intersection test */
401
float yintersect = fracf(v1[0][1]) + x1diff * dydx;
402
draw_start = (yintersect < 1.0 && yintersect > 0.0);
403
}
404
405
406
/*
407
* Diamond exit rule test for ending point
408
*/
409
if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
410
draw_end = FALSE;
411
}
412
else if (sign(x2diff) != sign(-dx)) {
413
draw_end = FALSE;
414
}
415
else if (sign(-y2diff) == sign(dy)) {
416
draw_end = TRUE;
417
}
418
else {
419
/* do intersection test */
420
float yintersect = fracf(v2[0][1]) + x2diff * dydx;
421
draw_end = (yintersect < 1.0 && yintersect > 0.0);
422
}
423
424
/* Are we already drawing start/end?
425
*/
426
will_draw_start = sign(-x1diff) != sign(dx);
427
will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
428
429
if (dx < 0) {
430
/* if v2 is to the right of v1, swap pointers */
431
const float (*temp)[4] = v1;
432
v1 = v2;
433
v2 = temp;
434
dx = -dx;
435
dy = -dy;
436
/* Otherwise shift planes appropriately */
437
if (will_draw_start != draw_start) {
438
x_offset_end = - x1diff - 0.5;
439
y_offset_end = x_offset_end * dydx;
440
441
}
442
if (will_draw_end != draw_end) {
443
x_offset = - x2diff - 0.5;
444
y_offset = x_offset * dydx;
445
}
446
447
}
448
else{
449
/* Otherwise shift planes appropriately */
450
if (will_draw_start != draw_start) {
451
x_offset = - x1diff + 0.5;
452
y_offset = x_offset * dydx;
453
}
454
if (will_draw_end != draw_end) {
455
x_offset_end = - x2diff + 0.5;
456
y_offset_end = x_offset_end * dydx;
457
}
458
}
459
460
/* x/y positions in fixed point */
461
x[0] = subpixel_snap(v1[0][0] + x_offset - pixel_offset);
462
x[1] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset);
463
x[2] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset);
464
x[3] = subpixel_snap(v1[0][0] + x_offset - pixel_offset);
465
466
y[0] = subpixel_snap(v1[0][1] + y_offset - pixel_offset) - fixed_width/2;
467
y[1] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset) - fixed_width/2;
468
y[2] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset) + fixed_width/2;
469
y[3] = subpixel_snap(v1[0][1] + y_offset - pixel_offset) + fixed_width/2;
470
471
}
472
else {
473
const float dxdy = dx / dy;
474
475
/* Y-MAJOR LINE */
476
x1diff = v1[0][0] - floorf(v1[0][0]) - 0.5f;
477
y1diff = v1[0][1] - floorf(v1[0][1]) - 0.5f;
478
x2diff = v2[0][0] - floorf(v2[0][0]) - 0.5f;
479
y2diff = v2[0][1] - floorf(v2[0][1]) - 0.5f;
480
481
if (x2diff==-0.5 && dx<0) {
482
x2diff = 0.5;
483
}
484
485
/*
486
* Diamond exit rule test for starting point
487
*/
488
if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
489
draw_start = TRUE;
490
}
491
else if (sign(-y1diff) == sign(dy)) {
492
draw_start = FALSE;
493
}
494
else if (sign(x1diff) != sign(-dx)) {
495
draw_start = TRUE;
496
}
497
else {
498
/* do intersection test */
499
float xintersect = fracf(v1[0][0]) + y1diff * dxdy;
500
draw_start = (xintersect < 1.0 && xintersect > 0.0);
501
}
502
503
/*
504
* Diamond exit rule test for ending point
505
*/
506
if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
507
draw_end = FALSE;
508
}
509
else if (sign(-y2diff) != sign(dy) ) {
510
draw_end = FALSE;
511
}
512
else if (sign(x2diff) == sign(-dx) ) {
513
draw_end = TRUE;
514
}
515
else {
516
/* do intersection test */
517
float xintersect = fracf(v2[0][0]) + y2diff * dxdy;
518
draw_end = (xintersect < 1.0 && xintersect >= 0.0);
519
}
520
521
/* Are we already drawing start/end?
522
*/
523
will_draw_start = sign(y1diff) == sign(dy);
524
will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
525
526
if (dy > 0) {
527
/* if v2 is on top of v1, swap pointers */
528
const float (*temp)[4] = v1;
529
v1 = v2;
530
v2 = temp;
531
dx = -dx;
532
dy = -dy;
533
534
/* Otherwise shift planes appropriately */
535
if (will_draw_start != draw_start) {
536
y_offset_end = - y1diff + 0.5;
537
x_offset_end = y_offset_end * dxdy;
538
}
539
if (will_draw_end != draw_end) {
540
y_offset = - y2diff + 0.5;
541
x_offset = y_offset * dxdy;
542
}
543
}
544
else {
545
/* Otherwise shift planes appropriately */
546
if (will_draw_start != draw_start) {
547
y_offset = - y1diff - 0.5;
548
x_offset = y_offset * dxdy;
549
550
}
551
if (will_draw_end != draw_end) {
552
y_offset_end = - y2diff - 0.5;
553
x_offset_end = y_offset_end * dxdy;
554
}
555
}
556
557
/* x/y positions in fixed point */
558
x[0] = subpixel_snap(v1[0][0] + x_offset - pixel_offset) - fixed_width/2;
559
x[1] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset) - fixed_width/2;
560
x[2] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset) + fixed_width/2;
561
x[3] = subpixel_snap(v1[0][0] + x_offset - pixel_offset) + fixed_width/2;
562
563
y[0] = subpixel_snap(v1[0][1] + y_offset - pixel_offset);
564
y[1] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset);
565
y[2] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset);
566
y[3] = subpixel_snap(v1[0][1] + y_offset - pixel_offset);
567
}
568
569
/* Bounding rectangle (in pixels) */
570
{
571
/* Yes this is necessary to accurately calculate bounding boxes
572
* with the two fill-conventions we support. GL (normally) ends
573
* up needing a bottom-left fill convention, which requires
574
* slightly different rounding.
575
*/
576
int adj = (setup->bottom_edge_rule != 0) ? 1 : 0;
577
578
bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
579
bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
580
bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
581
bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
582
583
/* Inclusive coordinates:
584
*/
585
bbox.x1--;
586
bbox.y1--;
587
}
588
589
if (bbox.x1 < bbox.x0 ||
590
bbox.y1 < bbox.y0) {
591
if (0) debug_printf("empty bounding box\n");
592
LP_COUNT(nr_culled_tris);
593
return TRUE;
594
}
595
596
if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
597
if (0) debug_printf("offscreen\n");
598
LP_COUNT(nr_culled_tris);
599
return TRUE;
600
}
601
602
bboxpos = bbox;
603
604
/* Can safely discard negative regions:
605
*/
606
bboxpos.x0 = MAX2(bboxpos.x0, 0);
607
bboxpos.y0 = MAX2(bboxpos.y0, 0);
608
609
nr_planes = 4;
610
/*
611
* Determine how many scissor planes we need, that is drop scissor
612
* edges if the bounding box of the tri is fully inside that edge.
613
*/
614
scissor = &setup->draw_regions[viewport_index];
615
scissor_planes_needed(s_planes, &bboxpos, scissor);
616
nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3];
617
618
line = lp_setup_alloc_triangle(scene,
619
key->num_inputs,
620
nr_planes,
621
&tri_bytes);
622
if (!line)
623
return FALSE;
624
625
#ifdef DEBUG
626
line->v[0][0] = v1[0][0];
627
line->v[1][0] = v2[0][0];
628
line->v[0][1] = v1[0][1];
629
line->v[1][1] = v2[0][1];
630
#endif
631
632
LP_COUNT(nr_tris);
633
634
/* calculate the deltas */
635
plane = GET_PLANES(line);
636
plane[0].dcdy = x[0] - x[1];
637
plane[1].dcdy = x[1] - x[2];
638
plane[2].dcdy = x[2] - x[3];
639
plane[3].dcdy = x[3] - x[0];
640
641
plane[0].dcdx = y[0] - y[1];
642
plane[1].dcdx = y[1] - y[2];
643
plane[2].dcdx = y[2] - y[3];
644
plane[3].dcdx = y[3] - y[0];
645
646
if (draw_will_inject_frontface(lp_context->draw) &&
647
setup->face_slot > 0) {
648
line->inputs.frontfacing = v1[setup->face_slot][0];
649
} else {
650
line->inputs.frontfacing = TRUE;
651
}
652
653
/* Setup parameter interpolants:
654
*/
655
info.a0 = GET_A0(&line->inputs);
656
info.dadx = GET_DADX(&line->inputs);
657
info.dady = GET_DADY(&line->inputs);
658
info.frontfacing = line->inputs.frontfacing;
659
setup_line_coefficients(setup, &info);
660
661
line->inputs.disable = FALSE;
662
line->inputs.opaque = FALSE;
663
line->inputs.layer = layer;
664
line->inputs.viewport_index = viewport_index;
665
line->inputs.view_index = setup->view_index;
666
667
/*
668
* XXX: this code is mostly identical to the one in lp_setup_tri, except it
669
* uses 4 planes instead of 3. Could share the code (including the sse
670
* assembly, in fact we'd get the 4th plane for free).
671
* The only difference apart from storing the 4th plane would be some
672
* different shuffle for calculating dcdx/dcdy.
673
*/
674
for (i = 0; i < 4; i++) {
675
676
/* half-edge constants, will be iterated over the whole render
677
* target.
678
*/
679
plane[i].c = IMUL64(plane[i].dcdx, x[i]) - IMUL64(plane[i].dcdy, y[i]);
680
681
/* correct for top-left vs. bottom-left fill convention.
682
*/
683
if (plane[i].dcdx < 0) {
684
/* both fill conventions want this - adjust for left edges */
685
plane[i].c++;
686
}
687
else if (plane[i].dcdx == 0) {
688
if (setup->bottom_edge_rule == 0) {
689
/* correct for top-left fill convention:
690
*/
691
if (plane[i].dcdy > 0) plane[i].c++;
692
}
693
else {
694
/* correct for bottom-left fill convention:
695
*/
696
if (plane[i].dcdy < 0) plane[i].c++;
697
}
698
}
699
700
plane[i].dcdx *= FIXED_ONE;
701
plane[i].dcdy *= FIXED_ONE;
702
703
/* find trivial reject offsets for each edge for a single-pixel
704
* sized block. These will be scaled up at each recursive level to
705
* match the active blocksize. Scaling in this way works best if
706
* the blocks are square.
707
*/
708
plane[i].eo = 0;
709
if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx;
710
if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy;
711
}
712
713
714
/*
715
* When rasterizing scissored tris, use the intersection of the
716
* triangle bounding box and the scissor rect to generate the
717
* scissor planes.
718
*
719
* This permits us to cut off the triangle "tails" that are present
720
* in the intermediate recursive levels caused when two of the
721
* triangles edges don't diverge quickly enough to trivially reject
722
* exterior blocks from the triangle.
723
*
724
* It's not really clear if it's worth worrying about these tails,
725
* but since we generate the planes for each scissored tri, it's
726
* free to trim them in this case.
727
*
728
* Note that otherwise, the scissor planes only vary in 'C' value,
729
* and even then only on state-changes. Could alternatively store
730
* these planes elsewhere.
731
* (Or only store the c value together with a bit indicating which
732
* scissor edge this is, so rasterization would treat them differently
733
* (easier to evaluate) to ordinary planes.)
734
*/
735
if (nr_planes > 4) {
736
struct lp_rast_plane *plane_s = &plane[4];
737
738
if (s_planes[0]) {
739
plane_s->dcdx = ~0U << 8;
740
plane_s->dcdy = 0;
741
plane_s->c = (1-scissor->x0) << 8;
742
plane_s->eo = 1 << 8;
743
plane_s++;
744
}
745
if (s_planes[1]) {
746
plane_s->dcdx = 1 << 8;
747
plane_s->dcdy = 0;
748
plane_s->c = (scissor->x1+1) << 8;
749
plane_s->eo = 0 << 8;
750
plane_s++;
751
}
752
if (s_planes[2]) {
753
plane_s->dcdx = 0;
754
plane_s->dcdy = 1 << 8;
755
plane_s->c = (1-scissor->y0) << 8;
756
plane_s->eo = 1 << 8;
757
plane_s++;
758
}
759
if (s_planes[3]) {
760
plane_s->dcdx = 0;
761
plane_s->dcdy = ~0U << 8;
762
plane_s->c = (scissor->y1+1) << 8;
763
plane_s->eo = 0;
764
plane_s++;
765
}
766
assert(plane_s == &plane[nr_planes]);
767
}
768
769
return lp_setup_bin_triangle(setup, line, &bbox, &bboxpos, nr_planes, viewport_index);
770
}
771
772
773
static void lp_setup_line_discard(struct lp_setup_context *setup,
774
const float (*v0)[4],
775
const float (*v1)[4])
776
{
777
}
778
779
static void lp_setup_line(struct lp_setup_context *setup,
780
const float (*v0)[4],
781
const float (*v1)[4])
782
{
783
if (!try_setup_line(setup, v0, v1)) {
784
if (!lp_setup_flush_and_restart(setup))
785
return;
786
787
if (!try_setup_line(setup, v0, v1))
788
return;
789
}
790
}
791
792
793
void lp_setup_choose_line(struct lp_setup_context *setup)
794
{
795
if (setup->rasterizer_discard) {
796
setup->line = lp_setup_line_discard;
797
} else {
798
setup->line = lp_setup_line;
799
}
800
}
801
802
803
804