Home | History | Annotate | Download | only in i965
      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 (at) 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 static void release_tmps( struct brw_clip_compile *c )
     44 {
     45    c->last_tmp = c->first_tmp;
     46 }
     47 
     48 
     49 void brw_clip_tri_alloc_regs( struct brw_clip_compile *c,
     50 			      GLuint nr_verts )
     51 {
     52    const struct gen_device_info *devinfo = c->func.devinfo;
     53    GLuint i = 0,j;
     54 
     55    /* Register usage is static, precompute here:
     56     */
     57    c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
     58 
     59    if (c->key.nr_userclip) {
     60       c->reg.fixed_planes = brw_vec4_grf(i, 0);
     61       i += (6 + c->key.nr_userclip + 1) / 2;
     62 
     63       c->prog_data.curb_read_length = (6 + c->key.nr_userclip + 1) / 2;
     64    }
     65    else
     66       c->prog_data.curb_read_length = 0;
     67 
     68 
     69    /* Payload vertices plus space for more generated vertices:
     70     */
     71    for (j = 0; j < nr_verts; j++) {
     72       c->reg.vertex[j] = brw_vec4_grf(i, 0);
     73       i += c->nr_regs;
     74    }
     75 
     76    if (c->vue_map.num_slots % 2) {
     77       /* The VUE has an odd number of slots so the last register is only half
     78        * used.  Fill the second half with zero.
     79        */
     80       for (j = 0; j < 3; j++) {
     81 	 GLuint delta = brw_vue_slot_to_offset(c->vue_map.num_slots);
     82 
     83 	 brw_MOV(&c->func, byte_offset(c->reg.vertex[j], delta), brw_imm_f(0));
     84       }
     85    }
     86 
     87    c->reg.t          = brw_vec1_grf(i, 0);
     88    c->reg.loopcount  = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_D);
     89    c->reg.nr_verts   = retype(brw_vec1_grf(i, 2), BRW_REGISTER_TYPE_UD);
     90    c->reg.planemask  = retype(brw_vec1_grf(i, 3), BRW_REGISTER_TYPE_UD);
     91    c->reg.plane_equation = brw_vec4_grf(i, 4);
     92    i++;
     93 
     94    c->reg.dpPrev     = brw_vec1_grf(i, 0); /* fixme - dp4 will clobber r.1,2,3 */
     95    c->reg.dp         = brw_vec1_grf(i, 4);
     96    i++;
     97 
     98    c->reg.inlist     = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
     99    i++;
    100 
    101    c->reg.outlist    = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
    102    i++;
    103 
    104    c->reg.freelist   = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, i, 0);
    105    i++;
    106 
    107    if (!c->key.nr_userclip) {
    108       c->reg.fixed_planes = brw_vec8_grf(i, 0);
    109       i++;
    110    }
    111 
    112    if (c->key.do_unfilled) {
    113       c->reg.dir     = brw_vec4_grf(i, 0);
    114       c->reg.offset  = brw_vec4_grf(i, 4);
    115       i++;
    116       c->reg.tmp0    = brw_vec4_grf(i, 0);
    117       c->reg.tmp1    = brw_vec4_grf(i, 4);
    118       i++;
    119    }
    120 
    121    c->reg.vertex_src_mask = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
    122    c->reg.clipdistance_offset = retype(brw_vec1_grf(i, 1), BRW_REGISTER_TYPE_W);
    123    i++;
    124 
    125    if (devinfo->gen == 5) {
    126       c->reg.ff_sync = retype(brw_vec1_grf(i, 0), BRW_REGISTER_TYPE_UD);
    127       i++;
    128    }
    129 
    130    c->first_tmp = i;
    131    c->last_tmp = i;
    132 
    133    c->prog_data.urb_read_length = c->nr_regs; /* ? */
    134    c->prog_data.total_grf = i;
    135 }
    136 
    137 
    138 
    139 void brw_clip_tri_init_vertices( struct brw_clip_compile *c )
    140 {
    141    struct brw_codegen *p = &c->func;
    142    struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
    143 
    144    /* Initial list of indices for incoming vertexes:
    145     */
    146    brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
    147    brw_CMP(p,
    148 	   vec1(brw_null_reg()),
    149 	   BRW_CONDITIONAL_EQ,
    150 	   tmp0,
    151 	   brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
    152 
    153    /* XXX: Is there an easier way to do this?  Need to reverse every
    154     * second tristrip element:  Can ignore sometimes?
    155     */
    156    brw_IF(p, BRW_EXECUTE_1);
    157    {
    158       brw_MOV(p, get_element(c->reg.inlist, 0),  brw_address(c->reg.vertex[1]) );
    159       brw_MOV(p, get_element(c->reg.inlist, 1),  brw_address(c->reg.vertex[0]) );
    160       if (c->need_direction)
    161 	 brw_MOV(p, c->reg.dir, brw_imm_f(-1));
    162    }
    163    brw_ELSE(p);
    164    {
    165       brw_MOV(p, get_element(c->reg.inlist, 0),  brw_address(c->reg.vertex[0]) );
    166       brw_MOV(p, get_element(c->reg.inlist, 1),  brw_address(c->reg.vertex[1]) );
    167       if (c->need_direction)
    168 	 brw_MOV(p, c->reg.dir, brw_imm_f(1));
    169    }
    170    brw_ENDIF(p);
    171 
    172    brw_MOV(p, get_element(c->reg.inlist, 2),  brw_address(c->reg.vertex[2]) );
    173    brw_MOV(p, brw_vec8_grf(c->reg.outlist.nr, 0), brw_imm_f(0));
    174    brw_MOV(p, c->reg.nr_verts, brw_imm_ud(3));
    175 }
    176 
    177 
    178 
    179 void brw_clip_tri_flat_shade( struct brw_clip_compile *c )
    180 {
    181    struct brw_codegen *p = &c->func;
    182    struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
    183 
    184    brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
    185    brw_CMP(p,
    186 	   vec1(brw_null_reg()),
    187 	   BRW_CONDITIONAL_EQ,
    188 	   tmp0,
    189 	   brw_imm_ud(_3DPRIM_POLYGON));
    190 
    191    brw_IF(p, BRW_EXECUTE_1);
    192    {
    193       brw_clip_copy_flatshaded_attributes(c, 1, 0);
    194       brw_clip_copy_flatshaded_attributes(c, 2, 0);
    195    }
    196    brw_ELSE(p);
    197    {
    198       if (c->key.pv_first) {
    199 	 brw_CMP(p,
    200 		 vec1(brw_null_reg()),
    201 		 BRW_CONDITIONAL_EQ,
    202 		 tmp0,
    203 		 brw_imm_ud(_3DPRIM_TRIFAN));
    204 	 brw_IF(p, BRW_EXECUTE_1);
    205 	 {
    206 	    brw_clip_copy_flatshaded_attributes(c, 0, 1);
    207 	    brw_clip_copy_flatshaded_attributes(c, 2, 1);
    208 	 }
    209 	 brw_ELSE(p);
    210 	 {
    211 	    brw_clip_copy_flatshaded_attributes(c, 1, 0);
    212 	    brw_clip_copy_flatshaded_attributes(c, 2, 0);
    213 	 }
    214 	 brw_ENDIF(p);
    215       }
    216       else {
    217          brw_clip_copy_flatshaded_attributes(c, 0, 2);
    218          brw_clip_copy_flatshaded_attributes(c, 1, 2);
    219       }
    220    }
    221    brw_ENDIF(p);
    222 }
    223 
    224 
    225 /**
    226  * Loads the clip distance for a vertex into `dst`, and ends with
    227  * a comparison of it to zero with the condition `cond`.
    228  *
    229  * - If using a fixed plane, the distance is dot(hpos, plane).
    230  * - If using a user clip plane, the distance is directly available in the vertex.
    231  */
    232 static inline void
    233 load_clip_distance(struct brw_clip_compile *c, struct brw_indirect vtx,
    234                 struct brw_reg dst, GLuint hpos_offset, int cond)
    235 {
    236    struct brw_codegen *p = &c->func;
    237 
    238    dst = vec4(dst);
    239    brw_AND(p, vec1(brw_null_reg()), c->reg.vertex_src_mask, brw_imm_ud(1));
    240    brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    241    brw_IF(p, BRW_EXECUTE_1);
    242    {
    243       struct brw_indirect temp_ptr = brw_indirect(7, 0);
    244       brw_ADD(p, get_addr_reg(temp_ptr), get_addr_reg(vtx), c->reg.clipdistance_offset);
    245       brw_MOV(p, vec1(dst), deref_1f(temp_ptr, 0));
    246    }
    247    brw_ELSE(p);
    248    {
    249       brw_MOV(p, dst, deref_4f(vtx, hpos_offset));
    250       brw_DP4(p, dst, dst, c->reg.plane_equation);
    251    }
    252    brw_ENDIF(p);
    253 
    254    brw_CMP(p, brw_null_reg(), cond, vec1(dst), brw_imm_f(0.0f));
    255 }
    256 
    257 
    258 /* Use mesa's clipping algorithms, translated to GEN4 assembly.
    259  */
    260 void brw_clip_tri( struct brw_clip_compile *c )
    261 {
    262    struct brw_codegen *p = &c->func;
    263    struct brw_indirect vtx = brw_indirect(0, 0);
    264    struct brw_indirect vtxPrev = brw_indirect(1, 0);
    265    struct brw_indirect vtxOut = brw_indirect(2, 0);
    266    struct brw_indirect plane_ptr = brw_indirect(3, 0);
    267    struct brw_indirect inlist_ptr = brw_indirect(4, 0);
    268    struct brw_indirect outlist_ptr = brw_indirect(5, 0);
    269    struct brw_indirect freelist_ptr = brw_indirect(6, 0);
    270    GLuint hpos_offset = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);
    271    GLint clipdist0_offset = c->key.nr_userclip
    272       ? brw_varying_to_offset(&c->vue_map, VARYING_SLOT_CLIP_DIST0)
    273       : 0;
    274 
    275    brw_MOV(p, get_addr_reg(vtxPrev),     brw_address(c->reg.vertex[2]) );
    276    brw_MOV(p, get_addr_reg(plane_ptr),   brw_clip_plane0_address(c));
    277    brw_MOV(p, get_addr_reg(inlist_ptr),  brw_address(c->reg.inlist));
    278    brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
    279 
    280    brw_MOV(p, get_addr_reg(freelist_ptr), brw_address(c->reg.vertex[3]) );
    281 
    282    /* Set the initial vertex source mask: The first 6 planes are the bounds
    283     * of the view volume; the next 8 planes are the user clipping planes.
    284     */
    285    brw_MOV(p, c->reg.vertex_src_mask, brw_imm_ud(0x3fc0));
    286 
    287    /* Set the initial clipdistance offset to be 6 floats before gl_ClipDistance[0].
    288     * We'll increment 6 times before we start hitting actual user clipping. */
    289    brw_MOV(p, c->reg.clipdistance_offset, brw_imm_d(clipdist0_offset - 6*sizeof(float)));
    290 
    291    brw_DO(p, BRW_EXECUTE_1);
    292    {
    293       /* if (planemask & 1)
    294        */
    295       brw_AND(p, vec1(brw_null_reg()), c->reg.planemask, brw_imm_ud(1));
    296       brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    297 
    298       brw_IF(p, BRW_EXECUTE_1);
    299       {
    300 	 /* vtxOut = freelist_ptr++
    301 	  */
    302 	 brw_MOV(p, get_addr_reg(vtxOut),       get_addr_reg(freelist_ptr) );
    303 	 brw_ADD(p, get_addr_reg(freelist_ptr), get_addr_reg(freelist_ptr), brw_imm_uw(c->nr_regs * REG_SIZE));
    304 
    305 	 if (c->key.nr_userclip)
    306 	    brw_MOV(p, c->reg.plane_equation, deref_4f(plane_ptr, 0));
    307 	 else
    308 	    brw_MOV(p, c->reg.plane_equation, deref_4b(plane_ptr, 0));
    309 
    310 	 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
    311 	 brw_MOV(p, c->reg.nr_verts, brw_imm_ud(0));
    312 
    313 	 brw_DO(p, BRW_EXECUTE_1);
    314 	 {
    315 	    /* vtx = *input_ptr;
    316 	     */
    317 	    brw_MOV(p, get_addr_reg(vtx), deref_1uw(inlist_ptr, 0));
    318 
    319             load_clip_distance(c, vtxPrev, c->reg.dpPrev, hpos_offset, BRW_CONDITIONAL_L);
    320 	    /* (prev < 0.0f) */
    321 	    brw_IF(p, BRW_EXECUTE_1);
    322 	    {
    323                load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_GE);
    324 	       /* IS_POSITIVE(next)
    325 		*/
    326 	       brw_IF(p, BRW_EXECUTE_1);
    327 	       {
    328 
    329 		  /* Coming back in.
    330 		   */
    331 		  brw_ADD(p, c->reg.t, c->reg.dpPrev, negate(c->reg.dp));
    332 		  brw_math_invert(p, c->reg.t, c->reg.t);
    333 		  brw_MUL(p, c->reg.t, c->reg.t, c->reg.dpPrev);
    334 
    335 		  /* If (vtxOut == 0) vtxOut = vtxPrev
    336 		   */
    337 		  brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
    338                   brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtxPrev));
    339                   brw_inst_set_pred_control(p->devinfo, brw_last_inst,
    340                                             BRW_PREDICATE_NORMAL);
    341 
    342 		  brw_clip_interp_vertex(c, vtxOut, vtxPrev, vtx, c->reg.t, false);
    343 
    344 		  /* *outlist_ptr++ = vtxOut;
    345 		   * nr_verts++;
    346 		   * vtxOut = 0;
    347 		   */
    348 		  brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
    349 		  brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
    350 		  brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
    351 		  brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
    352 	       }
    353 	       brw_ENDIF(p);
    354 
    355 	    }
    356 	    brw_ELSE(p);
    357 	    {
    358 	       /* *outlist_ptr++ = vtxPrev;
    359 		* nr_verts++;
    360 		*/
    361 	       brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxPrev));
    362 	       brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
    363 	       brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
    364 
    365                load_clip_distance(c, vtx, c->reg.dp, hpos_offset, BRW_CONDITIONAL_L);
    366 	       /* (next < 0.0f)
    367 		*/
    368 	       brw_IF(p, BRW_EXECUTE_1);
    369 	       {
    370 		  /* Going out of bounds.  Avoid division by zero as we
    371 		   * know dp != dpPrev from DIFFERENT_SIGNS, above.
    372 		   */
    373 		  brw_ADD(p, c->reg.t, c->reg.dp, negate(c->reg.dpPrev));
    374 		  brw_math_invert(p, c->reg.t, c->reg.t);
    375 		  brw_MUL(p, c->reg.t, c->reg.t, c->reg.dp);
    376 
    377 		  /* If (vtxOut == 0) vtxOut = vtx
    378 		   */
    379 		  brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, get_addr_reg(vtxOut), brw_imm_uw(0) );
    380                   brw_MOV(p, get_addr_reg(vtxOut), get_addr_reg(vtx));
    381                   brw_inst_set_pred_control(p->devinfo, brw_last_inst,
    382                                             BRW_PREDICATE_NORMAL);
    383 
    384 		  brw_clip_interp_vertex(c, vtxOut, vtx, vtxPrev, c->reg.t, true);
    385 
    386 		  /* *outlist_ptr++ = vtxOut;
    387 		   * nr_verts++;
    388 		   * vtxOut = 0;
    389 		   */
    390 		  brw_MOV(p, deref_1uw(outlist_ptr, 0), get_addr_reg(vtxOut));
    391 		  brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_uw(sizeof(short)));
    392 		  brw_ADD(p, c->reg.nr_verts, c->reg.nr_verts, brw_imm_ud(1));
    393 		  brw_MOV(p, get_addr_reg(vtxOut), brw_imm_uw(0) );
    394 	       }
    395 	       brw_ENDIF(p);
    396 	    }
    397 	    brw_ENDIF(p);
    398 
    399 	    /* vtxPrev = vtx;
    400 	     * inlist_ptr++;
    401 	     */
    402 	    brw_MOV(p, get_addr_reg(vtxPrev), get_addr_reg(vtx));
    403 	    brw_ADD(p, get_addr_reg(inlist_ptr), get_addr_reg(inlist_ptr), brw_imm_uw(sizeof(short)));
    404 
    405 	    /* while (--loopcount != 0)
    406 	     */
    407 	    brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
    408             brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    409 	 }
    410 	 brw_WHILE(p);
    411          brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    412 
    413 	 /* vtxPrev = *(outlist_ptr-1)  OR: outlist[nr_verts-1]
    414 	  * inlist = outlist
    415 	  * inlist_ptr = &inlist[0]
    416 	  * outlist_ptr = &outlist[0]
    417 	  */
    418 	 brw_ADD(p, get_addr_reg(outlist_ptr), get_addr_reg(outlist_ptr), brw_imm_w(-2));
    419 	 brw_MOV(p, get_addr_reg(vtxPrev), deref_1uw(outlist_ptr, 0));
    420 	 brw_MOV(p, brw_vec8_grf(c->reg.inlist.nr, 0), brw_vec8_grf(c->reg.outlist.nr, 0));
    421 	 brw_MOV(p, get_addr_reg(inlist_ptr), brw_address(c->reg.inlist));
    422 	 brw_MOV(p, get_addr_reg(outlist_ptr), brw_address(c->reg.outlist));
    423       }
    424       brw_ENDIF(p);
    425 
    426       /* plane_ptr++;
    427        */
    428       brw_ADD(p, get_addr_reg(plane_ptr), get_addr_reg(plane_ptr), brw_clip_plane_stride(c));
    429 
    430       /* nr_verts >= 3
    431        */
    432       brw_CMP(p,
    433 	      vec1(brw_null_reg()),
    434 	      BRW_CONDITIONAL_GE,
    435 	      c->reg.nr_verts,
    436 	      brw_imm_ud(3));
    437       brw_set_default_predicate_control(p, BRW_PREDICATE_NORMAL);
    438 
    439       /* && (planemask>>=1) != 0
    440        */
    441       brw_SHR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(1));
    442       brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    443       brw_SHR(p, c->reg.vertex_src_mask, c->reg.vertex_src_mask, brw_imm_ud(1));
    444       brw_ADD(p, c->reg.clipdistance_offset, c->reg.clipdistance_offset, brw_imm_w(sizeof(float)));
    445    }
    446    brw_WHILE(p);
    447    brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
    448 }
    449 
    450 
    451 
    452 void brw_clip_tri_emit_polygon(struct brw_clip_compile *c)
    453 {
    454    struct brw_codegen *p = &c->func;
    455 
    456    /* for (loopcount = nr_verts-2; loopcount > 0; loopcount--)
    457     */
    458    brw_ADD(p,
    459 	   c->reg.loopcount,
    460 	   c->reg.nr_verts,
    461 	   brw_imm_d(-2));
    462    brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_G);
    463 
    464    brw_IF(p, BRW_EXECUTE_1);
    465    {
    466       struct brw_indirect v0 = brw_indirect(0, 0);
    467       struct brw_indirect vptr = brw_indirect(1, 0);
    468 
    469       brw_MOV(p, get_addr_reg(vptr), brw_address(c->reg.inlist));
    470       brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
    471 
    472       brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
    473                         ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
    474                          | URB_WRITE_PRIM_START));
    475 
    476       brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
    477       brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
    478 
    479       brw_DO(p, BRW_EXECUTE_1);
    480       {
    481 	 brw_clip_emit_vue(c, v0, BRW_URB_WRITE_ALLOCATE_COMPLETE,
    482                            (_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT));
    483 
    484 	 brw_ADD(p, get_addr_reg(vptr), get_addr_reg(vptr), brw_imm_uw(2));
    485 	 brw_MOV(p, get_addr_reg(v0), deref_1uw(vptr, 0));
    486 
    487 	 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
    488          brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    489       }
    490       brw_WHILE(p);
    491       brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    492 
    493       brw_clip_emit_vue(c, v0, BRW_URB_WRITE_EOT_COMPLETE,
    494                         ((_3DPRIM_TRIFAN << URB_WRITE_PRIM_TYPE_SHIFT)
    495                          | URB_WRITE_PRIM_END));
    496    }
    497    brw_ENDIF(p);
    498 }
    499 
    500 static void do_clip_tri( struct brw_clip_compile *c )
    501 {
    502    brw_clip_init_planes(c);
    503 
    504    brw_clip_tri(c);
    505 }
    506 
    507 
    508 static void maybe_do_clip_tri( struct brw_clip_compile *c )
    509 {
    510    struct brw_codegen *p = &c->func;
    511 
    512    brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
    513    brw_IF(p, BRW_EXECUTE_1);
    514    {
    515       do_clip_tri(c);
    516    }
    517    brw_ENDIF(p);
    518 }
    519 
    520 static void brw_clip_test( struct brw_clip_compile *c )
    521 {
    522     struct brw_reg t = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
    523     struct brw_reg t1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
    524     struct brw_reg t2 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
    525     struct brw_reg t3 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD);
    526 
    527     struct brw_reg v0 = get_tmp(c);
    528     struct brw_reg v1 = get_tmp(c);
    529     struct brw_reg v2 = get_tmp(c);
    530 
    531     struct brw_indirect vt0 = brw_indirect(0, 0);
    532     struct brw_indirect vt1 = brw_indirect(1, 0);
    533     struct brw_indirect vt2 = brw_indirect(2, 0);
    534 
    535     struct brw_codegen *p = &c->func;
    536     struct brw_reg tmp0 = c->reg.loopcount; /* handy temporary */
    537 
    538     GLuint hpos_offset = brw_varying_to_offset(&c->vue_map,
    539                                                    VARYING_SLOT_POS);
    540 
    541     brw_MOV(p, get_addr_reg(vt0), brw_address(c->reg.vertex[0]));
    542     brw_MOV(p, get_addr_reg(vt1), brw_address(c->reg.vertex[1]));
    543     brw_MOV(p, get_addr_reg(vt2), brw_address(c->reg.vertex[2]));
    544     brw_MOV(p, v0, deref_4f(vt0, hpos_offset));
    545     brw_MOV(p, v1, deref_4f(vt1, hpos_offset));
    546     brw_MOV(p, v2, deref_4f(vt2, hpos_offset));
    547     brw_AND(p, c->reg.planemask, c->reg.planemask, brw_imm_ud(~0x3f));
    548 
    549     /* test nearz, xmin, ymin plane */
    550     /* clip.xyz < -clip.w */
    551     brw_CMP(p, t1, BRW_CONDITIONAL_L, v0, negate(get_element(v0, 3)));
    552     brw_CMP(p, t2, BRW_CONDITIONAL_L, v1, negate(get_element(v1, 3)));
    553     brw_CMP(p, t3, BRW_CONDITIONAL_L, v2, negate(get_element(v2, 3)));
    554 
    555     /* All vertices are outside of a plane, rejected */
    556     brw_AND(p, t, t1, t2);
    557     brw_AND(p, t, t, t3);
    558     brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
    559     brw_OR(p, tmp0, tmp0, get_element(t, 2));
    560     brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
    561     brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    562     brw_IF(p, BRW_EXECUTE_1);
    563     {
    564         brw_clip_kill_thread(c);
    565     }
    566     brw_ENDIF(p);
    567     brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
    568 
    569     /* some vertices are inside a plane, some are outside,need to clip */
    570     brw_XOR(p, t, t1, t2);
    571     brw_XOR(p, t1, t2, t3);
    572     brw_OR(p, t, t, t1);
    573     brw_AND(p, t, t, brw_imm_ud(0x1));
    574     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    575             get_element(t, 0), brw_imm_ud(0));
    576     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<5)));
    577     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    578     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    579             get_element(t, 1), brw_imm_ud(0));
    580     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<3)));
    581     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    582     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    583             get_element(t, 2), brw_imm_ud(0));
    584     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<1)));
    585     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    586 
    587     /* test farz, xmax, ymax plane */
    588     /* clip.xyz > clip.w */
    589     brw_CMP(p, t1, BRW_CONDITIONAL_G, v0, get_element(v0, 3));
    590     brw_CMP(p, t2, BRW_CONDITIONAL_G, v1, get_element(v1, 3));
    591     brw_CMP(p, t3, BRW_CONDITIONAL_G, v2, get_element(v2, 3));
    592 
    593     /* All vertices are outside of a plane, rejected */
    594     brw_AND(p, t, t1, t2);
    595     brw_AND(p, t, t, t3);
    596     brw_OR(p, tmp0, get_element(t, 0), get_element(t, 1));
    597     brw_OR(p, tmp0, tmp0, get_element(t, 2));
    598     brw_AND(p, brw_null_reg(), tmp0, brw_imm_ud(0x1));
    599     brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    600     brw_IF(p, BRW_EXECUTE_1);
    601     {
    602         brw_clip_kill_thread(c);
    603     }
    604     brw_ENDIF(p);
    605     brw_set_default_predicate_control(p, BRW_PREDICATE_NONE);
    606 
    607     /* some vertices are inside a plane, some are outside,need to clip */
    608     brw_XOR(p, t, t1, t2);
    609     brw_XOR(p, t1, t2, t3);
    610     brw_OR(p, t, t, t1);
    611     brw_AND(p, t, t, brw_imm_ud(0x1));
    612     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    613             get_element(t, 0), brw_imm_ud(0));
    614     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<4)));
    615     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    616     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    617             get_element(t, 1), brw_imm_ud(0));
    618     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<2)));
    619     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    620     brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_NZ,
    621             get_element(t, 2), brw_imm_ud(0));
    622     brw_OR(p, c->reg.planemask, c->reg.planemask, brw_imm_ud((1<<0)));
    623     brw_inst_set_pred_control(p->devinfo, brw_last_inst, BRW_PREDICATE_NORMAL);
    624 
    625     release_tmps(c);
    626 }
    627 
    628 
    629 void brw_emit_tri_clip( struct brw_clip_compile *c )
    630 {
    631    struct brw_codegen *p = &c->func;
    632    brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
    633    brw_clip_tri_init_vertices(c);
    634    brw_clip_init_clipmask(c);
    635    brw_clip_init_ff_sync(c);
    636 
    637    /* if -ve rhw workaround bit is set,
    638       do cliptest */
    639    if (p->devinfo->has_negative_rhw_bug) {
    640       brw_AND(p, brw_null_reg(), get_element_ud(c->reg.R0, 2),
    641               brw_imm_ud(1<<20));
    642       brw_inst_set_cond_modifier(p->devinfo, brw_last_inst, BRW_CONDITIONAL_NZ);
    643       brw_IF(p, BRW_EXECUTE_1);
    644       {
    645          brw_clip_test(c);
    646       }
    647       brw_ENDIF(p);
    648    }
    649    /* Can't push into do_clip_tri because with polygon (or quad)
    650     * flatshading, need to apply the flatshade here because we don't
    651     * respect the PV when converting to trifan for emit:
    652     */
    653    if (c->key.contains_flat_varying)
    654       brw_clip_tri_flat_shade(c);
    655 
    656    if ((c->key.clip_mode == BRW_CLIPMODE_NORMAL) ||
    657        (c->key.clip_mode == BRW_CLIPMODE_KERNEL_CLIP))
    658       do_clip_tri(c);
    659    else
    660       maybe_do_clip_tri(c);
    661 
    662    brw_clip_tri_emit_polygon(c);
    663 
    664    /* Send an empty message to kill the thread:
    665     */
    666    brw_clip_kill_thread(c);
    667 }
    668