i965: "Fix" aux offsets
[mesa.git] / src / mesa / drivers / dri / i965 / brw_clip_line.c
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 static void brw_clip_line_alloc_regs( struct brw_clip_compile *c )
46 {
47 const struct gen_device_info *devinfo = c->func.devinfo;
48 GLuint i = 0,j;
49
50 /* Register usage is static, precompute here:
51 */
52 c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
53
54 if (c->key.nr_userclip) {
55 c->reg.fixed_planes = brw_vec4_grf(i, 0);
56 i += (6 + c->key.nr_userclip + 1) / 2;
57
58 c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
59 }
60 else
61 c->prog_data.curb_read_length = 0;
62
63
64 /* Payload vertices plus space for more generated vertices:
65 */
66 for (j = 0; j < 4; j++) {
67 c->reg.vertex[j] = brw_vec4_grf(i, 0);
68 i += c->nr_regs;
69 }
70
71 c->reg.t = brw_vec1_grf(i, 0);
72 c->reg.t0 = brw_vec1_grf(i, 1);
73 c->reg.t1 = brw_vec1_grf(i, 2);
74 c->reg.planemask = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
75 c->reg.plane_equation = brw_vec4_grf(i, 4);
76 i++;
77
78 c->reg.dp0 = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
79 c->reg.dp1 = brw_vec1_grf(i, 4);
80 i++;
81
82 if (!c->key.nr_userclip) {
83 c->reg.fixed_planes = brw_vec8_grf(i, 0);
84 i++;
85 }
86
87 c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
88 c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
89 i++;
90
91 if (devinfo->gen == 5) {
92 c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
93 i++;
94 }
95
96 c->first_tmp = i;
97 c->last_tmp = i;
98
99 c->prog_data.urb_read_length = c->nr_regs; /* ? */
100 c->prog_data.total_grf = i;
101 }
102
103
104 /* Line clipping, more or less following the following algorithm:
105 *
106 * for (p=0;p<MAX_PLANES;p++) {
107 * if (clipmask & (1 << p)) {
108 * GLfloat dp0 = DOTPROD( vtx0, plane[p] );
109 * GLfloat dp1 = DOTPROD( vtx1, plane[p] );
110 *
111 * if (dp1 < 0.0f) {
112 * GLfloat t = dp1 / (dp1 - dp0);
113 * if (t > t1) t1 = t;
114 * } else {
115 * GLfloat t = dp0 / (dp0 - dp1);
116 * if (t > t0) t0 = t;
117 * }
118 *
119 * if (t0 + t1 >= 1.0)
120 * return;
121 * }
122 * }
123 *
124 * interp( ctx, newvtx0, vtx0, vtx1, t0 );
125 * interp( ctx, newvtx1, vtx1, vtx0, t1 );
126 *
127 */
128 static void clip_and_emit_line( struct brw_clip_compile *c )
129 {
130 struct brw_codegen *p = &c->func;
131 struct brw_indirect vtx0 = brw_indirect(0, 0);
132 struct brw_indirect vtx1 = brw_indirect(1, 0);
133 struct brw_indirect newvtx0 = brw_indirect(2, 0);
134 struct brw_indirect newvtx1 = brw_indirect(3, 0);
135 struct brw_indirect plane_ptr = brw_indirect(4, 0);
136 struct brw_reg v1_null_ud = retype(vec1(brw_null_reg()), BRW_REGISTER_TYPE_UD);
137 GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
138 GLint clipdist0_offset = c->key.nr_userclip
139 ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
140 : 0;
141
142 brw_MOV(p, get_addr_reg(vtx0), brw_address(c->reg.vertex[0]));
143 brw_MOV(p, get_addr_reg(vtx1), brw_address(c->reg.vertex[1]));
144 brw_MOV(p, get_addr_reg(newvtx0), brw_address(c->reg.vertex[2]));
145 brw_MOV(p, get_addr_reg(newvtx1), brw_address(c->reg.vertex[3]));
146 brw_MOV(p, get_addr_reg(plane_ptr), brw_clip_plane0_address(c));
147
148 /* Note: init t0, t1 together:
149 */
150 brw_MOV(p, vec2(c->reg.t0), brw_imm_f(0));
151
152 brw_clip_init_planes(c);
153 brw_clip_init_clipmask(c);
154
155 /* -ve rhw workaround */
156 if (p->devinfo->has_negative_rhw_bug) {
157 brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
158 brw_imm_ud(1<<20));
159 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
160 brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(0x3f));
161 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
162 }
163
164 /* Set the initial vertex source mask: The first 6 planes are the bounds
165 * of the view volume; the next 8 planes are the user clipping planes.
166 */
167 brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
168
169 /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
170 * We'll increment 6 times before we start hitting actual user clipping. */
171 brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
172
173 brw_DO(p, BRW_EXECUTE_1);
174 {
175 /* if (planemask & 1)
176 */
177 brw_AND(p, v1_null_ud, c->reg.planemask, brw_imm_ud(1));
178 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
179
180 brw_IF(p, BRW_EXECUTE_1);
181 {
182 brw_AND(p, v1_null_ud, c->reg.vertex_src_mask, brw_imm_ud(1));
183 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
184 brw_IF(p, BRW_EXECUTE_1);
185 {
186 /* user clip distance: just fetch the correct float from each vertex */
187 struct brw_indirect temp_ptr = brw_indirect(7, 0);
188 brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx0), c->reg.clipdistance_offset);
189 brw_MOV(p, c->reg.dp0, deref_1f(temp_ptr, 0));
190 brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx1), c->reg.clipdistance_offset);
191 brw_MOV(p, c->reg.dp1, deref_1f(temp_ptr, 0));
192 }
193 brw_ELSE(p);
194 {
195 /* fixed plane: fetch the hpos, dp4 against the plane. */
196 if (c->key.nr_userclip)
197 brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
198 else
199 brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
200
201 brw_DP4(p, vec4(c->reg.dp0), deref_4f(vtx0, hpos_offset), c->reg.plane_equation);
202 brw_DP4(p, vec4(c->reg.dp1), deref_4f(vtx1, hpos_offset), c->reg.plane_equation);
203 }
204 brw_ENDIF(p);
205
206 brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, vec1(c->reg.dp1), brw_imm_f(0.0f));
207
208 brw_IF(p, BRW_EXECUTE_1);
209 {
210 /*
211 * Both can be negative on GM965/G965 due to RHW workaround
212 * if so, this object should be rejected.
213 */
214 if (p->devinfo->has_negative_rhw_bug) {
215 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE, c->reg.dp0, brw_imm_f(0.0));
216 brw_IF(p, BRW_EXECUTE_1);
217 {
218 brw_clip_kill_thread(c);
219 }
220 brw_ENDIF(p);
221 }
222
223 brw_ADD(p, c->reg.t, c->reg.dp1, negate(c->reg.dp0));
224 brw_math_invert(p, c->reg.t, c->reg.t);
225 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp1);
226
227 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t1 );
228 brw_MOV(p, c->reg.t1, c->reg.t);
229 brw_inst_set_pred_control(p->devinfo, brw_last_inst,
230 BRW_PREDICATE_NORMAL);
231 }
232 brw_ELSE(p);
233 {
234 /* Coming back in. We know that both cannot be negative
235 * because the line would have been culled in that case.
236 */
237
238 /* If both are positive, do nothing */
239 /* Only on GM965/G965 */
240 if (p->devinfo->has_negative_rhw_bug) {
241 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.dp0, brw_imm_f(0.0));
242 brw_IF(p, BRW_EXECUTE_1);
243 }
244
245 {
246 brw_ADD(p, c->reg.t, c->reg.dp0, negate(c->reg.dp1));
247 brw_math_invert(p, c->reg.t, c->reg.t);
248 brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp0);
249
250 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_G, c->reg.t, c->reg.t0 );
251 brw_MOV(p, c->reg.t0, c->reg.t);
252 brw_inst_set_pred_control(p->devinfo, brw_last_inst,
253 BRW_PREDICATE_NORMAL);
254 }
255
256 if (p->devinfo->has_negative_rhw_bug) {
257 brw_ENDIF(p);
258 }
259 }
260 brw_ENDIF(p);
261 }
262 brw_ENDIF(p);
263
264 /* plane_ptr++;
265 */
266 brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
267
268 /* while (planemask>>=1) != 0
269 */
270 brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
271 brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
272 brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
273 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
274 brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
275 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
276 }
277 brw_WHILE(p);
278 brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
279
280 brw_ADD(p, c->reg.t, c->reg.t0, c->reg.t1);
281 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.t, brw_imm_f(1.0));
282 brw_IF(p, BRW_EXECUTE_1);
283 {
284 brw_clip_interp_vertex(c, newvtx0, vtx0, vtx1, c->reg.t0, false);
285 brw_clip_interp_vertex(c, newvtx1, vtx1, vtx0, c->reg.t1, false);
286
287 brw_clip_emit_vue(c, newvtx0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
288 (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
289 | URB_WRITE_PRIM_START);
290 brw_clip_emit_vue(c, newvtx1, BRW_URB_WRITE_EOT_COMPLETE,
291 (_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
292 | URB_WRITE_PRIM_END);
293 }
294 brw_ENDIF(p);
295 brw_clip_kill_thread(c);
296 }
297
298
299
300 void brw_emit_line_clip( struct brw_clip_compile *c )
301 {
302 brw_clip_line_alloc_regs(c);
303 brw_clip_init_ff_sync(c);
304
305 if (c->key.contains_flat_varying) {
306 if (c->key.pv_first)
307 brw_clip_copy_flatshaded_attributes(c, 1, 0);
308 else
309 brw_clip_copy_flatshaded_attributes(c, 0, 1);
310 }
311
312 clip_and_emit_line(c);
313 }