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>
36 #include "shader/program.h"
37 #include "intel_batchbuffer.h"
39 #include "brw_defines.h"
40 #include "brw_context.h"
47 void brw_clip_tri_alloc_regs( struct brw_clip_compile
*c
,
52 /* Register usage is static, precompute here:
54 c
->reg
.R0
= retype(brw_vec8_grf(i
, 0), BRW_REGISTER_TYPE_UD
); i
++;
56 if (c
->key
.nr_userclip
) {
57 c
->reg
.fixed_planes
= brw_vec4_grf(i
, 0);
58 i
+= (6 + c
->key
.nr_userclip
+ 1) / 2;
60 c
->prog_data
.curb_read_length
= (6 + c
->key
.nr_userclip
+ 1) / 2;
63 c
->prog_data
.curb_read_length
= 0;
66 /* Payload vertices plus space for more generated vertices:
68 for (j
= 0; j
< nr_verts
; j
++) {
69 c
->reg
.vertex
[j
] = brw_vec4_grf(i
, 0);
73 if (c
->nr_attrs
& 1) {
74 for (j
= 0; j
< 3; j
++) {
75 GLuint delta
= c
->nr_attrs
*16 + 32;
76 brw_MOV(&c
->func
, byte_offset(c
->reg
.vertex
[j
], delta
), brw_imm_f(0));
80 c
->reg
.t
= brw_vec1_grf(i
, 0);
81 c
->reg
.loopcount
= retype(brw_vec1_grf(i
, 1), BRW_REGISTER_TYPE_UD
);
82 c
->reg
.nr_verts
= retype(brw_vec1_grf(i
, 2), BRW_REGISTER_TYPE_UD
);
83 c
->reg
.planemask
= retype(brw_vec1_grf(i
, 3), BRW_REGISTER_TYPE_UD
);
84 c
->reg
.plane_equation
= brw_vec4_grf(i
, 4);
87 c
->reg
.dpPrev
= brw_vec1_grf(i
, 0); /* fixme - dp4 will clobber r.1,2,3 */
88 c
->reg
.dp
= brw_vec1_grf(i
, 4);
91 c
->reg
.inlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
94 c
->reg
.outlist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
97 c
->reg
.freelist
= brw_uw16_reg(BRW_GENERAL_REGISTER_FILE
, i
, 0);
100 if (!c
->key
.nr_userclip
) {
101 c
->reg
.fixed_planes
= brw_vec8_grf(i
, 0);
105 if (c
->key
.do_unfilled
) {
106 c
->reg
.dir
= brw_vec4_grf(i
, 0);
107 c
->reg
.offset
= brw_vec4_grf(i
, 4);
109 c
->reg
.tmp0
= brw_vec4_grf(i
, 0);
110 c
->reg
.tmp1
= brw_vec4_grf(i
, 4);
117 c
->prog_data
.urb_read_length
= c
->nr_regs
; /* ? */
118 c
->prog_data
.total_grf
= i
;
123 void brw_clip_tri_init_vertices( struct brw_clip_compile
*c
)
125 struct brw_compile
*p
= &c
->func
;
126 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
127 struct brw_instruction
*is_rev
;
129 /* Initial list of indices for incoming vertexes:
131 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
133 vec1(brw_null_reg()),
136 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE
));
138 /* XXX: Is there an easier way to do this? Need to reverse every
139 * second tristrip element: Can ignore sometimes?
141 is_rev
= brw_IF(p
, BRW_EXECUTE_1
);
143 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[1]) );
144 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[0]) );
145 if (c
->need_direction
)
146 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(-1));
148 is_rev
= brw_ELSE(p
, is_rev
);
150 brw_MOV(p
, get_element(c
->reg
.inlist
, 0), brw_address(c
->reg
.vertex
[0]) );
151 brw_MOV(p
, get_element(c
->reg
.inlist
, 1), brw_address(c
->reg
.vertex
[1]) );
152 if (c
->need_direction
)
153 brw_MOV(p
, c
->reg
.dir
, brw_imm_f(1));
155 brw_ENDIF(p
, is_rev
);
157 brw_MOV(p
, get_element(c
->reg
.inlist
, 2), brw_address(c
->reg
.vertex
[2]) );
158 brw_MOV(p
, brw_vec8_grf(c
->reg
.outlist
.nr
, 0), brw_imm_f(0));
159 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(3));
164 void brw_clip_tri_flat_shade( struct brw_clip_compile
*c
)
166 struct brw_compile
*p
= &c
->func
;
167 struct brw_instruction
*is_poly
;
168 struct brw_reg tmp0
= c
->reg
.loopcount
; /* handy temporary */
170 brw_AND(p
, tmp0
, get_element_ud(c
->reg
.R0
, 2), brw_imm_ud(PRIM_MASK
));
172 vec1(brw_null_reg()),
175 brw_imm_ud(_3DPRIM_POLYGON
));
177 is_poly
= brw_IF(p
, BRW_EXECUTE_1
);
179 brw_clip_copy_colors(c
, 1, 0);
180 brw_clip_copy_colors(c
, 2, 0);
182 is_poly
= brw_ELSE(p
, is_poly
);
184 brw_clip_copy_colors(c
, 0, 2);
185 brw_clip_copy_colors(c
, 1, 2);
187 brw_ENDIF(p
, is_poly
);
192 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
194 void brw_clip_tri( struct brw_clip_compile
*c
)
196 struct brw_compile
*p
= &c
->func
;
197 struct brw_indirect vtx
= brw_indirect(0, 0);
198 struct brw_indirect vtxPrev
= brw_indirect(1, 0);
199 struct brw_indirect vtxOut
= brw_indirect(2, 0);
200 struct brw_indirect plane_ptr
= brw_indirect(3, 0);
201 struct brw_indirect inlist_ptr
= brw_indirect(4, 0);
202 struct brw_indirect outlist_ptr
= brw_indirect(5, 0);
203 struct brw_indirect freelist_ptr
= brw_indirect(6, 0);
204 struct brw_instruction
*plane_loop
;
205 struct brw_instruction
*plane_active
;
206 struct brw_instruction
*vertex_loop
;
207 struct brw_instruction
*next_test
;
208 struct brw_instruction
*prev_test
;
210 brw_MOV(p
, get_addr_reg(vtxPrev
), brw_address(c
->reg
.vertex
[2]) );
211 brw_MOV(p
, get_addr_reg(plane_ptr
), brw_clip_plane0_address(c
));
212 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
213 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
215 brw_MOV(p
, get_addr_reg(freelist_ptr
), brw_address(c
->reg
.vertex
[3]) );
217 plane_loop
= brw_DO(p
, BRW_EXECUTE_1
);
219 /* if (planemask & 1)
221 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
222 brw_AND(p
, vec1(brw_null_reg()), c
->reg
.planemask
, brw_imm_ud(1));
224 plane_active
= brw_IF(p
, BRW_EXECUTE_1
);
226 /* vtxOut = freelist_ptr++
228 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(freelist_ptr
) );
229 brw_ADD(p
, get_addr_reg(freelist_ptr
), get_addr_reg(freelist_ptr
), brw_imm_uw(c
->nr_regs
* REG_SIZE
));
231 if (c
->key
.nr_userclip
)
232 brw_MOV(p
, c
->reg
.plane_equation
, deref_4f(plane_ptr
, 0));
234 brw_MOV(p
, c
->reg
.plane_equation
, deref_4b(plane_ptr
, 0));
236 brw_MOV(p
, c
->reg
.loopcount
, c
->reg
.nr_verts
);
237 brw_MOV(p
, c
->reg
.nr_verts
, brw_imm_ud(0));
239 vertex_loop
= brw_DO(p
, BRW_EXECUTE_1
);
243 brw_MOV(p
, get_addr_reg(vtx
), deref_1uw(inlist_ptr
, 0));
245 /* IS_NEGATIVE(prev) */
246 brw_set_conditionalmod(p
, BRW_CONDITIONAL_L
);
247 brw_DP4(p
, vec4(c
->reg
.dpPrev
), deref_4f(vtxPrev
, c
->offset
[VERT_RESULT_HPOS
]), c
->reg
.plane_equation
);
248 prev_test
= brw_IF(p
, BRW_EXECUTE_1
);
252 brw_set_conditionalmod(p
, BRW_CONDITIONAL_GE
);
253 brw_DP4(p
, vec4(c
->reg
.dp
), deref_4f(vtx
, c
->offset
[VERT_RESULT_HPOS
]), c
->reg
.plane_equation
);
254 next_test
= brw_IF(p
, BRW_EXECUTE_1
);
259 brw_ADD(p
, c
->reg
.t
, c
->reg
.dpPrev
, negate(c
->reg
.dp
));
260 brw_math_invert(p
, c
->reg
.t
, c
->reg
.t
);
261 brw_MUL(p
, c
->reg
.t
, c
->reg
.t
, c
->reg
.dpPrev
);
263 /* If (vtxOut == 0) vtxOut = vtxPrev
265 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
266 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(vtxPrev
) );
267 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
269 brw_clip_interp_vertex(c
, vtxOut
, vtxPrev
, vtx
, c
->reg
.t
, GL_FALSE
);
271 /* *outlist_ptr++ = vtxOut;
275 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxOut
));
276 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
277 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
278 brw_MOV(p
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
280 brw_ENDIF(p
, next_test
);
283 prev_test
= brw_ELSE(p
, prev_test
);
285 /* *outlist_ptr++ = vtxPrev;
288 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxPrev
));
289 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
290 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
294 brw_set_conditionalmod(p
, BRW_CONDITIONAL_L
);
295 brw_DP4(p
, vec4(c
->reg
.dp
), deref_4f(vtx
, c
->offset
[VERT_RESULT_HPOS
]), c
->reg
.plane_equation
);
296 next_test
= brw_IF(p
, BRW_EXECUTE_1
);
298 /* Going out of bounds. Avoid division by zero as we
299 * know dp != dpPrev from DIFFERENT_SIGNS, above.
301 brw_ADD(p
, c
->reg
.t
, c
->reg
.dp
, negate(c
->reg
.dpPrev
));
302 brw_math_invert(p
, c
->reg
.t
, c
->reg
.t
);
303 brw_MUL(p
, c
->reg
.t
, c
->reg
.t
, c
->reg
.dp
);
305 /* If (vtxOut == 0) vtxOut = vtx
307 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
308 brw_MOV(p
, get_addr_reg(vtxOut
), get_addr_reg(vtx
) );
309 brw_set_predicate_control(p
, BRW_PREDICATE_NONE
);
311 brw_clip_interp_vertex(c
, vtxOut
, vtx
, vtxPrev
, c
->reg
.t
, GL_TRUE
);
313 /* *outlist_ptr++ = vtxOut;
317 brw_MOV(p
, deref_1uw(outlist_ptr
, 0), get_addr_reg(vtxOut
));
318 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_uw(sizeof(short)));
319 brw_ADD(p
, c
->reg
.nr_verts
, c
->reg
.nr_verts
, brw_imm_ud(1));
320 brw_MOV(p
, get_addr_reg(vtxOut
), brw_imm_uw(0) );
322 brw_ENDIF(p
, next_test
);
324 brw_ENDIF(p
, prev_test
);
329 brw_MOV(p
, get_addr_reg(vtxPrev
), get_addr_reg(vtx
));
330 brw_ADD(p
, get_addr_reg(inlist_ptr
), get_addr_reg(inlist_ptr
), brw_imm_uw(sizeof(short)));
332 /* while (--loopcount != 0)
334 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
335 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
337 brw_WHILE(p
, vertex_loop
);
339 /* vtxPrev = *(outlist_ptr-1) OR: outlist[nr_verts-1]
341 * inlist_ptr = &inlist[0]
342 * outlist_ptr = &outlist[0]
344 brw_ADD(p
, get_addr_reg(outlist_ptr
), get_addr_reg(outlist_ptr
), brw_imm_w(-2));
345 brw_MOV(p
, get_addr_reg(vtxPrev
), deref_1uw(outlist_ptr
, 0));
346 brw_MOV(p
, brw_vec8_grf(c
->reg
.inlist
.nr
, 0), brw_vec8_grf(c
->reg
.outlist
.nr
, 0));
347 brw_MOV(p
, get_addr_reg(inlist_ptr
), brw_address(c
->reg
.inlist
));
348 brw_MOV(p
, get_addr_reg(outlist_ptr
), brw_address(c
->reg
.outlist
));
350 brw_ENDIF(p
, plane_active
);
354 brw_ADD(p
, get_addr_reg(plane_ptr
), get_addr_reg(plane_ptr
), brw_clip_plane_stride(c
));
359 vec1(brw_null_reg()),
364 /* && (planemask>>=1) != 0
366 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
367 brw_SHR(p
, c
->reg
.planemask
, c
->reg
.planemask
, brw_imm_ud(1));
369 brw_WHILE(p
, plane_loop
);
374 void brw_clip_tri_emit_polygon(struct brw_clip_compile
*c
)
376 struct brw_compile
*p
= &c
->func
;
377 struct brw_instruction
*loop
, *if_insn
;
379 /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
381 brw_set_conditionalmod(p
, BRW_CONDITIONAL_G
);
387 if_insn
= brw_IF(p
, BRW_EXECUTE_1
);
389 struct brw_indirect v0
= brw_indirect(0, 0);
390 struct brw_indirect vptr
= brw_indirect(1, 0);
392 brw_MOV(p
, get_addr_reg(vptr
), brw_address(c
->reg
.inlist
));
393 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
395 brw_clip_emit_vue(c
, v0
, 1, 0, ((_3DPRIM_TRIFAN
<< 2) | R02_PRIM_START
));
397 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
398 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
400 loop
= brw_DO(p
, BRW_EXECUTE_1
);
402 brw_clip_emit_vue(c
, v0
, 1, 0, (_3DPRIM_TRIFAN
<< 2));
404 brw_ADD(p
, get_addr_reg(vptr
), get_addr_reg(vptr
), brw_imm_uw(2));
405 brw_MOV(p
, get_addr_reg(v0
), deref_1uw(vptr
, 0));
407 brw_set_conditionalmod(p
, BRW_CONDITIONAL_NZ
);
408 brw_ADD(p
, c
->reg
.loopcount
, c
->reg
.loopcount
, brw_imm_d(-1));
412 brw_clip_emit_vue(c
, v0
, 0, 1, ((_3DPRIM_TRIFAN
<< 2) | R02_PRIM_END
));
414 brw_ENDIF(p
, if_insn
);
417 static void do_clip_tri( struct brw_clip_compile
*c
)
419 brw_clip_init_planes(c
);
425 static void maybe_do_clip_tri( struct brw_clip_compile
*c
)
427 struct brw_compile
*p
= &c
->func
;
428 struct brw_instruction
*do_clip
;
430 brw_CMP(p
, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ
, c
->reg
.planemask
, brw_imm_ud(0));
431 do_clip
= brw_IF(p
, BRW_EXECUTE_1
);
435 brw_ENDIF(p
, do_clip
);
441 void brw_emit_tri_clip( struct brw_clip_compile
*c
)
443 brw_clip_tri_alloc_regs(c
, 3 + c
->key
.nr_userclip
+ 6);
444 brw_clip_tri_init_vertices(c
);
445 brw_clip_init_clipmask(c
);
447 /* Can't push into do_clip_tri because with polygon (or quad)
448 * flatshading, need to apply the flatshade here because we don't
449 * respect the PV when converting to trifan for emit:
451 if (c
->key
.do_flat_shading
)
452 brw_clip_tri_flat_shade(c
);
454 if (c
->key
.clip_mode
== BRW_CLIPMODE_NORMAL
)
457 maybe_do_clip_tri(c
);
459 brw_clip_tri_emit_polygon(c
);
461 /* Send an empty message to kill the thread:
463 brw_clip_kill_thread(c
);