Merge branch 'gallium-msaa'
[mesa.git] / src / gallium / drivers / i965 / brw_clip_line.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) 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 <keith@tungstengraphics.com>
30 */
31
32 #include "util/u_debug.h"
33
34 #include "brw_defines.h"
35 #include "brw_eu.h"
36 #include "brw_clip.h"
37
38
39
40
41 static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
42 {
43 GLuint i = 0,j;
44
45 /* Register usage is static, precompute here:
46 */
47 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
48
49 if (c->key.nr_userclip) {
50 c->reg.fixed_planes = brw_vec4_grf(i, 0);
51 i += (6 + c->key.nr_userclip + 1) / 2;
52
53 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
54 }
55 else
56 c->prog_data.curb_read_length = 0;
57
58
59 /* Payload vertices plus space for more generated vertices:
60 */
61 for (j = 0; j < 4; j++) {
62 c->reg.vertex[j] = brw_vec4_grf(i, 0);
63 i += c->nr_regs;
64 }
65
66 c->reg.t = brw_vec1_grf(i, 0);
67 c->reg.t0 = brw_vec1_grf(i, 1);
68 c->reg.t1 = brw_vec1_grf(i, 2);
69 c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
70 c->reg.plane_equation = brw_vec4_grf(i, 4);
71 i++;
72
73 c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
74 c->reg.dp1 = brw_vec1_grf(i, 4);
75 i++;
76
77 if (!c->key.nr_userclip) {
78 c->reg.fixed_planes = brw_vec8_grf(i, 0);
79 i++;
80 }
81
82 if (c->need_ff_sync) {
83 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
84 i++;
85 }
86
87 c->first_tmp = i;
88 c->last_tmp = i;
89
90 c->prog_data.urb_read_length = c->nr_regs; /* ? */
91 c->prog_data.total_grf = i;
92 }
93
94
95
96 /* Line clipping, more or less following the following algorithm:
97 *
98 * for (p=0;p<MAX_PLANES;p++) {
99 * if (clipmask & (1 << p)) {
100 * GLfloat dp0 = DOTPROD( vtx0, plane[p] );
101 * GLfloat dp1 = DOTPROD( vtx1, plane[p] );
102 *
103 * if (IS_NEGATIVE(dp1)) {
104 * GLfloat t = dp1 / (dp1 - dp0);
105 * if (t > t1) t1 = t;
106 * } else {
107 * GLfloat t = dp0 / (dp0 - dp1);
108 * if (t > t0) t0 = t;
109 * }
110 *
111 * if (t0 + t1 >= 1.0)
112 * return;
113 * }
114 * }
115 *
116 * interp( ctx, newvtx0, vtx0, vtx1, t0 );
117 * interp( ctx, newvtx1, vtx1, vtx0, t1 );
118 *
119 */
120 static void clip_and_emit_line( struct brw_clip_compile *c )
121 {
122 struct brw_compile *p = &c->func;
123 struct brw_indirect vtx0 = brw_indirect(0, 0);
124 struct brw_indirect vtx1 = brw_indirect(1, 0);
125 struct brw_indirect newvtx0 = brw_indirect(2, 0);
126 struct brw_indirect newvtx1 = brw_indirect(3, 0);
127 struct brw_indirect plane_ptr = brw_indirect(4, 0);
128 struct brw_instruction *plane_loop;
129 struct brw_instruction *plane_active;
130 struct brw_instruction *is_negative;
131 struct brw_instruction *is_neg2 = NULL;
132 struct brw_instruction *not_culled;
133 struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
134
135 brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));
136 brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));
137 brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));
138 brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));
139 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
140
141 /* Note: init t0, t1 together:
142 */
143 brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));
144
145 brw_clip_init_planes(c);
146 brw_clip_init_clipmask(c);
147
148 /* -ve rhw workaround */
149 if (c->chipset.is_965) {
150 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
151 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
152 brw_imm_ud(1<<20));
153 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
154 }
155
156 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
157
158 plane_loop = brw_DO(p, BRW_EXECUTE_1);
159 {
160 /* if (planemask & 1)
161 */
162 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
163 brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
164
165 plane_active = brw_IF(p, BRW_EXECUTE_1);
166 {
167 if (c->key.nr_userclip)
168 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
169 else
170 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
171
172 /* dp = DP4(vtx->position, plane)
173 */
174 brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, c->offset_hpos), c->reg.plane_equation);
175
176 /* if (IS_NEGATIVE(dp1))
177 */
178 brw_set_conditionalmod(p, BRW_CONDITIONAL_L);
179 brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, c->offset_hpos), c->reg.plane_equation);
180 is_negative = brw_IF(p, BRW_EXECUTE_1);
181 {
182 /*
183 * Both can be negative on GM965/G965 due to RHW workaround
184 * if so, this object should be rejected.
185 */
186 if (c->chipset.is_965) {
187 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
188 is_neg2 = brw_IF(p, BRW_EXECUTE_1);
189 {
190 brw_clip_kill_thread(c);
191 }
192 brw_ENDIF(p, is_neg2);
193 }
194
195 brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
196 brw_math_invert(p, c->reg.t, c->reg.t);
197 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
198
199 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
200 brw_MOV(p, c->reg.t1, c->reg.t);
201 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
202 }
203 is_negative = brw_ELSE(p, is_negative);
204 {
205 /* Coming back in. We know that both cannot be negative
206 * because the line would have been culled in that case.
207 */
208
209 /* If both are positive, do nothing */
210 /* Only on GM965/G965 */
211 if (c->chipset.is_965) {
212 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
213 is_neg2 = brw_IF(p, BRW_EXECUTE_1);
214 }
215
216 {
217 brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
218 brw_math_invert(p, c->reg.t, c->reg.t);
219 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
220
221 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
222 brw_MOV(p, c->reg.t0, c->reg.t);
223 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
224 }
225
226 if (c->chipset.is_965) {
227 brw_ENDIF(p, is_neg2);
228 }
229 }
230 brw_ENDIF(p, is_negative);
231 }
232 brw_ENDIF(p, plane_active);
233
234 /* plane_ptr++;
235 */
236 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
237
238 /* while (planemask>>=1) != 0
239 */
240 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
241 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
242 }
243 brw_WHILE(p, plane_loop);
244
245 brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
246 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
247 not_culled = brw_IF(p, BRW_EXECUTE_1);
248 {
249 brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, FALSE);
250 brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, FALSE);
251
252 brw_clip_emit_vue(c, newvtx0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
253 brw_clip_emit_vue(c, newvtx1, 0, 1, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
254 }
255 brw_ENDIF(p, not_culled);
256 brw_clip_kill_thread(c);
257 }
258
259
260
261 void brw_emit_line_clip( struct brw_clip_compile *c )
262 {
263 brw_clip_line_alloc_regs(c);
264 brw_clip_init_ff_sync(c);
265
266 if (c->key.do_flat_shading)
267 brw_clip_copy_colors(c, 0, 1);
268
269 clip_and_emit_line(c);
270 }