Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/intel/compiler/brw_clip_unfilled.c
4550 views
1
/*
2
Copyright (C) Intel Corp. 2006. All Rights Reserved.
3
Intel funded Tungsten Graphics to
4
develop this 3D driver.
5
6
Permission is hereby granted, free of charge, to any person obtaining
7
a 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, sublicense, 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
16
portions of the Software.
17
18
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26
**********************************************************************/
27
/*
28
* Authors:
29
* Keith Whitwell <[email protected]>
30
*/
31
32
#include "main/macros.h"
33
#include "main/enums.h"
34
#include "program/program.h"
35
36
#include "brw_clip.h"
37
38
39
/* This is performed against the original triangles, so no indirection
40
* required:
41
BZZZT!
42
*/
43
static void compute_tri_direction( struct brw_clip_compile *c )
44
{
45
struct brw_codegen *p = &c->func;
46
struct brw_reg e = c->reg.tmp0;
47
struct brw_reg f = c->reg.tmp1;
48
GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
49
struct brw_reg v0 = byte_offset(c->reg.vertex[0], hpos_offset);
50
struct brw_reg v1 = byte_offset(c->reg.vertex[1], hpos_offset);
51
struct brw_reg v2 = byte_offset(c->reg.vertex[2], hpos_offset);
52
53
54
struct brw_reg v0n = get_tmp(c);
55
struct brw_reg v1n = get_tmp(c);
56
struct brw_reg v2n = get_tmp(c);
57
58
/* Convert to NDC.
59
* NOTE: We can't modify the original vertex coordinates,
60
* as it may impact further operations.
61
* So, we have to keep normalized coordinates in temp registers.
62
*
63
* TBD-KC
64
* Try to optimize unnecessary MOV's.
65
*/
66
brw_MOV(p, v0n, v0);
67
brw_MOV(p, v1n, v1);
68
brw_MOV(p, v2n, v2);
69
70
brw_clip_project_position(c, v0n);
71
brw_clip_project_position(c, v1n);
72
brw_clip_project_position(c, v2n);
73
74
/* Calculate the vectors of two edges of the triangle:
75
*/
76
brw_ADD(p, e, v0n, negate(v2n));
77
brw_ADD(p, f, v1n, negate(v2n));
78
79
/* Take their crossproduct:
80
*/
81
brw_set_default_access_mode(p, BRW_ALIGN_16);
82
brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, BRW_SWIZZLE_YZXW),
83
brw_swizzle(f, BRW_SWIZZLE_ZXYW));
84
brw_MAC(p, vec4(e), negate(brw_swizzle(e, BRW_SWIZZLE_ZXYW)),
85
brw_swizzle(f, BRW_SWIZZLE_YZXW));
86
brw_set_default_access_mode(p, BRW_ALIGN_1);
87
88
brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
89
}
90
91
92
static void cull_direction( struct brw_clip_compile *c )
93
{
94
struct brw_codegen *p = &c->func;
95
GLuint conditional;
96
97
assert (!(c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
98
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL));
99
100
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL)
101
conditional = BRW_CONDITIONAL_GE;
102
else
103
conditional = BRW_CONDITIONAL_L;
104
105
brw_CMP(p,
106
vec1(brw_null_reg()),
107
conditional,
108
get_element(c->reg.dir, 2),
109
brw_imm_f(0));
110
111
brw_IF(p, BRW_EXECUTE_1);
112
{
113
brw_clip_kill_thread(c);
114
}
115
brw_ENDIF(p);
116
}
117
118
119
120
static void copy_bfc( struct brw_clip_compile *c )
121
{
122
struct brw_codegen *p = &c->func;
123
GLuint conditional;
124
125
/* Do we have any colors to copy?
126
*/
127
if (!(brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
128
brw_clip_have_varying(c, VARYING_SLOT_BFC0)) &&
129
!(brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
130
brw_clip_have_varying(c, VARYING_SLOT_BFC1)))
131
return;
132
133
/* In some weird degenerate cases we can end up testing the
134
* direction twice, once for culling and once for bfc copying. Oh
135
* well, that's what you get for setting weird GL state.
136
*/
137
if (c->key.copy_bfc_ccw)
138
conditional = BRW_CONDITIONAL_GE;
139
else
140
conditional = BRW_CONDITIONAL_L;
141
142
brw_CMP(p,
143
vec1(brw_null_reg()),
144
conditional,
145
get_element(c->reg.dir, 2),
146
brw_imm_f(0));
147
148
brw_IF(p, BRW_EXECUTE_1);
149
{
150
GLuint i;
151
152
for (i = 0; i < 3; i++) {
153
if (brw_clip_have_varying(c, VARYING_SLOT_COL0) &&
154
brw_clip_have_varying(c, VARYING_SLOT_BFC0))
155
brw_MOV(p,
156
byte_offset(c->reg.vertex[i],
157
brw_varying_to_offset(&c->vue_map,
158
VARYING_SLOT_COL0)),
159
byte_offset(c->reg.vertex[i],
160
brw_varying_to_offset(&c->vue_map,
161
VARYING_SLOT_BFC0)));
162
163
if (brw_clip_have_varying(c, VARYING_SLOT_COL1) &&
164
brw_clip_have_varying(c, VARYING_SLOT_BFC1))
165
brw_MOV(p,
166
byte_offset(c->reg.vertex[i],
167
brw_varying_to_offset(&c->vue_map,
168
VARYING_SLOT_COL1)),
169
byte_offset(c->reg.vertex[i],
170
brw_varying_to_offset(&c->vue_map,
171
VARYING_SLOT_BFC1)));
172
}
173
}
174
brw_ENDIF(p);
175
}
176
177
178
179
180
/*
181
GLfloat iz = 1.0 / dir.z;
182
GLfloat ac = dir.x * iz;
183
GLfloat bc = dir.y * iz;
184
offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
185
offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
186
if (ctx->Polygon.OffsetClamp && isfinite(ctx->Polygon.OffsetClamp)) {
187
if (ctx->Polygon.OffsetClamp < 0)
188
offset = MAX2( offset, ctx->Polygon.OffsetClamp );
189
else
190
offset = MIN2( offset, ctx->Polygon.OffsetClamp );
191
}
192
offset *= MRD;
193
*/
194
static void compute_offset( struct brw_clip_compile *c )
195
{
196
struct brw_codegen *p = &c->func;
197
struct brw_reg off = c->reg.offset;
198
struct brw_reg dir = c->reg.dir;
199
200
brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
201
brw_MUL(p, vec2(off), vec2(dir), get_element(off, 2));
202
203
brw_CMP(p,
204
vec1(brw_null_reg()),
205
BRW_CONDITIONAL_GE,
206
brw_abs(get_element(off, 0)),
207
brw_abs(get_element(off, 1)));
208
209
brw_SEL(p, vec1(off),
210
brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
211
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
212
213
brw_MUL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_factor));
214
brw_ADD(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_units));
215
if (c->key.offset_clamp && isfinite(c->key.offset_clamp)) {
216
brw_CMP(p,
217
vec1(brw_null_reg()),
218
c->key.offset_clamp < 0 ? BRW_CONDITIONAL_GE : BRW_CONDITIONAL_L,
219
vec1(off),
220
brw_imm_f(c->key.offset_clamp));
221
brw_SEL(p, vec1(off), vec1(off), brw_imm_f(c->key.offset_clamp));
222
}
223
}
224
225
226
static void merge_edgeflags( struct brw_clip_compile *c )
227
{
228
struct brw_codegen *p = &c->func;
229
struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
230
231
brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
232
brw_CMP(p,
233
vec1(brw_null_reg()),
234
BRW_CONDITIONAL_EQ,
235
tmp0,
236
brw_imm_ud(_3DPRIM_POLYGON));
237
238
/* Get away with using reg.vertex because we know that this is not
239
* a _3DPRIM_TRISTRIP_REVERSE:
240
*/
241
brw_IF(p, BRW_EXECUTE_1);
242
{
243
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
244
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
245
brw_MOV(p, byte_offset(c->reg.vertex[0],
246
brw_varying_to_offset(&c->vue_map,
247
VARYING_SLOT_EDGE)),
248
brw_imm_f(0));
249
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
250
251
brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
252
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_EQ);
253
brw_MOV(p, byte_offset(c->reg.vertex[2],
254
brw_varying_to_offset(&c->vue_map,
255
VARYING_SLOT_EDGE)),
256
brw_imm_f(0));
257
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
258
}
259
brw_ENDIF(p);
260
}
261
262
263
264
static void apply_one_offset( struct brw_clip_compile *c,
265
struct brw_indirect vert )
266
{
267
struct brw_codegen *p = &c->func;
268
GLuint ndc_offset = brw_varying_to_offset(&c->vue_map,
269
BRW_VARYING_SLOT_NDC);
270
struct brw_reg z = deref_1f(vert, ndc_offset +
271
2 * type_sz(BRW_REGISTER_TYPE_F));
272
273
brw_ADD(p, z, z, vec1(c->reg.offset));
274
}
275
276
277
278
/***********************************************************************
279
* Output clipped polygon as an unfilled primitive:
280
*/
281
static void emit_lines(struct brw_clip_compile *c,
282
bool do_offset)
283
{
284
struct brw_codegen *p = &c->func;
285
struct brw_indirect v0 = brw_indirect(0, 0);
286
struct brw_indirect v1 = brw_indirect(1, 0);
287
struct brw_indirect v0ptr = brw_indirect(2, 0);
288
struct brw_indirect v1ptr = brw_indirect(3, 0);
289
290
/* Need a separate loop for offset:
291
*/
292
if (do_offset) {
293
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
294
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
295
296
brw_DO(p, BRW_EXECUTE_1);
297
{
298
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
299
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
300
301
apply_one_offset(c, v0);
302
303
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
304
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
305
}
306
brw_WHILE(p);
307
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
308
}
309
310
/* v1ptr = &inlist[nr_verts]
311
* *v1ptr = v0
312
*/
313
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
314
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
315
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
316
brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
317
brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
318
319
brw_DO(p, BRW_EXECUTE_1);
320
{
321
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
322
brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
323
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
324
325
/* draw edge if edgeflag != 0 */
326
brw_CMP(p,
327
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
328
deref_1f(v0, brw_varying_to_offset(&c->vue_map,
329
VARYING_SLOT_EDGE)),
330
brw_imm_f(0));
331
brw_IF(p, BRW_EXECUTE_1);
332
{
333
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
334
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
335
| URB_WRITE_PRIM_START);
336
brw_clip_emit_vue(c, v1, BRW_URB_WRITE_ALLOCATE_COMPLETE,
337
(_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
338
| URB_WRITE_PRIM_END);
339
}
340
brw_ENDIF(p);
341
342
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
343
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
344
}
345
brw_WHILE(p);
346
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
347
}
348
349
350
351
static void emit_points(struct brw_clip_compile *c,
352
bool do_offset )
353
{
354
struct brw_codegen *p = &c->func;
355
356
struct brw_indirect v0 = brw_indirect(0, 0);
357
struct brw_indirect v0ptr = brw_indirect(2, 0);
358
359
brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
360
brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
361
362
brw_DO(p, BRW_EXECUTE_1);
363
{
364
brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
365
brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
366
367
/* draw if edgeflag != 0
368
*/
369
brw_CMP(p,
370
vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
371
deref_1f(v0, brw_varying_to_offset(&c->vue_map,
372
VARYING_SLOT_EDGE)),
373
brw_imm_f(0));
374
brw_IF(p, BRW_EXECUTE_1);
375
{
376
if (do_offset)
377
apply_one_offset(c, v0);
378
379
brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
380
(_3DPRIM_POINTLIST << URB_WRITE_PRIM_TYPE_SHIFT)
381
| URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
382
}
383
brw_ENDIF(p);
384
385
brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
386
brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
387
}
388
brw_WHILE(p);
389
brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
390
}
391
392
393
394
395
396
397
398
static void emit_primitives( struct brw_clip_compile *c,
399
GLuint mode,
400
bool do_offset )
401
{
402
switch (mode) {
403
case BRW_CLIP_FILL_MODE_FILL:
404
brw_clip_tri_emit_polygon(c);
405
break;
406
407
case BRW_CLIP_FILL_MODE_LINE:
408
emit_lines(c, do_offset);
409
break;
410
411
case BRW_CLIP_FILL_MODE_POINT:
412
emit_points(c, do_offset);
413
break;
414
415
case BRW_CLIP_FILL_MODE_CULL:
416
unreachable("not reached");
417
}
418
}
419
420
421
422
static void emit_unfilled_primitives( struct brw_clip_compile *c )
423
{
424
struct brw_codegen *p = &c->func;
425
426
/* Direction culling has already been done.
427
*/
428
if (c->key.fill_ccw != c->key.fill_cw &&
429
c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL &&
430
c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL)
431
{
432
brw_CMP(p,
433
vec1(brw_null_reg()),
434
BRW_CONDITIONAL_GE,
435
get_element(c->reg.dir, 2),
436
brw_imm_f(0));
437
438
brw_IF(p, BRW_EXECUTE_1);
439
{
440
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
441
}
442
brw_ELSE(p);
443
{
444
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
445
}
446
brw_ENDIF(p);
447
}
448
else if (c->key.fill_cw != BRW_CLIP_FILL_MODE_CULL) {
449
emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
450
}
451
else if (c->key.fill_ccw != BRW_CLIP_FILL_MODE_CULL) {
452
emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
453
}
454
}
455
456
457
458
459
static void check_nr_verts( struct brw_clip_compile *c )
460
{
461
struct brw_codegen *p = &c->func;
462
463
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
464
brw_IF(p, BRW_EXECUTE_1);
465
{
466
brw_clip_kill_thread(c);
467
}
468
brw_ENDIF(p);
469
}
470
471
472
void brw_emit_unfilled_clip( struct brw_clip_compile *c )
473
{
474
struct brw_codegen *p = &c->func;
475
476
c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
477
(c->key.fill_ccw != c->key.fill_cw) ||
478
c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
479
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL ||
480
c->key.copy_bfc_cw ||
481
c->key.copy_bfc_ccw);
482
483
brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
484
brw_clip_tri_init_vertices(c);
485
brw_clip_init_ff_sync(c);
486
487
assert(brw_clip_have_varying(c, VARYING_SLOT_EDGE));
488
489
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL &&
490
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL) {
491
brw_clip_kill_thread(c);
492
return;
493
}
494
495
merge_edgeflags(c);
496
497
/* Need to use the inlist indirection here:
498
*/
499
if (c->need_direction)
500
compute_tri_direction(c);
501
502
if (c->key.fill_ccw == BRW_CLIP_FILL_MODE_CULL ||
503
c->key.fill_cw == BRW_CLIP_FILL_MODE_CULL)
504
cull_direction(c);
505
506
if (c->key.offset_ccw ||
507
c->key.offset_cw)
508
compute_offset(c);
509
510
if (c->key.copy_bfc_ccw ||
511
c->key.copy_bfc_cw)
512
copy_bfc(c);
513
514
/* Need to do this whether we clip or not:
515
*/
516
if (c->key.contains_flat_varying)
517
brw_clip_tri_flat_shade(c);
518
519
brw_clip_init_clipmask(c);
520
brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
521
brw_IF(p, BRW_EXECUTE_1);
522
{
523
brw_clip_init_planes(c);
524
brw_clip_tri(c);
525
check_nr_verts(c);
526
}
527
brw_ENDIF(p);
528
529
emit_unfilled_primitives(c);
530
brw_clip_kill_thread(c);
531
}
532
533