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