Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/softpipe/sp_setup.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
* \brief Primitive rasterization/rendering (points, lines, triangles)
30
*
31
* \author Keith Whitwell <[email protected]>
32
* \author Brian Paul
33
*/
34
35
#include "sp_context.h"
36
#include "sp_screen.h"
37
#include "sp_quad.h"
38
#include "sp_quad_pipe.h"
39
#include "sp_setup.h"
40
#include "sp_state.h"
41
#include "draw/draw_context.h"
42
#include "pipe/p_shader_tokens.h"
43
#include "util/u_math.h"
44
#include "util/u_memory.h"
45
46
47
#define DEBUG_VERTS 0
48
#define DEBUG_FRAGS 0
49
50
51
/**
52
* Triangle edge info
53
*/
54
struct edge {
55
float dx; /**< X(v1) - X(v0), used only during setup */
56
float dy; /**< Y(v1) - Y(v0), used only during setup */
57
float dxdy; /**< dx/dy */
58
float sx, sy; /**< first sample point coord */
59
int lines; /**< number of lines on this edge */
60
};
61
62
63
/**
64
* Max number of quads (2x2 pixel blocks) to process per batch.
65
* This can't be arbitrarily increased since we depend on some 32-bit
66
* bitmasks (two bits per quad).
67
*/
68
#define MAX_QUADS 16
69
70
71
/**
72
* Triangle setup info.
73
* Also used for line drawing (taking some liberties).
74
*/
75
struct setup_context {
76
struct softpipe_context *softpipe;
77
78
/* Vertices are just an array of floats making up each attribute in
79
* turn. Currently fixed at 4 floats, but should change in time.
80
* Codegen will help cope with this.
81
*/
82
const float (*vmax)[4];
83
const float (*vmid)[4];
84
const float (*vmin)[4];
85
const float (*vprovoke)[4];
86
87
struct edge ebot;
88
struct edge etop;
89
struct edge emaj;
90
91
float oneoverarea;
92
int facing;
93
94
float pixel_offset;
95
unsigned max_layer;
96
97
struct quad_header quad[MAX_QUADS];
98
struct quad_header *quad_ptrs[MAX_QUADS];
99
unsigned count;
100
101
struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
102
struct tgsi_interp_coef posCoef; /* For Z, W */
103
104
struct {
105
int left[2]; /**< [0] = row0, [1] = row1 */
106
int right[2];
107
int y;
108
} span;
109
110
#if DEBUG_FRAGS
111
uint numFragsEmitted; /**< per primitive */
112
uint numFragsWritten; /**< per primitive */
113
#endif
114
115
unsigned cull_face; /* which faces cull */
116
unsigned nr_vertex_attrs;
117
};
118
119
120
121
122
123
124
125
/**
126
* Clip setup->quad against the scissor/surface bounds.
127
*/
128
static inline void
129
quad_clip(struct setup_context *setup, struct quad_header *quad)
130
{
131
unsigned viewport_index = quad[0].input.viewport_index;
132
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index];
133
const int minx = (int) cliprect->minx;
134
const int maxx = (int) cliprect->maxx;
135
const int miny = (int) cliprect->miny;
136
const int maxy = (int) cliprect->maxy;
137
138
if (quad->input.x0 >= maxx ||
139
quad->input.y0 >= maxy ||
140
quad->input.x0 + 1 < minx ||
141
quad->input.y0 + 1 < miny) {
142
/* totally clipped */
143
quad->inout.mask = 0x0;
144
return;
145
}
146
if (quad->input.x0 < minx)
147
quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
148
if (quad->input.y0 < miny)
149
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
150
if (quad->input.x0 == maxx - 1)
151
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
152
if (quad->input.y0 == maxy - 1)
153
quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
154
}
155
156
157
/**
158
* Emit a quad (pass to next stage) with clipping.
159
*/
160
static inline void
161
clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
162
{
163
quad_clip(setup, quad);
164
165
if (quad->inout.mask) {
166
struct softpipe_context *sp = setup->softpipe;
167
168
#if DEBUG_FRAGS
169
setup->numFragsEmitted += util_bitcount(quad->inout.mask);
170
#endif
171
172
sp->quad.first->run( sp->quad.first, &quad, 1 );
173
}
174
}
175
176
177
178
/**
179
* Given an X or Y coordinate, return the block/quad coordinate that it
180
* belongs to.
181
*/
182
static inline int
183
block(int x)
184
{
185
return x & ~(2-1);
186
}
187
188
189
static inline int
190
block_x(int x)
191
{
192
return x & ~(16-1);
193
}
194
195
196
/**
197
* Render a horizontal span of quads
198
*/
199
static void
200
flush_spans(struct setup_context *setup)
201
{
202
const int step = MAX_QUADS;
203
const int xleft0 = setup->span.left[0];
204
const int xleft1 = setup->span.left[1];
205
const int xright0 = setup->span.right[0];
206
const int xright1 = setup->span.right[1];
207
struct quad_stage *pipe = setup->softpipe->quad.first;
208
209
const int minleft = block_x(MIN2(xleft0, xleft1));
210
const int maxright = MAX2(xright0, xright1);
211
int x;
212
213
/* process quads in horizontal chunks of 16 */
214
for (x = minleft; x < maxright; x += step) {
215
unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
216
unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
217
unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
218
unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
219
unsigned lx = x;
220
unsigned q = 0;
221
222
unsigned skipmask_left0 = (1U << skip_left0) - 1U;
223
unsigned skipmask_left1 = (1U << skip_left1) - 1U;
224
225
/* These calculations fail when step == 32 and skip_right == 0.
226
*/
227
unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
228
unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
229
230
unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
231
unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
232
233
if (mask0 | mask1) {
234
do {
235
unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
236
if (quadmask) {
237
setup->quad[q].input.x0 = lx;
238
setup->quad[q].input.y0 = setup->span.y;
239
setup->quad[q].input.facing = setup->facing;
240
setup->quad[q].inout.mask = quadmask;
241
setup->quad_ptrs[q] = &setup->quad[q];
242
q++;
243
#if DEBUG_FRAGS
244
setup->numFragsEmitted += util_bitcount(quadmask);
245
#endif
246
}
247
mask0 >>= 2;
248
mask1 >>= 2;
249
lx += 2;
250
} while (mask0 | mask1);
251
252
pipe->run( pipe, setup->quad_ptrs, q );
253
}
254
}
255
256
257
setup->span.y = 0;
258
setup->span.right[0] = 0;
259
setup->span.right[1] = 0;
260
setup->span.left[0] = 1000000; /* greater than right[0] */
261
setup->span.left[1] = 1000000; /* greater than right[1] */
262
}
263
264
265
#if DEBUG_VERTS
266
static void
267
print_vertex(const struct setup_context *setup,
268
const float (*v)[4])
269
{
270
int i;
271
debug_printf(" Vertex: (%p)\n", (void *) v);
272
for (i = 0; i < setup->nr_vertex_attrs; i++) {
273
debug_printf(" %d: %f %f %f %f\n", i,
274
v[i][0], v[i][1], v[i][2], v[i][3]);
275
if (util_is_inf_or_nan(v[i][0])) {
276
debug_printf(" NaN!\n");
277
}
278
}
279
}
280
#endif
281
282
283
/**
284
* Sort the vertices from top to bottom order, setting up the triangle
285
* edge fields (ebot, emaj, etop).
286
* \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
287
*/
288
static boolean
289
setup_sort_vertices(struct setup_context *setup,
290
float det,
291
const float (*v0)[4],
292
const float (*v1)[4],
293
const float (*v2)[4])
294
{
295
if (setup->softpipe->rasterizer->flatshade_first)
296
setup->vprovoke = v0;
297
else
298
setup->vprovoke = v2;
299
300
/* determine bottom to top order of vertices */
301
{
302
float y0 = v0[0][1];
303
float y1 = v1[0][1];
304
float y2 = v2[0][1];
305
if (y0 <= y1) {
306
if (y1 <= y2) {
307
/* y0<=y1<=y2 */
308
setup->vmin = v0;
309
setup->vmid = v1;
310
setup->vmax = v2;
311
}
312
else if (y2 <= y0) {
313
/* y2<=y0<=y1 */
314
setup->vmin = v2;
315
setup->vmid = v0;
316
setup->vmax = v1;
317
}
318
else {
319
/* y0<=y2<=y1 */
320
setup->vmin = v0;
321
setup->vmid = v2;
322
setup->vmax = v1;
323
}
324
}
325
else {
326
if (y0 <= y2) {
327
/* y1<=y0<=y2 */
328
setup->vmin = v1;
329
setup->vmid = v0;
330
setup->vmax = v2;
331
}
332
else if (y2 <= y1) {
333
/* y2<=y1<=y0 */
334
setup->vmin = v2;
335
setup->vmid = v1;
336
setup->vmax = v0;
337
}
338
else {
339
/* y1<=y2<=y0 */
340
setup->vmin = v1;
341
setup->vmid = v2;
342
setup->vmax = v0;
343
}
344
}
345
}
346
347
setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
348
setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
349
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
350
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
351
setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
352
setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
353
354
/*
355
* Compute triangle's area. Use 1/area to compute partial
356
* derivatives of attributes later.
357
*
358
* The area will be the same as prim->det, but the sign may be
359
* different depending on how the vertices get sorted above.
360
*
361
* To determine whether the primitive is front or back facing we
362
* use the prim->det value because its sign is correct.
363
*/
364
{
365
const float area = (setup->emaj.dx * setup->ebot.dy -
366
setup->ebot.dx * setup->emaj.dy);
367
368
setup->oneoverarea = 1.0f / area;
369
370
/*
371
debug_printf("%s one-over-area %f area %f det %f\n",
372
__FUNCTION__, setup->oneoverarea, area, det );
373
*/
374
if (util_is_inf_or_nan(setup->oneoverarea))
375
return FALSE;
376
}
377
378
/* We need to know if this is a front or back-facing triangle for:
379
* - the GLSL gl_FrontFacing fragment attribute (bool)
380
* - two-sided stencil test
381
* 0 = front-facing, 1 = back-facing
382
*/
383
setup->facing =
384
((det < 0.0) ^
385
(setup->softpipe->rasterizer->front_ccw));
386
387
{
388
unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK;
389
390
if (face & setup->cull_face)
391
return FALSE;
392
}
393
394
return TRUE;
395
}
396
397
398
/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
399
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
400
* Some combinations of coordinates produce invalid results,
401
* but this behaviour is acceptable.
402
*/
403
static void
404
tri_apply_cylindrical_wrap(float v0,
405
float v1,
406
float v2,
407
uint cylindrical_wrap,
408
float output[3])
409
{
410
if (cylindrical_wrap) {
411
float delta;
412
413
delta = v1 - v0;
414
if (delta > 0.5f) {
415
v0 += 1.0f;
416
}
417
else if (delta < -0.5f) {
418
v1 += 1.0f;
419
}
420
421
delta = v2 - v1;
422
if (delta > 0.5f) {
423
v1 += 1.0f;
424
}
425
else if (delta < -0.5f) {
426
v2 += 1.0f;
427
}
428
429
delta = v0 - v2;
430
if (delta > 0.5f) {
431
v2 += 1.0f;
432
}
433
else if (delta < -0.5f) {
434
v0 += 1.0f;
435
}
436
}
437
438
output[0] = v0;
439
output[1] = v1;
440
output[2] = v2;
441
}
442
443
444
/**
445
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
446
* The value value comes from vertex[slot][i].
447
* The result will be put into setup->coef[slot].a0[i].
448
* \param slot which attribute slot
449
* \param i which component of the slot (0..3)
450
*/
451
static void
452
const_coeff(struct setup_context *setup,
453
struct tgsi_interp_coef *coef,
454
uint vertSlot, uint i)
455
{
456
assert(i <= 3);
457
458
coef->dadx[i] = 0;
459
coef->dady[i] = 0;
460
461
/* need provoking vertex info!
462
*/
463
coef->a0[i] = setup->vprovoke[vertSlot][i];
464
}
465
466
467
/**
468
* Compute a0, dadx and dady for a linearly interpolated coefficient,
469
* for a triangle.
470
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
471
*/
472
static void
473
tri_linear_coeff(struct setup_context *setup,
474
struct tgsi_interp_coef *coef,
475
uint i,
476
const float v[3])
477
{
478
float botda = v[1] - v[0];
479
float majda = v[2] - v[0];
480
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
481
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
482
float dadx = a * setup->oneoverarea;
483
float dady = b * setup->oneoverarea;
484
485
assert(i <= 3);
486
487
coef->dadx[i] = dadx;
488
coef->dady[i] = dady;
489
490
/* calculate a0 as the value which would be sampled for the
491
* fragment at (0,0), taking into account that we want to sample at
492
* pixel centers, in other words (pixel_offset, pixel_offset).
493
*
494
* this is neat but unfortunately not a good way to do things for
495
* triangles with very large values of dadx or dady as it will
496
* result in the subtraction and re-addition from a0 of a very
497
* large number, which means we'll end up loosing a lot of the
498
* fractional bits and precision from a0. the way to fix this is
499
* to define a0 as the sample at a pixel center somewhere near vmin
500
* instead - i'll switch to this later.
501
*/
502
coef->a0[i] = (v[0] -
503
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
504
dady * (setup->vmin[0][1] - setup->pixel_offset)));
505
}
506
507
508
/**
509
* Compute a0, dadx and dady for a perspective-corrected interpolant,
510
* for a triangle.
511
* We basically multiply the vertex value by 1/w before computing
512
* the plane coefficients (a0, dadx, dady).
513
* Later, when we compute the value at a particular fragment position we'll
514
* divide the interpolated value by the interpolated W at that fragment.
515
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
516
*/
517
static void
518
tri_persp_coeff(struct setup_context *setup,
519
struct tgsi_interp_coef *coef,
520
uint i,
521
const float v[3])
522
{
523
/* premultiply by 1/w (v[0][3] is always W):
524
*/
525
float mina = v[0] * setup->vmin[0][3];
526
float mida = v[1] * setup->vmid[0][3];
527
float maxa = v[2] * setup->vmax[0][3];
528
float botda = mida - mina;
529
float majda = maxa - mina;
530
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
531
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
532
float dadx = a * setup->oneoverarea;
533
float dady = b * setup->oneoverarea;
534
535
assert(i <= 3);
536
537
coef->dadx[i] = dadx;
538
coef->dady[i] = dady;
539
coef->a0[i] = (mina -
540
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
541
dady * (setup->vmin[0][1] - setup->pixel_offset)));
542
}
543
544
545
/**
546
* Special coefficient setup for gl_FragCoord.
547
* X and Y are trivial, though Y may have to be inverted for OpenGL.
548
* Z and W are copied from posCoef which should have already been computed.
549
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
550
*/
551
static void
552
setup_fragcoord_coeff(struct setup_context *setup, uint slot)
553
{
554
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
555
boolean origin_lower_left =
556
fsInfo->properties[TGSI_PROPERTY_FS_COORD_ORIGIN];
557
boolean pixel_center_integer =
558
fsInfo->properties[TGSI_PROPERTY_FS_COORD_PIXEL_CENTER];
559
560
/*X*/
561
setup->coef[slot].a0[0] = pixel_center_integer ? 0.0f : 0.5f;
562
setup->coef[slot].dadx[0] = 1.0f;
563
setup->coef[slot].dady[0] = 0.0f;
564
/*Y*/
565
setup->coef[slot].a0[1] =
566
(origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
567
+ (pixel_center_integer ? 0.0f : 0.5f);
568
setup->coef[slot].dadx[1] = 0.0f;
569
setup->coef[slot].dady[1] = origin_lower_left ? -1.0f : 1.0f;
570
/*Z*/
571
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
572
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
573
setup->coef[slot].dady[2] = setup->posCoef.dady[2];
574
/*W*/
575
setup->coef[slot].a0[3] = setup->posCoef.a0[3];
576
setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
577
setup->coef[slot].dady[3] = setup->posCoef.dady[3];
578
}
579
580
581
582
/**
583
* Compute the setup->coef[] array dadx, dady, a0 values.
584
* Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
585
*/
586
static void
587
setup_tri_coefficients(struct setup_context *setup)
588
{
589
struct softpipe_context *softpipe = setup->softpipe;
590
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
591
const struct sp_setup_info *sinfo = &softpipe->setup_info;
592
uint fragSlot;
593
float v[3];
594
595
assert(sinfo->valid);
596
597
/* z and w are done by linear interpolation:
598
*/
599
v[0] = setup->vmin[0][2];
600
v[1] = setup->vmid[0][2];
601
v[2] = setup->vmax[0][2];
602
tri_linear_coeff(setup, &setup->posCoef, 2, v);
603
604
v[0] = setup->vmin[0][3];
605
v[1] = setup->vmid[0][3];
606
v[2] = setup->vmax[0][3];
607
tri_linear_coeff(setup, &setup->posCoef, 3, v);
608
609
/* setup interpolation for all the remaining attributes:
610
*/
611
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
612
const uint vertSlot = sinfo->attrib[fragSlot].src_index;
613
uint j;
614
615
switch (sinfo->attrib[fragSlot].interp) {
616
case SP_INTERP_CONSTANT:
617
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
618
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
619
}
620
break;
621
case SP_INTERP_LINEAR:
622
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
623
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
624
setup->vmid[vertSlot][j],
625
setup->vmax[vertSlot][j],
626
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
627
v);
628
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
629
}
630
break;
631
case SP_INTERP_PERSPECTIVE:
632
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
633
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
634
setup->vmid[vertSlot][j],
635
setup->vmax[vertSlot][j],
636
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
637
v);
638
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
639
}
640
break;
641
case SP_INTERP_POS:
642
setup_fragcoord_coeff(setup, fragSlot);
643
break;
644
default:
645
assert(0);
646
}
647
648
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
649
/* convert 0 to 1.0 and 1 to -1.0 */
650
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
651
setup->coef[fragSlot].dadx[0] = 0.0;
652
setup->coef[fragSlot].dady[0] = 0.0;
653
}
654
655
if (0) {
656
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
657
debug_printf("attr[%d].%c: a0:%f dx:%f dy:%f\n",
658
fragSlot, "xyzw"[j],
659
setup->coef[fragSlot].a0[j],
660
setup->coef[fragSlot].dadx[j],
661
setup->coef[fragSlot].dady[j]);
662
}
663
}
664
}
665
}
666
667
668
static void
669
setup_tri_edges(struct setup_context *setup)
670
{
671
float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
672
float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
673
674
float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
675
float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
676
float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
677
678
setup->emaj.sy = ceilf(vmin_y);
679
setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
680
setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f;
681
setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
682
683
setup->etop.sy = ceilf(vmid_y);
684
setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
685
setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f;
686
setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
687
688
setup->ebot.sy = ceilf(vmin_y);
689
setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
690
setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f;
691
setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
692
}
693
694
695
/**
696
* Render the upper or lower half of a triangle.
697
* Scissoring/cliprect is applied here too.
698
*/
699
static void
700
subtriangle(struct setup_context *setup,
701
struct edge *eleft,
702
struct edge *eright,
703
int lines,
704
unsigned viewport_index)
705
{
706
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect[viewport_index];
707
const int minx = (int) cliprect->minx;
708
const int maxx = (int) cliprect->maxx;
709
const int miny = (int) cliprect->miny;
710
const int maxy = (int) cliprect->maxy;
711
int y, start_y, finish_y;
712
int sy = (int)eleft->sy;
713
714
assert((int)eleft->sy == (int) eright->sy);
715
assert(lines >= 0);
716
717
/* clip top/bottom */
718
start_y = sy;
719
if (start_y < miny)
720
start_y = miny;
721
722
finish_y = sy + lines;
723
if (finish_y > maxy)
724
finish_y = maxy;
725
726
start_y -= sy;
727
finish_y -= sy;
728
729
/*
730
debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
731
*/
732
733
for (y = start_y; y < finish_y; y++) {
734
735
/* avoid accumulating adds as floats don't have the precision to
736
* accurately iterate large triangle edges that way. luckily we
737
* can just multiply these days.
738
*
739
* this is all drowned out by the attribute interpolation anyway.
740
*/
741
int left = (int)(eleft->sx + y * eleft->dxdy);
742
int right = (int)(eright->sx + y * eright->dxdy);
743
744
/* clip left/right */
745
if (left < minx)
746
left = minx;
747
if (right > maxx)
748
right = maxx;
749
750
if (left < right) {
751
int _y = sy + y;
752
if (block(_y) != setup->span.y) {
753
flush_spans(setup);
754
setup->span.y = block(_y);
755
}
756
757
setup->span.left[_y&1] = left;
758
setup->span.right[_y&1] = right;
759
}
760
}
761
762
763
/* save the values so that emaj can be restarted:
764
*/
765
eleft->sx += lines * eleft->dxdy;
766
eright->sx += lines * eright->dxdy;
767
eleft->sy += lines;
768
eright->sy += lines;
769
}
770
771
772
/**
773
* Recalculate prim's determinant. This is needed as we don't have
774
* get this information through the vbuf_render interface & we must
775
* calculate it here.
776
*/
777
static float
778
calc_det(const float (*v0)[4],
779
const float (*v1)[4],
780
const float (*v2)[4])
781
{
782
/* edge vectors e = v0 - v2, f = v1 - v2 */
783
const float ex = v0[0][0] - v2[0][0];
784
const float ey = v0[0][1] - v2[0][1];
785
const float fx = v1[0][0] - v2[0][0];
786
const float fy = v1[0][1] - v2[0][1];
787
788
/* det = cross(e,f).z */
789
return ex * fy - ey * fx;
790
}
791
792
793
/**
794
* Do setup for triangle rasterization, then render the triangle.
795
*/
796
void
797
sp_setup_tri(struct setup_context *setup,
798
const float (*v0)[4],
799
const float (*v1)[4],
800
const float (*v2)[4])
801
{
802
float det;
803
uint layer = 0;
804
unsigned viewport_index = 0;
805
#if DEBUG_VERTS
806
debug_printf("Setup triangle:\n");
807
print_vertex(setup, v0);
808
print_vertex(setup, v1);
809
print_vertex(setup, v2);
810
#endif
811
812
if (unlikely(sp_debug & SP_DBG_NO_RAST) ||
813
setup->softpipe->rasterizer->rasterizer_discard)
814
return;
815
816
det = calc_det(v0, v1, v2);
817
/*
818
debug_printf("%s\n", __FUNCTION__ );
819
*/
820
821
#if DEBUG_FRAGS
822
setup->numFragsEmitted = 0;
823
setup->numFragsWritten = 0;
824
#endif
825
826
if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
827
return;
828
829
setup_tri_coefficients( setup );
830
setup_tri_edges( setup );
831
832
assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
833
834
setup->span.y = 0;
835
setup->span.right[0] = 0;
836
setup->span.right[1] = 0;
837
/* setup->span.z_mode = tri_z_mode( setup->ctx ); */
838
if (setup->softpipe->layer_slot > 0) {
839
layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot];
840
layer = MIN2(layer, setup->max_layer);
841
}
842
setup->quad[0].input.layer = layer;
843
844
if (setup->softpipe->viewport_index_slot > 0) {
845
unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
846
viewport_index = sp_clamp_viewport_idx(*udata);
847
}
848
setup->quad[0].input.viewport_index = viewport_index;
849
850
/* init_constant_attribs( setup ); */
851
852
if (setup->oneoverarea < 0.0) {
853
/* emaj on left:
854
*/
855
subtriangle(setup, &setup->emaj, &setup->ebot, setup->ebot.lines, viewport_index);
856
subtriangle(setup, &setup->emaj, &setup->etop, setup->etop.lines, viewport_index);
857
}
858
else {
859
/* emaj on right:
860
*/
861
subtriangle(setup, &setup->ebot, &setup->emaj, setup->ebot.lines, viewport_index);
862
subtriangle(setup, &setup->etop, &setup->emaj, setup->etop.lines, viewport_index);
863
}
864
865
flush_spans( setup );
866
867
if (setup->softpipe->active_statistics_queries) {
868
setup->softpipe->pipeline_statistics.c_primitives++;
869
}
870
871
#if DEBUG_FRAGS
872
printf("Tri: %u frags emitted, %u written\n",
873
setup->numFragsEmitted,
874
setup->numFragsWritten);
875
#endif
876
}
877
878
879
/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
880
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
881
*/
882
static void
883
line_apply_cylindrical_wrap(float v0,
884
float v1,
885
uint cylindrical_wrap,
886
float output[2])
887
{
888
if (cylindrical_wrap) {
889
float delta;
890
891
delta = v1 - v0;
892
if (delta > 0.5f) {
893
v0 += 1.0f;
894
}
895
else if (delta < -0.5f) {
896
v1 += 1.0f;
897
}
898
}
899
900
output[0] = v0;
901
output[1] = v1;
902
}
903
904
905
/**
906
* Compute a0, dadx and dady for a linearly interpolated coefficient,
907
* for a line.
908
* v[0] and v[1] are vmin and vmax, respectively.
909
*/
910
static void
911
line_linear_coeff(const struct setup_context *setup,
912
struct tgsi_interp_coef *coef,
913
uint i,
914
const float v[2])
915
{
916
const float da = v[1] - v[0];
917
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
918
const float dady = da * setup->emaj.dy * setup->oneoverarea;
919
coef->dadx[i] = dadx;
920
coef->dady[i] = dady;
921
coef->a0[i] = (v[0] -
922
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
923
dady * (setup->vmin[0][1] - setup->pixel_offset)));
924
}
925
926
927
/**
928
* Compute a0, dadx and dady for a perspective-corrected interpolant,
929
* for a line.
930
* v[0] and v[1] are vmin and vmax, respectively.
931
*/
932
static void
933
line_persp_coeff(const struct setup_context *setup,
934
struct tgsi_interp_coef *coef,
935
uint i,
936
const float v[2])
937
{
938
const float a0 = v[0] * setup->vmin[0][3];
939
const float a1 = v[1] * setup->vmax[0][3];
940
const float da = a1 - a0;
941
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
942
const float dady = da * setup->emaj.dy * setup->oneoverarea;
943
coef->dadx[i] = dadx;
944
coef->dady[i] = dady;
945
coef->a0[i] = (a0 -
946
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
947
dady * (setup->vmin[0][1] - setup->pixel_offset)));
948
}
949
950
951
/**
952
* Compute the setup->coef[] array dadx, dady, a0 values.
953
* Must be called after setup->vmin,vmax are initialized.
954
*/
955
static boolean
956
setup_line_coefficients(struct setup_context *setup,
957
const float (*v0)[4],
958
const float (*v1)[4])
959
{
960
struct softpipe_context *softpipe = setup->softpipe;
961
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
962
const struct sp_setup_info *sinfo = &softpipe->setup_info;
963
uint fragSlot;
964
float area;
965
float v[2];
966
967
assert(sinfo->valid);
968
969
/* use setup->vmin, vmax to point to vertices */
970
if (softpipe->rasterizer->flatshade_first)
971
setup->vprovoke = v0;
972
else
973
setup->vprovoke = v1;
974
setup->vmin = v0;
975
setup->vmax = v1;
976
977
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
978
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
979
980
/* NOTE: this is not really area but something proportional to it */
981
area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
982
if (area == 0.0f || util_is_inf_or_nan(area))
983
return FALSE;
984
setup->oneoverarea = 1.0f / area;
985
986
/* z and w are done by linear interpolation:
987
*/
988
v[0] = setup->vmin[0][2];
989
v[1] = setup->vmax[0][2];
990
line_linear_coeff(setup, &setup->posCoef, 2, v);
991
992
v[0] = setup->vmin[0][3];
993
v[1] = setup->vmax[0][3];
994
line_linear_coeff(setup, &setup->posCoef, 3, v);
995
996
/* setup interpolation for all the remaining attributes:
997
*/
998
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
999
const uint vertSlot = sinfo->attrib[fragSlot].src_index;
1000
uint j;
1001
1002
switch (sinfo->attrib[fragSlot].interp) {
1003
case SP_INTERP_CONSTANT:
1004
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
1005
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
1006
break;
1007
case SP_INTERP_LINEAR:
1008
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
1009
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
1010
setup->vmax[vertSlot][j],
1011
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
1012
v);
1013
line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
1014
}
1015
break;
1016
case SP_INTERP_PERSPECTIVE:
1017
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
1018
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
1019
setup->vmax[vertSlot][j],
1020
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
1021
v);
1022
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
1023
}
1024
break;
1025
case SP_INTERP_POS:
1026
setup_fragcoord_coeff(setup, fragSlot);
1027
break;
1028
default:
1029
assert(0);
1030
}
1031
1032
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1033
/* convert 0 to 1.0 and 1 to -1.0 */
1034
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
1035
setup->coef[fragSlot].dadx[0] = 0.0;
1036
setup->coef[fragSlot].dady[0] = 0.0;
1037
}
1038
}
1039
return TRUE;
1040
}
1041
1042
1043
/**
1044
* Plot a pixel in a line segment.
1045
*/
1046
static inline void
1047
plot(struct setup_context *setup, int x, int y)
1048
{
1049
const int iy = y & 1;
1050
const int ix = x & 1;
1051
const int quadX = x - ix;
1052
const int quadY = y - iy;
1053
const int mask = (1 << ix) << (2 * iy);
1054
1055
if (quadX != setup->quad[0].input.x0 ||
1056
quadY != setup->quad[0].input.y0)
1057
{
1058
/* flush prev quad, start new quad */
1059
1060
if (setup->quad[0].input.x0 != -1)
1061
clip_emit_quad(setup, &setup->quad[0]);
1062
1063
setup->quad[0].input.x0 = quadX;
1064
setup->quad[0].input.y0 = quadY;
1065
setup->quad[0].inout.mask = 0x0;
1066
}
1067
1068
setup->quad[0].inout.mask |= mask;
1069
}
1070
1071
1072
/**
1073
* Do setup for line rasterization, then render the line.
1074
* Single-pixel width, no stipple, etc. We rely on the 'draw' module
1075
* to handle stippling and wide lines.
1076
*/
1077
void
1078
sp_setup_line(struct setup_context *setup,
1079
const float (*v0)[4],
1080
const float (*v1)[4])
1081
{
1082
int x0 = (int) v0[0][0];
1083
int x1 = (int) v1[0][0];
1084
int y0 = (int) v0[0][1];
1085
int y1 = (int) v1[0][1];
1086
int dx = x1 - x0;
1087
int dy = y1 - y0;
1088
int xstep, ystep;
1089
uint layer = 0;
1090
unsigned viewport_index = 0;
1091
1092
#if DEBUG_VERTS
1093
debug_printf("Setup line:\n");
1094
print_vertex(setup, v0);
1095
print_vertex(setup, v1);
1096
#endif
1097
1098
if (unlikely(sp_debug & SP_DBG_NO_RAST) ||
1099
setup->softpipe->rasterizer->rasterizer_discard)
1100
return;
1101
1102
if (dx == 0 && dy == 0)
1103
return;
1104
1105
if (!setup_line_coefficients(setup, v0, v1))
1106
return;
1107
1108
assert(v0[0][0] < 1.0e9);
1109
assert(v0[0][1] < 1.0e9);
1110
assert(v1[0][0] < 1.0e9);
1111
assert(v1[0][1] < 1.0e9);
1112
1113
if (dx < 0) {
1114
dx = -dx; /* make positive */
1115
xstep = -1;
1116
}
1117
else {
1118
xstep = 1;
1119
}
1120
1121
if (dy < 0) {
1122
dy = -dy; /* make positive */
1123
ystep = -1;
1124
}
1125
else {
1126
ystep = 1;
1127
}
1128
1129
assert(dx >= 0);
1130
assert(dy >= 0);
1131
assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);
1132
1133
setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
1134
setup->quad[0].inout.mask = 0x0;
1135
if (setup->softpipe->layer_slot > 0) {
1136
layer = *(unsigned *)setup->vprovoke[setup->softpipe->layer_slot];
1137
layer = MIN2(layer, setup->max_layer);
1138
}
1139
setup->quad[0].input.layer = layer;
1140
1141
if (setup->softpipe->viewport_index_slot > 0) {
1142
unsigned *udata = (unsigned*)setup->vprovoke[setup->softpipe->viewport_index_slot];
1143
viewport_index = sp_clamp_viewport_idx(*udata);
1144
}
1145
setup->quad[0].input.viewport_index = viewport_index;
1146
1147
/* XXX temporary: set coverage to 1.0 so the line appears
1148
* if AA mode happens to be enabled.
1149
*/
1150
setup->quad[0].input.coverage[0] =
1151
setup->quad[0].input.coverage[1] =
1152
setup->quad[0].input.coverage[2] =
1153
setup->quad[0].input.coverage[3] = 1.0;
1154
1155
if (dx > dy) {
1156
/*** X-major line ***/
1157
int i;
1158
const int errorInc = dy + dy;
1159
int error = errorInc - dx;
1160
const int errorDec = error - dx;
1161
1162
for (i = 0; i < dx; i++) {
1163
plot(setup, x0, y0);
1164
1165
x0 += xstep;
1166
if (error < 0) {
1167
error += errorInc;
1168
}
1169
else {
1170
error += errorDec;
1171
y0 += ystep;
1172
}
1173
}
1174
}
1175
else {
1176
/*** Y-major line ***/
1177
int i;
1178
const int errorInc = dx + dx;
1179
int error = errorInc - dy;
1180
const int errorDec = error - dy;
1181
1182
for (i = 0; i < dy; i++) {
1183
plot(setup, x0, y0);
1184
1185
y0 += ystep;
1186
if (error < 0) {
1187
error += errorInc;
1188
}
1189
else {
1190
error += errorDec;
1191
x0 += xstep;
1192
}
1193
}
1194
}
1195
1196
/* draw final quad */
1197
if (setup->quad[0].inout.mask) {
1198
clip_emit_quad(setup, &setup->quad[0]);
1199
}
1200
}
1201
1202
1203
static void
1204
point_persp_coeff(const struct setup_context *setup,
1205
const float (*vert)[4],
1206
struct tgsi_interp_coef *coef,
1207
uint vertSlot, uint i)
1208
{
1209
assert(i <= 3);
1210
coef->dadx[i] = 0.0F;
1211
coef->dady[i] = 0.0F;
1212
coef->a0[i] = vert[vertSlot][i] * vert[0][3];
1213
}
1214
1215
1216
/**
1217
* Do setup for point rasterization, then render the point.
1218
* Round or square points...
1219
* XXX could optimize a lot for 1-pixel points.
1220
*/
1221
void
1222
sp_setup_point(struct setup_context *setup,
1223
const float (*v0)[4])
1224
{
1225
struct softpipe_context *softpipe = setup->softpipe;
1226
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
1227
const int sizeAttr = setup->softpipe->psize_slot;
1228
const float size
1229
= sizeAttr > 0 ? v0[sizeAttr][0]
1230
: setup->softpipe->rasterizer->point_size;
1231
const float halfSize = 0.5F * size;
1232
const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
1233
const float x = v0[0][0]; /* Note: data[0] is always position */
1234
const float y = v0[0][1];
1235
const struct sp_setup_info *sinfo = &softpipe->setup_info;
1236
uint fragSlot;
1237
uint layer = 0;
1238
unsigned viewport_index = 0;
1239
#if DEBUG_VERTS
1240
debug_printf("Setup point:\n");
1241
print_vertex(setup, v0);
1242
#endif
1243
1244
assert(sinfo->valid);
1245
1246
if (unlikely(sp_debug & SP_DBG_NO_RAST) ||
1247
setup->softpipe->rasterizer->rasterizer_discard)
1248
return;
1249
1250
assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
1251
1252
if (setup->softpipe->layer_slot > 0) {
1253
layer = *(unsigned *)v0[setup->softpipe->layer_slot];
1254
layer = MIN2(layer, setup->max_layer);
1255
}
1256
setup->quad[0].input.layer = layer;
1257
1258
if (setup->softpipe->viewport_index_slot > 0) {
1259
unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot];
1260
viewport_index = sp_clamp_viewport_idx(*udata);
1261
}
1262
setup->quad[0].input.viewport_index = viewport_index;
1263
1264
/* For points, all interpolants are constant-valued.
1265
* However, for point sprites, we'll need to setup texcoords appropriately.
1266
* XXX: which coefficients are the texcoords???
1267
* We may do point sprites as textured quads...
1268
*
1269
* KW: We don't know which coefficients are texcoords - ultimately
1270
* the choice of what interpolation mode to use for each attribute
1271
* should be determined by the fragment program, using
1272
* per-attribute declaration statements that include interpolation
1273
* mode as a parameter. So either the fragment program will have
1274
* to be adjusted for pointsprite vs normal point behaviour, or
1275
* otherwise a special interpolation mode will have to be defined
1276
* which matches the required behaviour for point sprites. But -
1277
* the latter is not a feature of normal hardware, and as such
1278
* probably should be ruled out on that basis.
1279
*/
1280
setup->vprovoke = v0;
1281
1282
/* setup Z, W */
1283
const_coeff(setup, &setup->posCoef, 0, 2);
1284
const_coeff(setup, &setup->posCoef, 0, 3);
1285
1286
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
1287
const uint vertSlot = sinfo->attrib[fragSlot].src_index;
1288
uint j;
1289
1290
switch (sinfo->attrib[fragSlot].interp) {
1291
case SP_INTERP_CONSTANT:
1292
FALLTHROUGH;
1293
case SP_INTERP_LINEAR:
1294
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
1295
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
1296
break;
1297
case SP_INTERP_PERSPECTIVE:
1298
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
1299
point_persp_coeff(setup, setup->vprovoke,
1300
&setup->coef[fragSlot], vertSlot, j);
1301
break;
1302
case SP_INTERP_POS:
1303
setup_fragcoord_coeff(setup, fragSlot);
1304
break;
1305
default:
1306
assert(0);
1307
}
1308
1309
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
1310
/* convert 0 to 1.0 and 1 to -1.0 */
1311
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
1312
setup->coef[fragSlot].dadx[0] = 0.0;
1313
setup->coef[fragSlot].dady[0] = 0.0;
1314
}
1315
}
1316
1317
1318
if (halfSize <= 0.5 && !round) {
1319
/* special case for 1-pixel points */
1320
const int ix = ((int) x) & 1;
1321
const int iy = ((int) y) & 1;
1322
setup->quad[0].input.x0 = (int) x - ix;
1323
setup->quad[0].input.y0 = (int) y - iy;
1324
setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
1325
clip_emit_quad(setup, &setup->quad[0]);
1326
}
1327
else {
1328
if (round) {
1329
/* rounded points */
1330
const int ixmin = block((int) (x - halfSize));
1331
const int ixmax = block((int) (x + halfSize));
1332
const int iymin = block((int) (y - halfSize));
1333
const int iymax = block((int) (y + halfSize));
1334
const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
1335
const float rmax = halfSize + 0.7071F;
1336
const float rmin2 = MAX2(0.0F, rmin * rmin);
1337
const float rmax2 = rmax * rmax;
1338
const float cscale = 1.0F / (rmax2 - rmin2);
1339
int ix, iy;
1340
1341
for (iy = iymin; iy <= iymax; iy += 2) {
1342
for (ix = ixmin; ix <= ixmax; ix += 2) {
1343
float dx, dy, dist2, cover;
1344
1345
setup->quad[0].inout.mask = 0x0;
1346
1347
dx = (ix + 0.5f) - x;
1348
dy = (iy + 0.5f) - y;
1349
dist2 = dx * dx + dy * dy;
1350
if (dist2 <= rmax2) {
1351
cover = 1.0F - (dist2 - rmin2) * cscale;
1352
setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
1353
setup->quad[0].inout.mask |= MASK_TOP_LEFT;
1354
}
1355
1356
dx = (ix + 1.5f) - x;
1357
dy = (iy + 0.5f) - y;
1358
dist2 = dx * dx + dy * dy;
1359
if (dist2 <= rmax2) {
1360
cover = 1.0F - (dist2 - rmin2) * cscale;
1361
setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
1362
setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
1363
}
1364
1365
dx = (ix + 0.5f) - x;
1366
dy = (iy + 1.5f) - y;
1367
dist2 = dx * dx + dy * dy;
1368
if (dist2 <= rmax2) {
1369
cover = 1.0F - (dist2 - rmin2) * cscale;
1370
setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
1371
setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
1372
}
1373
1374
dx = (ix + 1.5f) - x;
1375
dy = (iy + 1.5f) - y;
1376
dist2 = dx * dx + dy * dy;
1377
if (dist2 <= rmax2) {
1378
cover = 1.0F - (dist2 - rmin2) * cscale;
1379
setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
1380
setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
1381
}
1382
1383
if (setup->quad[0].inout.mask) {
1384
setup->quad[0].input.x0 = ix;
1385
setup->quad[0].input.y0 = iy;
1386
clip_emit_quad(setup, &setup->quad[0]);
1387
}
1388
}
1389
}
1390
}
1391
else {
1392
/* square points */
1393
const int xmin = (int) (x + 0.75 - halfSize);
1394
const int ymin = (int) (y + 0.25 - halfSize);
1395
const int xmax = xmin + (int) size;
1396
const int ymax = ymin + (int) size;
1397
/* XXX could apply scissor to xmin,ymin,xmax,ymax now */
1398
const int ixmin = block(xmin);
1399
const int ixmax = block(xmax - 1);
1400
const int iymin = block(ymin);
1401
const int iymax = block(ymax - 1);
1402
int ix, iy;
1403
1404
/*
1405
debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
1406
*/
1407
for (iy = iymin; iy <= iymax; iy += 2) {
1408
uint rowMask = 0xf;
1409
if (iy < ymin) {
1410
/* above the top edge */
1411
rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
1412
}
1413
if (iy + 1 >= ymax) {
1414
/* below the bottom edge */
1415
rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
1416
}
1417
1418
for (ix = ixmin; ix <= ixmax; ix += 2) {
1419
uint mask = rowMask;
1420
1421
if (ix < xmin) {
1422
/* fragment is past left edge of point, turn off left bits */
1423
mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
1424
}
1425
if (ix + 1 >= xmax) {
1426
/* past the right edge */
1427
mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
1428
}
1429
1430
setup->quad[0].inout.mask = mask;
1431
setup->quad[0].input.x0 = ix;
1432
setup->quad[0].input.y0 = iy;
1433
clip_emit_quad(setup, &setup->quad[0]);
1434
}
1435
}
1436
}
1437
}
1438
}
1439
1440
1441
/**
1442
* Called by vbuf code just before we start buffering primitives.
1443
*/
1444
void
1445
sp_setup_prepare(struct setup_context *setup)
1446
{
1447
struct softpipe_context *sp = setup->softpipe;
1448
int i;
1449
unsigned max_layer = ~0;
1450
if (sp->dirty) {
1451
softpipe_update_derived(sp, sp->reduced_api_prim);
1452
}
1453
1454
/* Note: nr_attrs is only used for debugging (vertex printing) */
1455
setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw);
1456
1457
/*
1458
* Determine how many layers the fb has (used for clamping layer value).
1459
* OpenGL (but not d3d10) permits different amount of layers per rt, however
1460
* results are undefined if layer exceeds the amount of layers of ANY
1461
* attachment hence don't need separate per cbuf and zsbuf max.
1462
*/
1463
for (i = 0; i < setup->softpipe->framebuffer.nr_cbufs; i++) {
1464
struct pipe_surface *cbuf = setup->softpipe->framebuffer.cbufs[i];
1465
if (cbuf) {
1466
max_layer = MIN2(max_layer,
1467
cbuf->u.tex.last_layer - cbuf->u.tex.first_layer);
1468
1469
}
1470
}
1471
1472
/* Prepare pixel offset for rasterisation:
1473
* - pixel center (0.5, 0.5) for GL, or
1474
* - assume (0.0, 0.0) for other APIs.
1475
*/
1476
if (setup->softpipe->rasterizer->half_pixel_center) {
1477
setup->pixel_offset = 0.5f;
1478
} else {
1479
setup->pixel_offset = 0.0f;
1480
}
1481
1482
setup->max_layer = max_layer;
1483
1484
sp->quad.first->begin( sp->quad.first );
1485
1486
if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
1487
sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL &&
1488
sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) {
1489
/* we'll do culling */
1490
setup->cull_face = sp->rasterizer->cull_face;
1491
}
1492
else {
1493
/* 'draw' will do culling */
1494
setup->cull_face = PIPE_FACE_NONE;
1495
}
1496
}
1497
1498
1499
void
1500
sp_setup_destroy_context(struct setup_context *setup)
1501
{
1502
FREE( setup );
1503
}
1504
1505
1506
/**
1507
* Create a new primitive setup/render stage.
1508
*/
1509
struct setup_context *
1510
sp_setup_create_context(struct softpipe_context *softpipe)
1511
{
1512
struct setup_context *setup = CALLOC_STRUCT(setup_context);
1513
unsigned i;
1514
1515
setup->softpipe = softpipe;
1516
1517
for (i = 0; i < MAX_QUADS; i++) {
1518
setup->quad[i].coef = setup->coef;
1519
setup->quad[i].posCoef = &setup->posCoef;
1520
}
1521
1522
setup->span.left[0] = 1000000; /* greater than right[0] */
1523
setup->span.left[1] = 1000000; /* greater than right[1] */
1524
1525
return setup;
1526
}
1527
1528