97f321966acca085891fbcf568d596a77a5aae23
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
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:
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.
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.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
32 #include "main/glheader.h"
33 #include "main/macros.h"
34 #include "main/enums.h"
35 #include "program/program.h"
37 #include "intel_batchbuffer.h"
39 #include "brw_defines.h"
40 #include "brw_context.h"
46 /* This is performed against the original triangles, so no indirection
50 static void compute_tri_direction( struct brw_clip_compile
*c
)
52 struct brw_compile
*p
= &c
->func
;
53 struct brw_reg e
= c
->reg
.tmp0
;
54 struct brw_reg f
= c
->reg
.tmp1
;
55 struct brw_reg v0
= byte_offset(c
->reg
.vertex
[0], c
->offset
[VERT_RESULT_HPOS
]);
56 struct brw_reg v1
= byte_offset(c
->reg
.vertex
[1], c
->offset
[VERT_RESULT_HPOS
]);
57 struct brw_reg v2
= byte_offset(c
->reg
.vertex
[2], c
->offset
[VERT_RESULT_HPOS
]);
60 struct brw_reg v0n
= get_tmp(c
);
61 struct brw_reg v1n
= get_tmp(c
);
62 struct brw_reg v2n
= get_tmp(c
);
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.
70 * Try to optimize unnecessary MOV's.
76 brw_clip_project_position(c
, v0n
);
77 brw_clip_project_position(c
, v1n
);
78 brw_clip_project_position(c
, v2n
);
80 /* Calculate the vectors of two edges of the triangle:
82 brw_ADD(p
, e
, v0n
, negate(v2n
));
83 brw_ADD(p
, f
, v1n
, negate(v2n
));
85 /* Take their crossproduct:
87 brw_set_access_mode(p
, BRW_ALIGN_16
);
88 brw_MUL(p
, vec4(brw_null_reg()), brw_swizzle(e
, 1,2,0,3), brw_swizzle(f
,2,0,1,3));
89 brw_MAC(p
, vec4(e
), negate(brw_swizzle(e
, 2,0,1,3)), brw_swizzle(f
,1,2,0,3));
90 brw_set_access_mode(p
, BRW_ALIGN_1
);
92 brw_MUL(p
, c
->reg
.dir
, c
->reg
.dir
, vec4(e
));
96 static void cull_direction( struct brw_clip_compile
*c
)
98 struct brw_compile
*p
= &c
->func
;
101 assert (!(c
->key
.fill_ccw
== CLIP_CULL
&&
102 c
->key
.fill_cw
== CLIP_CULL
));
104 if (c
->key
.fill_ccw
== CLIP_CULL
)
105 conditional
= BRW_CONDITIONAL_GE
;
107 conditional
= BRW_CONDITIONAL_L
;
110 vec1(brw_null_reg()),
112 get_element(c
->reg
.dir
, 2),
115 brw_IF(p
, BRW_EXECUTE_1
);
117 brw_clip_kill_thread(c
);
124 static void copy_bfc( struct brw_clip_compile
*c
)
126 struct brw_compile
*p
= &c
->func
;
129 /* Do we have any colors to copy?
131 if (!(c
->offset
[VERT_RESULT_COL0
] && c
->offset
[VERT_RESULT_BFC0
]) &&
132 !(c
->offset
[VERT_RESULT_COL1
] && c
->offset
[VERT_RESULT_BFC1
]))
135 /* In some wierd degnerate cases we can end up testing the
136 * direction twice, once for culling and once for bfc copying. Oh
137 * well, that's what you get for setting wierd GL state.
139 if (c
->key
.copy_bfc_ccw
)
140 conditional
= BRW_CONDITIONAL_GE
;
142 conditional
= BRW_CONDITIONAL_L
;
145 vec1(brw_null_reg()),
147 get_element(c
->reg
.dir
, 2),
150 brw_IF(p
, BRW_EXECUTE_1
);
154 for (i
= 0; i
< 3; i
++) {
155 if (c
->offset
[VERT_RESULT_COL0
] && c
->offset
[VERT_RESULT_BFC0
])
157 byte_offset(c
->reg
.vertex
[i
], c
->offset
[VERT_RESULT_COL0
]),
158 byte_offset(c
->reg
.vertex
[i
], c
->offset
[VERT_RESULT_BFC0
]));
160 if (c
->offset
[VERT_RESULT_COL1
] && c
->offset
[VERT_RESULT_BFC1
])
162 byte_offset(c
->reg
.vertex
[i
], c
->offset
[VERT_RESULT_COL1
]),
163 byte_offset(c
->reg
.vertex
[i
], c
->offset
[VERT_RESULT_BFC1
]));
173 GLfloat iz = 1.0 / dir.z;
174 GLfloat ac = dir.x * iz;
175 GLfloat bc = dir.y * iz;
176 offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
177 offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
180 static void compute_offset( struct brw_clip_compile
*c
)
182 struct brw_compile
*p
= &c
->func
;
183 struct brw_reg off
= c
->reg
.offset
;
184 struct brw_reg dir
= c
->reg
.dir
;
186 brw_math_invert(p
, get_element(off
, 2), get_element(dir
, 2));
187 brw_MUL(p
, vec2(off
), dir
, get_element(off
, 2));
190 vec1(brw_null_reg()),
192 brw_abs(get_element(off
, 0)),
193 brw_abs(get_element(off
, 1)));
195 brw_SEL(p
, vec1(off
), brw_abs(get_element(off
, 0)), brw_abs(get_element(off
, 1)));
196 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
198 brw_MUL(p
, vec1(off
), off
, brw_imm_f(c
->key
.offset_factor
));
199 brw_ADD(p
, vec1(off
), off
, brw_imm_f(c
->key
.offset_units
));
203 static void merge_edgeflags( struct brw_clip_compile
*c
)
205 struct brw_compile
*p
= &c
->func
;
206 struct brw_reg tmp0
= get_element_ud(c
->reg
.tmp0
, 0);
208 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
210 vec1(brw_null_reg()),
213 brw_imm_ud(_3DPRIM_POLYGON
));
215 /* Get away with using reg.vertex because we know that this is not
216 * a _3DPRIM_TRISTRIP_REVERSE:
218 brw_IF(p
, BRW_EXECUTE_1
);
220 brw_set_conditionalmod(p
, BRW_CONDITIONAL_EQ
);
221 brw_AND(p
, vec1(brw_null_reg()), get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(1<<8));
222 brw_MOV(p
, byte_offset(c
->reg
.vertex
[0], c
->offset
[VERT_RESULT_EDGE
]), brw_imm_f(0));
223 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
225 brw_set_conditionalmod(p
, BRW_CONDITIONAL_EQ
);
226 brw_AND(p
, vec1(brw_null_reg()), get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(1<<9));
227 brw_MOV(p
, byte_offset(c
->reg
.vertex
[2], c
->offset
[VERT_RESULT_EDGE
]), brw_imm_f(0));
228 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
235 static void apply_one_offset( struct brw_clip_compile
*c
,
236 struct brw_indirect vert
)
238 struct brw_compile
*p
= &c
->func
;
239 struct brw_reg z
= deref_1f(vert
, c
->ndc_offset
+
240 2 * type_sz(BRW_REGISTER_TYPE_F
));
242 brw_ADD(p
, z
, z
, vec1(c
->reg
.offset
));
247 /***********************************************************************
248 * Output clipped polygon as an unfilled primitive:
250 static void emit_lines(struct brw_clip_compile
*c
,
253 struct brw_compile
*p
= &c
->func
;
254 struct brw_instruction
*loop
;
255 struct brw_indirect v0
= brw_indirect(0, 0);
256 struct brw_indirect v1
= brw_indirect(1, 0);
257 struct brw_indirect v0ptr
= brw_indirect(2, 0);
258 struct brw_indirect v1ptr
= brw_indirect(3, 0);
260 /* Need a seperate loop for offset:
263 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
264 brw_MOV(p
, get_addr_reg(v0ptr
), brw_address(c
->reg
.inlist
));
266 loop
= brw_DO(p
, BRW_EXECUTE_1
);
268 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(v0ptr
, 0));
269 brw_ADD(p
, get_addr_reg(v0ptr
), get_addr_reg(v0ptr
), brw_imm_uw(2));
271 apply_one_offset(c
, v0
);
273 brw_set_conditionalmod(p
, BRW_CONDITIONAL_G
);
274 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
279 /* v1ptr = &inlist[nr_verts]
282 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
283 brw_MOV(p
, get_addr_reg(v0ptr
), brw_address(c
->reg
.inlist
));
284 brw_ADD(p
, get_addr_reg(v1ptr
), get_addr_reg(v0ptr
), retype(c
->reg
.nr_verts
, BRW_REGISTER_TYPE_UW
));
285 brw_ADD(p
, get_addr_reg(v1ptr
), get_addr_reg(v1ptr
), retype(c
->reg
.nr_verts
, BRW_REGISTER_TYPE_UW
));
286 brw_MOV(p
, deref_1uw(v1ptr
, 0), deref_1uw(v0ptr
, 0));
288 loop
= brw_DO(p
, BRW_EXECUTE_1
);
290 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(v0ptr
, 0));
291 brw_MOV(p
, get_addr_reg(v1
), deref_1uw(v0ptr
, 2));
292 brw_ADD(p
, get_addr_reg(v0ptr
), get_addr_reg(v0ptr
), brw_imm_uw(2));
294 /* draw edge if edgeflag != 0 */
296 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
,
297 deref_1f(v0
, c
->offset
[VERT_RESULT_EDGE
]),
299 brw_IF(p
, BRW_EXECUTE_1
);
301 brw_clip_emit_vue(c
, v0
, 1, 0, (_3DPRIM_LINESTRIP
<< 2) | R02_PRIM_START
);
302 brw_clip_emit_vue(c
, v1
, 1, 0, (_3DPRIM_LINESTRIP
<< 2) | R02_PRIM_END
);
306 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
307 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
314 static void emit_points(struct brw_clip_compile
*c
,
315 GLboolean do_offset
)
317 struct brw_compile
*p
= &c
->func
;
318 struct brw_instruction
*loop
;
320 struct brw_indirect v0
= brw_indirect(0, 0);
321 struct brw_indirect v0ptr
= brw_indirect(2, 0);
323 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
324 brw_MOV(p
, get_addr_reg(v0ptr
), brw_address(c
->reg
.inlist
));
326 loop
= brw_DO(p
, BRW_EXECUTE_1
);
328 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(v0ptr
, 0));
329 brw_ADD(p
, get_addr_reg(v0ptr
), get_addr_reg(v0ptr
), brw_imm_uw(2));
331 /* draw if edgeflag != 0
334 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
,
335 deref_1f(v0
, c
->offset
[VERT_RESULT_EDGE
]),
337 brw_IF(p
, BRW_EXECUTE_1
);
340 apply_one_offset(c
, v0
);
342 brw_clip_emit_vue(c
, v0
, 1, 0, (_3DPRIM_POINTLIST
<< 2) | R02_PRIM_START
| R02_PRIM_END
);
346 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
347 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
358 static void emit_primitives( struct brw_clip_compile
*c
,
360 GLboolean do_offset
)
364 brw_clip_tri_emit_polygon(c
);
368 emit_lines(c
, do_offset
);
372 emit_points(c
, do_offset
);
383 static void emit_unfilled_primitives( struct brw_clip_compile
*c
)
385 struct brw_compile
*p
= &c
->func
;
387 /* Direction culling has already been done.
389 if (c
->key
.fill_ccw
!= c
->key
.fill_cw
&&
390 c
->key
.fill_ccw
!= CLIP_CULL
&&
391 c
->key
.fill_cw
!= CLIP_CULL
)
394 vec1(brw_null_reg()),
396 get_element(c
->reg
.dir
, 2),
399 brw_IF(p
, BRW_EXECUTE_1
);
401 emit_primitives(c
, c
->key
.fill_ccw
, c
->key
.offset_ccw
);
405 emit_primitives(c
, c
->key
.fill_cw
, c
->key
.offset_cw
);
409 else if (c
->key
.fill_cw
!= CLIP_CULL
) {
410 emit_primitives(c
, c
->key
.fill_cw
, c
->key
.offset_cw
);
412 else if (c
->key
.fill_ccw
!= CLIP_CULL
) {
413 emit_primitives(c
, c
->key
.fill_ccw
, c
->key
.offset_ccw
);
420 static void check_nr_verts( struct brw_clip_compile
*c
)
422 struct brw_compile
*p
= &c
->func
;
424 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_L
, c
->reg
.nr_verts
, brw_imm_d(3));
425 brw_IF(p
, BRW_EXECUTE_1
);
427 brw_clip_kill_thread(c
);
433 void brw_emit_unfilled_clip( struct brw_clip_compile
*c
)
435 struct brw_compile
*p
= &c
->func
;
437 c
->need_direction
= ((c
->key
.offset_ccw
|| c
->key
.offset_cw
) ||
438 (c
->key
.fill_ccw
!= c
->key
.fill_cw
) ||
439 c
->key
.fill_ccw
== CLIP_CULL
||
440 c
->key
.fill_cw
== CLIP_CULL
||
441 c
->key
.copy_bfc_cw
||
442 c
->key
.copy_bfc_ccw
);
444 brw_clip_tri_alloc_regs(c
, 3 + c
->key
.nr_userclip
+ 6);
445 brw_clip_tri_init_vertices(c
);
446 brw_clip_init_ff_sync(c
);
448 assert(c
->offset
[VERT_RESULT_EDGE
]);
450 if (c
->key
.fill_ccw
== CLIP_CULL
&&
451 c
->key
.fill_cw
== CLIP_CULL
) {
452 brw_clip_kill_thread(c
);
458 /* Need to use the inlist indirection here:
460 if (c
->need_direction
)
461 compute_tri_direction(c
);
463 if (c
->key
.fill_ccw
== CLIP_CULL
||
464 c
->key
.fill_cw
== CLIP_CULL
)
467 if (c
->key
.offset_ccw
||
471 if (c
->key
.copy_bfc_ccw
||
475 /* Need to do this whether we clip or not:
477 if (c
->key
.do_flat_shading
)
478 brw_clip_tri_flat_shade(c
);
480 brw_clip_init_clipmask(c
);
481 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
, c
->reg
.planemask
, brw_imm_ud(0));
482 brw_IF(p
, BRW_EXECUTE_1
);
484 brw_clip_init_planes(c
);
490 emit_unfilled_primitives(c
);
491 brw_clip_kill_thread(c
);