1b8e80941Smrg/* 2b8e80941Smrg Copyright (C) Intel Corp. 2006. All Rights Reserved. 3b8e80941Smrg Intel funded Tungsten Graphics to 4b8e80941Smrg develop this 3D driver. 5b8e80941Smrg 6b8e80941Smrg Permission is hereby granted, free of charge, to any person obtaining 7b8e80941Smrg a copy of this software and associated documentation files (the 8b8e80941Smrg "Software"), to deal in the Software without restriction, including 9b8e80941Smrg without limitation the rights to use, copy, modify, merge, publish, 10b8e80941Smrg distribute, sublicense, and/or sell copies of the Software, and to 11b8e80941Smrg permit persons to whom the Software is furnished to do so, subject to 12b8e80941Smrg the following conditions: 13b8e80941Smrg 14b8e80941Smrg The above copyright notice and this permission notice (including the 15b8e80941Smrg next paragraph) shall be included in all copies or substantial 16b8e80941Smrg portions of the Software. 17b8e80941Smrg 18b8e80941Smrg THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19b8e80941Smrg EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20b8e80941Smrg MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21b8e80941Smrg IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22b8e80941Smrg LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23b8e80941Smrg OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24b8e80941Smrg WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b8e80941Smrg 26b8e80941Smrg **********************************************************************/ 27b8e80941Smrg /* 28b8e80941Smrg * Authors: 29b8e80941Smrg * Keith Whitwell <keithw@vmware.com> 30b8e80941Smrg */ 31b8e80941Smrg 32b8e80941Smrg 33b8e80941Smrg#include "main/macros.h" 34b8e80941Smrg#include "main/enums.h" 35b8e80941Smrg#include "program/program.h" 36b8e80941Smrg 37b8e80941Smrg#include "brw_clip.h" 38b8e80941Smrg 39b8e80941Smrg 40b8e80941Smrgstruct brw_reg get_tmp( struct brw_clip_compile *c ) 41b8e80941Smrg{ 42b8e80941Smrg struct brw_reg tmp = brw_vec4_grf(c->last_tmp, 0); 43b8e80941Smrg 44b8e80941Smrg if (++c->last_tmp > c->prog_data.total_grf) 45b8e80941Smrg c->prog_data.total_grf = c->last_tmp; 46b8e80941Smrg 47b8e80941Smrg return tmp; 48b8e80941Smrg} 49b8e80941Smrg 50b8e80941Smrgstatic void release_tmp( struct brw_clip_compile *c, struct brw_reg tmp ) 51b8e80941Smrg{ 52b8e80941Smrg if (tmp.nr == c->last_tmp-1) 53b8e80941Smrg c->last_tmp--; 54b8e80941Smrg} 55b8e80941Smrg 56b8e80941Smrg 57b8e80941Smrgstatic struct brw_reg make_plane_ud(GLuint x, GLuint y, GLuint z, GLuint w) 58b8e80941Smrg{ 59b8e80941Smrg return brw_imm_ud((w<<24) | (z<<16) | (y<<8) | x); 60b8e80941Smrg} 61b8e80941Smrg 62b8e80941Smrg 63b8e80941Smrgvoid brw_clip_init_planes( struct brw_clip_compile *c ) 64b8e80941Smrg{ 65b8e80941Smrg struct brw_codegen *p = &c->func; 66b8e80941Smrg 67b8e80941Smrg if (!c->key.nr_userclip) { 68b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 0), make_plane_ud( 0, 0, 0xff, 1)); 69b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 1), make_plane_ud( 0, 0, 1, 1)); 70b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 2), make_plane_ud( 0, 0xff, 0, 1)); 71b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 3), make_plane_ud( 0, 1, 0, 1)); 72b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 4), make_plane_ud(0xff, 0, 0, 1)); 73b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.fixed_planes, 5), make_plane_ud( 1, 0, 0, 1)); 74b8e80941Smrg } 75b8e80941Smrg} 76b8e80941Smrg 77b8e80941Smrg 78b8e80941Smrg 79b8e80941Smrg#define W 3 80b8e80941Smrg 81b8e80941Smrg/* Project 'pos' to screen space (or back again), overwrite with results: 82b8e80941Smrg */ 83b8e80941Smrgvoid brw_clip_project_position(struct brw_clip_compile *c, struct brw_reg pos ) 84b8e80941Smrg{ 85b8e80941Smrg struct brw_codegen *p = &c->func; 86b8e80941Smrg 87b8e80941Smrg /* calc rhw 88b8e80941Smrg */ 89b8e80941Smrg brw_math_invert(p, get_element(pos, W), get_element(pos, W)); 90b8e80941Smrg 91b8e80941Smrg /* value.xyz *= value.rhw 92b8e80941Smrg */ 93b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_16); 94b8e80941Smrg brw_MUL(p, brw_writemask(pos, WRITEMASK_XYZ), pos, 95b8e80941Smrg brw_swizzle(pos, BRW_SWIZZLE_WWWW)); 96b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_1); 97b8e80941Smrg} 98b8e80941Smrg 99b8e80941Smrg 100b8e80941Smrgstatic void brw_clip_project_vertex( struct brw_clip_compile *c, 101b8e80941Smrg struct brw_indirect vert_addr ) 102b8e80941Smrg{ 103b8e80941Smrg struct brw_codegen *p = &c->func; 104b8e80941Smrg struct brw_reg tmp = get_tmp(c); 105b8e80941Smrg GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 106b8e80941Smrg GLuint ndc_offset = brw_varying_to_offset(&c->vue_map, 107b8e80941Smrg BRW_VARYING_SLOT_NDC); 108b8e80941Smrg 109b8e80941Smrg /* Fixup position. Extract from the original vertex and re-project 110b8e80941Smrg * to screen space: 111b8e80941Smrg */ 112b8e80941Smrg brw_MOV(p, tmp, deref_4f(vert_addr, hpos_offset)); 113b8e80941Smrg brw_clip_project_position(c, tmp); 114b8e80941Smrg brw_MOV(p, deref_4f(vert_addr, ndc_offset), tmp); 115b8e80941Smrg 116b8e80941Smrg release_tmp(c, tmp); 117b8e80941Smrg} 118b8e80941Smrg 119b8e80941Smrg 120b8e80941Smrg 121b8e80941Smrg 122b8e80941Smrg/* Interpolate between two vertices and put the result into a0.0. 123b8e80941Smrg * Increment a0.0 accordingly. 124b8e80941Smrg * 125b8e80941Smrg * Beware that dest_ptr can be equal to v0_ptr! 126b8e80941Smrg */ 127b8e80941Smrgvoid brw_clip_interp_vertex( struct brw_clip_compile *c, 128b8e80941Smrg struct brw_indirect dest_ptr, 129b8e80941Smrg struct brw_indirect v0_ptr, /* from */ 130b8e80941Smrg struct brw_indirect v1_ptr, /* to */ 131b8e80941Smrg struct brw_reg t0, 132b8e80941Smrg bool force_edgeflag) 133b8e80941Smrg{ 134b8e80941Smrg struct brw_codegen *p = &c->func; 135b8e80941Smrg struct brw_reg t_nopersp, v0_ndc_copy; 136b8e80941Smrg GLuint slot; 137b8e80941Smrg 138b8e80941Smrg /* Just copy the vertex header: 139b8e80941Smrg */ 140b8e80941Smrg /* 141b8e80941Smrg * After CLIP stage, only first 256 bits of the VUE are read 142b8e80941Smrg * back on Ironlake, so needn't change it 143b8e80941Smrg */ 144b8e80941Smrg brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1); 145b8e80941Smrg 146b8e80941Smrg 147b8e80941Smrg /* First handle the 3D and NDC interpolation, in case we 148b8e80941Smrg * need noperspective interpolation. Doing it early has no 149b8e80941Smrg * performance impact in any case. 150b8e80941Smrg */ 151b8e80941Smrg 152b8e80941Smrg /* Take a copy of the v0 NDC coordinates, in case dest == v0. */ 153b8e80941Smrg if (c->key.contains_noperspective_varying) { 154b8e80941Smrg GLuint offset = brw_varying_to_offset(&c->vue_map, 155b8e80941Smrg BRW_VARYING_SLOT_NDC); 156b8e80941Smrg v0_ndc_copy = get_tmp(c); 157b8e80941Smrg brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset)); 158b8e80941Smrg } 159b8e80941Smrg 160b8e80941Smrg /* Compute the new 3D position 161b8e80941Smrg * 162b8e80941Smrg * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0 163b8e80941Smrg */ 164b8e80941Smrg { 165b8e80941Smrg GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); 166b8e80941Smrg struct brw_reg tmp = get_tmp(c); 167b8e80941Smrg brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0); 168b8e80941Smrg brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0); 169b8e80941Smrg brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp); 170b8e80941Smrg release_tmp(c, tmp); 171b8e80941Smrg } 172b8e80941Smrg 173b8e80941Smrg /* Recreate the projected (NDC) coordinate in the new vertex header */ 174b8e80941Smrg brw_clip_project_vertex(c, dest_ptr); 175b8e80941Smrg 176b8e80941Smrg /* If we have noperspective attributes, 177b8e80941Smrg * we need to compute the screen-space t 178b8e80941Smrg */ 179b8e80941Smrg if (c->key.contains_noperspective_varying) { 180b8e80941Smrg GLuint delta = brw_varying_to_offset(&c->vue_map, 181b8e80941Smrg BRW_VARYING_SLOT_NDC); 182b8e80941Smrg struct brw_reg tmp = get_tmp(c); 183b8e80941Smrg t_nopersp = get_tmp(c); 184b8e80941Smrg 185b8e80941Smrg /* t_nopersp = vec4(v1.xy, dest.xy) */ 186b8e80941Smrg brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta)); 187b8e80941Smrg brw_MOV(p, tmp, deref_4f(dest_ptr, delta)); 188b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_16); 189b8e80941Smrg brw_MOV(p, 190b8e80941Smrg brw_writemask(t_nopersp, WRITEMASK_ZW), 191b8e80941Smrg brw_swizzle(tmp, BRW_SWIZZLE_XYXY)); 192b8e80941Smrg 193b8e80941Smrg /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */ 194b8e80941Smrg brw_ADD(p, t_nopersp, t_nopersp, 195b8e80941Smrg negate(brw_swizzle(v0_ndc_copy, BRW_SWIZZLE_XYXY))); 196b8e80941Smrg 197b8e80941Smrg /* Add the absolute values of the X and Y deltas so that if 198b8e80941Smrg * the points aren't in the same place on the screen we get 199b8e80941Smrg * nonzero values to divide. 200b8e80941Smrg * 201b8e80941Smrg * After that, we have vert1 - vert0 in t_nopersp.x and 202b8e80941Smrg * vertnew - vert0 in t_nopersp.y 203b8e80941Smrg * 204b8e80941Smrg * t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|, 205b8e80941Smrg * |dest.x-v0.x| + |dest.y-v0.y|) 206b8e80941Smrg */ 207b8e80941Smrg brw_ADD(p, 208b8e80941Smrg brw_writemask(t_nopersp, WRITEMASK_XY), 209b8e80941Smrg brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_XZXZ)), 210b8e80941Smrg brw_abs(brw_swizzle(t_nopersp, BRW_SWIZZLE_YWYW))); 211b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_1); 212b8e80941Smrg 213b8e80941Smrg /* If the points are in the same place, just substitute a 214b8e80941Smrg * value to avoid divide-by-zero 215b8e80941Smrg */ 216b8e80941Smrg brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, 217b8e80941Smrg vec1(t_nopersp), 218b8e80941Smrg brw_imm_f(0)); 219b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 220b8e80941Smrg brw_MOV(p, t_nopersp, brw_imm_vf4(brw_float_to_vf(1.0), 221b8e80941Smrg brw_float_to_vf(0.0), 222b8e80941Smrg brw_float_to_vf(0.0), 223b8e80941Smrg brw_float_to_vf(0.0))); 224b8e80941Smrg brw_ENDIF(p); 225b8e80941Smrg 226b8e80941Smrg /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it. */ 227b8e80941Smrg brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0)); 228b8e80941Smrg brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp), 229b8e80941Smrg vec1(suboffset(t_nopersp, 1))); 230b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_16); 231b8e80941Smrg brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, BRW_SWIZZLE_XXXX)); 232b8e80941Smrg brw_set_default_access_mode(p, BRW_ALIGN_1); 233b8e80941Smrg 234b8e80941Smrg release_tmp(c, tmp); 235b8e80941Smrg release_tmp(c, v0_ndc_copy); 236b8e80941Smrg } 237b8e80941Smrg 238b8e80941Smrg /* Now we can iterate over each attribute 239b8e80941Smrg * (could be done in pairs?) 240b8e80941Smrg */ 241b8e80941Smrg for (slot = 0; slot < c->vue_map.num_slots; slot++) { 242b8e80941Smrg int varying = c->vue_map.slot_to_varying[slot]; 243b8e80941Smrg GLuint delta = brw_vue_slot_to_offset(slot); 244b8e80941Smrg 245b8e80941Smrg /* HPOS, NDC already handled above */ 246b8e80941Smrg if (varying == VARYING_SLOT_POS || varying == BRW_VARYING_SLOT_NDC) 247b8e80941Smrg continue; 248b8e80941Smrg 249b8e80941Smrg 250b8e80941Smrg if (varying == VARYING_SLOT_EDGE) { 251b8e80941Smrg if (force_edgeflag) 252b8e80941Smrg brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1)); 253b8e80941Smrg else 254b8e80941Smrg brw_MOV(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta)); 255b8e80941Smrg } else if (varying == VARYING_SLOT_PSIZ) { 256b8e80941Smrg /* PSIZ doesn't need interpolation because it isn't used by the 257b8e80941Smrg * fragment shader. 258b8e80941Smrg */ 259b8e80941Smrg } else if (varying < VARYING_SLOT_MAX) { 260b8e80941Smrg /* This is a true vertex result (and not a special value for the VUE 261b8e80941Smrg * header), so interpolate: 262b8e80941Smrg * 263b8e80941Smrg * New = attr0 + t*attr1 - t*attr0 264b8e80941Smrg * 265b8e80941Smrg * Unless the attribute is flat shaded -- in which case just copy 266b8e80941Smrg * from one of the sources (doesn't matter which; already copied from pv) 267b8e80941Smrg */ 268b8e80941Smrg GLuint interp = c->key.interp_mode[slot]; 269b8e80941Smrg 270b8e80941Smrg if (interp != INTERP_MODE_FLAT) { 271b8e80941Smrg struct brw_reg tmp = get_tmp(c); 272b8e80941Smrg struct brw_reg t = 273b8e80941Smrg interp == INTERP_MODE_NOPERSPECTIVE ? t_nopersp : t0; 274b8e80941Smrg 275b8e80941Smrg brw_MUL(p, 276b8e80941Smrg vec4(brw_null_reg()), 277b8e80941Smrg deref_4f(v1_ptr, delta), 278b8e80941Smrg t); 279b8e80941Smrg 280b8e80941Smrg brw_MAC(p, 281b8e80941Smrg tmp, 282b8e80941Smrg negate(deref_4f(v0_ptr, delta)), 283b8e80941Smrg t); 284b8e80941Smrg 285b8e80941Smrg brw_ADD(p, 286b8e80941Smrg deref_4f(dest_ptr, delta), 287b8e80941Smrg deref_4f(v0_ptr, delta), 288b8e80941Smrg tmp); 289b8e80941Smrg 290b8e80941Smrg release_tmp(c, tmp); 291b8e80941Smrg } 292b8e80941Smrg else { 293b8e80941Smrg brw_MOV(p, 294b8e80941Smrg deref_4f(dest_ptr, delta), 295b8e80941Smrg deref_4f(v0_ptr, delta)); 296b8e80941Smrg } 297b8e80941Smrg } 298b8e80941Smrg } 299b8e80941Smrg 300b8e80941Smrg if (c->vue_map.num_slots % 2) { 301b8e80941Smrg GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots); 302b8e80941Smrg 303b8e80941Smrg brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0)); 304b8e80941Smrg } 305b8e80941Smrg 306b8e80941Smrg if (c->key.contains_noperspective_varying) 307b8e80941Smrg release_tmp(c, t_nopersp); 308b8e80941Smrg} 309b8e80941Smrg 310b8e80941Smrgvoid brw_clip_emit_vue(struct brw_clip_compile *c, 311b8e80941Smrg struct brw_indirect vert, 312b8e80941Smrg enum brw_urb_write_flags flags, 313b8e80941Smrg GLuint header) 314b8e80941Smrg{ 315b8e80941Smrg struct brw_codegen *p = &c->func; 316b8e80941Smrg bool allocate = flags & BRW_URB_WRITE_ALLOCATE; 317b8e80941Smrg 318b8e80941Smrg brw_clip_ff_sync(c); 319b8e80941Smrg 320b8e80941Smrg /* Any URB entry that is allocated must subsequently be used or discarded, 321b8e80941Smrg * so it doesn't make sense to mark EOT and ALLOCATE at the same time. 322b8e80941Smrg */ 323b8e80941Smrg assert(!(allocate && (flags & BRW_URB_WRITE_EOT))); 324b8e80941Smrg 325b8e80941Smrg /* Copy the vertex from vertn into m1..mN+1: 326b8e80941Smrg */ 327b8e80941Smrg brw_copy_from_indirect(p, brw_message_reg(1), vert, c->nr_regs); 328b8e80941Smrg 329b8e80941Smrg /* Overwrite PrimType and PrimStart in the message header, for 330b8e80941Smrg * each vertex in turn: 331b8e80941Smrg */ 332b8e80941Smrg brw_MOV(p, get_element_ud(c->reg.R0, 2), brw_imm_ud(header)); 333b8e80941Smrg 334b8e80941Smrg 335b8e80941Smrg /* Send each vertex as a separate write to the urb. This 336b8e80941Smrg * is different to the concept in brw_sf_emit.c, where 337b8e80941Smrg * subsequent writes are used to build up a single urb 338b8e80941Smrg * entry. Each of these writes instantiates a separate 339b8e80941Smrg * urb entry - (I think... what about 'allocate'?) 340b8e80941Smrg */ 341b8e80941Smrg brw_urb_WRITE(p, 342b8e80941Smrg allocate ? c->reg.R0 : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), 343b8e80941Smrg 0, 344b8e80941Smrg c->reg.R0, 345b8e80941Smrg flags, 346b8e80941Smrg c->nr_regs + 1, /* msg length */ 347b8e80941Smrg allocate ? 1 : 0, /* response_length */ 348b8e80941Smrg 0, /* urb offset */ 349b8e80941Smrg BRW_URB_SWIZZLE_NONE); 350b8e80941Smrg} 351b8e80941Smrg 352b8e80941Smrg 353b8e80941Smrg 354b8e80941Smrgvoid brw_clip_kill_thread(struct brw_clip_compile *c) 355b8e80941Smrg{ 356b8e80941Smrg struct brw_codegen *p = &c->func; 357b8e80941Smrg 358b8e80941Smrg brw_clip_ff_sync(c); 359b8e80941Smrg /* Send an empty message to kill the thread and release any 360b8e80941Smrg * allocated urb entry: 361b8e80941Smrg */ 362b8e80941Smrg brw_urb_WRITE(p, 363b8e80941Smrg retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), 364b8e80941Smrg 0, 365b8e80941Smrg c->reg.R0, 366b8e80941Smrg BRW_URB_WRITE_UNUSED | BRW_URB_WRITE_EOT_COMPLETE, 367b8e80941Smrg 1, /* msg len */ 368b8e80941Smrg 0, /* response len */ 369b8e80941Smrg 0, 370b8e80941Smrg BRW_URB_SWIZZLE_NONE); 371b8e80941Smrg} 372b8e80941Smrg 373b8e80941Smrg 374b8e80941Smrg 375b8e80941Smrg 376b8e80941Smrgstruct brw_reg brw_clip_plane0_address( struct brw_clip_compile *c ) 377b8e80941Smrg{ 378b8e80941Smrg return brw_address(c->reg.fixed_planes); 379b8e80941Smrg} 380b8e80941Smrg 381b8e80941Smrg 382b8e80941Smrgstruct brw_reg brw_clip_plane_stride( struct brw_clip_compile *c ) 383b8e80941Smrg{ 384b8e80941Smrg if (c->key.nr_userclip) { 385b8e80941Smrg return brw_imm_uw(16); 386b8e80941Smrg } 387b8e80941Smrg else { 388b8e80941Smrg return brw_imm_uw(4); 389b8e80941Smrg } 390b8e80941Smrg} 391b8e80941Smrg 392b8e80941Smrg 393b8e80941Smrg/* Distribute flatshaded attributes from provoking vertex prior to 394b8e80941Smrg * clipping. 395b8e80941Smrg */ 396b8e80941Smrgvoid brw_clip_copy_flatshaded_attributes( struct brw_clip_compile *c, 397b8e80941Smrg GLuint to, GLuint from ) 398b8e80941Smrg{ 399b8e80941Smrg struct brw_codegen *p = &c->func; 400b8e80941Smrg 401b8e80941Smrg for (int i = 0; i < c->vue_map.num_slots; i++) { 402b8e80941Smrg if (c->key.interp_mode[i] == INTERP_MODE_FLAT) { 403b8e80941Smrg brw_MOV(p, 404b8e80941Smrg byte_offset(c->reg.vertex[to], brw_vue_slot_to_offset(i)), 405b8e80941Smrg byte_offset(c->reg.vertex[from], brw_vue_slot_to_offset(i))); 406b8e80941Smrg } 407b8e80941Smrg } 408b8e80941Smrg} 409b8e80941Smrg 410b8e80941Smrg 411b8e80941Smrg 412b8e80941Smrgvoid brw_clip_init_clipmask( struct brw_clip_compile *c ) 413b8e80941Smrg{ 414b8e80941Smrg struct brw_codegen *p = &c->func; 415b8e80941Smrg struct brw_reg incoming = get_element_ud(c->reg.R0, 2); 416b8e80941Smrg 417b8e80941Smrg /* Shift so that lowest outcode bit is rightmost: 418b8e80941Smrg */ 419b8e80941Smrg brw_SHR(p, c->reg.planemask, incoming, brw_imm_ud(26)); 420b8e80941Smrg 421b8e80941Smrg if (c->key.nr_userclip) { 422b8e80941Smrg struct brw_reg tmp = retype(vec1(get_tmp(c)), BRW_REGISTER_TYPE_UD); 423b8e80941Smrg 424b8e80941Smrg /* Rearrange userclip outcodes so that they come directly after 425b8e80941Smrg * the fixed plane bits. 426b8e80941Smrg */ 427b8e80941Smrg if (p->devinfo->gen == 5 || p->devinfo->is_g4x) 428b8e80941Smrg brw_AND(p, tmp, incoming, brw_imm_ud(0xff<<14)); 429b8e80941Smrg else 430b8e80941Smrg brw_AND(p, tmp, incoming, brw_imm_ud(0x3f<<14)); 431b8e80941Smrg 432b8e80941Smrg brw_SHR(p, tmp, tmp, brw_imm_ud(8)); 433b8e80941Smrg brw_OR(p, c->reg.planemask, c->reg.planemask, tmp); 434b8e80941Smrg 435b8e80941Smrg release_tmp(c, tmp); 436b8e80941Smrg } 437b8e80941Smrg} 438b8e80941Smrg 439b8e80941Smrgvoid brw_clip_ff_sync(struct brw_clip_compile *c) 440b8e80941Smrg{ 441b8e80941Smrg struct brw_codegen *p = &c->func; 442b8e80941Smrg 443b8e80941Smrg if (p->devinfo->gen == 5) { 444b8e80941Smrg brw_AND(p, brw_null_reg(), c->reg.ff_sync, brw_imm_ud(0x1)); 445b8e80941Smrg brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_Z); 446b8e80941Smrg brw_IF(p, BRW_EXECUTE_1); 447b8e80941Smrg { 448b8e80941Smrg brw_OR(p, c->reg.ff_sync, c->reg.ff_sync, brw_imm_ud(0x1)); 449b8e80941Smrg brw_ff_sync(p, 450b8e80941Smrg c->reg.R0, 451b8e80941Smrg 0, 452b8e80941Smrg c->reg.R0, 453b8e80941Smrg 1, /* allocate */ 454b8e80941Smrg 1, /* response length */ 455b8e80941Smrg 0 /* eot */); 456b8e80941Smrg } 457b8e80941Smrg brw_ENDIF(p); 458b8e80941Smrg brw_set_default_predicate_control(p, BRW_PREDICATE_NONE); 459b8e80941Smrg } 460b8e80941Smrg} 461b8e80941Smrg 462b8e80941Smrgvoid brw_clip_init_ff_sync(struct brw_clip_compile *c) 463b8e80941Smrg{ 464b8e80941Smrg struct brw_codegen *p = &c->func; 465b8e80941Smrg 466b8e80941Smrg if (p->devinfo->gen == 5) { 467b8e80941Smrg brw_MOV(p, c->reg.ff_sync, brw_imm_ud(0)); 468b8e80941Smrg } 469b8e80941Smrg} 470