brw_clip_unfilled.c

Go to the documentation of this file.
00001 /*
00002  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
00003  Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
00004  develop this 3D driver.
00005  
00006  Permission is hereby granted, free of charge, to any person obtaining
00007  a copy of this software and associated documentation files (the
00008  "Software"), to deal in the Software without restriction, including
00009  without limitation the rights to use, copy, modify, merge, publish,
00010  distribute, sublicense, and/or sell copies of the Software, and to
00011  permit persons to whom the Software is furnished to do so, subject to
00012  the following conditions:
00013  
00014  The above copyright notice and this permission notice (including the
00015  next paragraph) shall be included in all copies or substantial
00016  portions of the Software.
00017  
00018  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00021  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
00022  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00023  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00024  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  
00026  **********************************************************************/
00027  /*
00028   * Authors:
00029   *   Keith Whitwell <keith@tungstengraphics.com>
00030   */
00031 
00032 #include "brw_defines.h"
00033 #include "brw_context.h"
00034 #include "brw_eu.h"
00035 #include "brw_util.h"
00036 #include "brw_clip.h"
00037 
00038 
00039 
00040 /* This is performed against the original triangles, so no indirection
00041  * required:
00042 BZZZT!
00043  */
00044 static void compute_tri_direction( struct brw_clip_compile *c )
00045 {
00046    struct brw_compile *p = &c->func;
00047    struct brw_reg e = c->reg.tmp0;
00048    struct brw_reg f = c->reg.tmp1;
00049    struct brw_reg v0 = byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_HPOS]); 
00050    struct brw_reg v1 = byte_offset(c->reg.vertex[1], c->offset[VERT_RESULT_HPOS]); 
00051    struct brw_reg v2 = byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_HPOS]); 
00052 
00053 
00054    /* Calculate the vectors of two edges of the triangle:
00055     */
00056    brw_ADD(p, e, v0, negate(v2)); 
00057    brw_ADD(p, f, v1, negate(v2)); 
00058 
00059    /* Take their crossproduct:
00060     */
00061    brw_set_access_mode(p, BRW_ALIGN_16);
00062    brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, 1,2,0,3),  brw_swizzle(f,2,0,1,3));
00063    brw_MAC(p, vec4(e),  negate(brw_swizzle(e, 2,0,1,3)), brw_swizzle(f,1,2,0,3));
00064    brw_set_access_mode(p, BRW_ALIGN_1);
00065 
00066    brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
00067 }
00068 
00069 
00070 static void cull_direction( struct brw_clip_compile *c )
00071 {
00072    struct brw_compile *p = &c->func;
00073    struct brw_instruction *ccw;
00074    unsigned conditional;
00075 
00076    assert (!(c->key.fill_ccw == CLIP_CULL &&
00077              c->key.fill_cw == CLIP_CULL));
00078 
00079    if (c->key.fill_ccw == CLIP_CULL)
00080       conditional = BRW_CONDITIONAL_GE;
00081    else
00082       conditional = BRW_CONDITIONAL_L;
00083 
00084    brw_CMP(p,
00085            vec1(brw_null_reg()),
00086            conditional,
00087            get_element(c->reg.dir, 2),
00088            brw_imm_f(0));
00089    
00090    ccw = brw_IF(p, BRW_EXECUTE_1);
00091    {
00092       brw_clip_kill_thread(c);
00093    }
00094    brw_ENDIF(p, ccw);
00095 }
00096 
00097 
00098 
00099 static void copy_bfc( struct brw_clip_compile *c )
00100 {
00101    struct brw_compile *p = &c->func;
00102    struct brw_instruction *ccw;
00103    unsigned conditional;
00104 
00105    /* Do we have any colors to copy? 
00106     */
00107    if (!(c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0]) &&
00108        !(c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1]))
00109       return;
00110 
00111    /* In some wierd degnerate cases we can end up testing the
00112     * direction twice, once for culling and once for bfc copying.  Oh
00113     * well, that's what you get for setting wierd GL state.
00114     */
00115    if (c->key.copy_bfc_ccw)
00116       conditional = BRW_CONDITIONAL_GE;
00117    else
00118       conditional = BRW_CONDITIONAL_L;
00119 
00120    brw_CMP(p,
00121            vec1(brw_null_reg()),
00122            conditional,
00123            get_element(c->reg.dir, 2),
00124            brw_imm_f(0));
00125    
00126    ccw = brw_IF(p, BRW_EXECUTE_1);
00127    {
00128       unsigned i;
00129 
00130       for (i = 0; i < 3; i++) {
00131          if (c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0])
00132             brw_MOV(p, 
00133                     byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL0]),
00134                     byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC0]));
00135 
00136          if (c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1])
00137             brw_MOV(p, 
00138                     byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL1]),
00139                     byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC1]));
00140       }
00141    }
00142    brw_ENDIF(p, ccw);
00143 }
00144 
00145 
00146 
00147 
00148 /*
00149   float iz      = 1.0 / dir.z;
00150   float ac      = dir.x * iz;
00151   float bc      = dir.y * iz;
00152   offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
00153   offset += MAX2( abs(ac), abs(bc) ) * ctx->Polygon.OffsetFactor;
00154   offset *= MRD;
00155 */
00156 static void compute_offset( struct brw_clip_compile *c )
00157 {
00158    struct brw_compile *p = &c->func;
00159    struct brw_reg off = c->reg.offset;
00160    struct brw_reg dir = c->reg.dir;
00161    
00162    brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
00163    brw_MUL(p, vec2(off), dir, get_element(off, 2));
00164 
00165    brw_CMP(p, 
00166            vec1(brw_null_reg()), 
00167            BRW_CONDITIONAL_GE,
00168            brw_abs(get_element(off, 0)), 
00169            brw_abs(get_element(off, 1)));
00170 
00171    brw_SEL(p, vec1(off), brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
00172    brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00173 
00174    brw_MUL(p, vec1(off), off, brw_imm_f(c->key.offset_factor));
00175    brw_ADD(p, vec1(off), off, brw_imm_f(c->key.offset_units));
00176 }
00177 
00178 
00179 static void merge_edgeflags( struct brw_clip_compile *c )
00180 {
00181    struct brw_compile *p = &c->func;
00182    struct brw_instruction *is_poly;
00183    struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
00184 
00185    brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK)); 
00186    brw_CMP(p, 
00187            vec1(brw_null_reg()), 
00188            BRW_CONDITIONAL_EQ, 
00189            tmp0,
00190            brw_imm_ud(_3DPRIM_POLYGON));
00191 
00192    /* Get away with using reg.vertex because we know that this is not
00193     * a _3DPRIM_TRISTRIP_REVERSE:
00194     */
00195    is_poly = brw_IF(p, BRW_EXECUTE_1);
00196    {   
00197       brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
00198       brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
00199       brw_MOV(p, byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
00200       brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00201 
00202       brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
00203       brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
00204       brw_MOV(p, byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
00205       brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00206    }
00207    brw_ENDIF(p, is_poly);
00208 }
00209 
00210 
00211 
00212 static void apply_one_offset( struct brw_clip_compile *c,
00213                           struct brw_indirect vert )
00214 {
00215    struct brw_compile *p = &c->func;
00216    struct brw_reg pos = deref_4f(vert, c->offset[VERT_RESULT_HPOS]);
00217    struct brw_reg z = get_element(pos, 2);
00218 
00219    brw_ADD(p, z, z, vec1(c->reg.offset));
00220 }
00221 
00222 
00223 
00224 /***********************************************************************
00225  * Output clipped polygon as an unfilled primitive:
00226  */
00227 static void emit_lines(struct brw_clip_compile *c,
00228                        boolean do_offset)
00229 {
00230    struct brw_compile *p = &c->func;
00231    struct brw_instruction *loop;
00232    struct brw_instruction *draw_edge;
00233    struct brw_indirect v0 = brw_indirect(0, 0);
00234    struct brw_indirect v1 = brw_indirect(1, 0);
00235    struct brw_indirect v0ptr = brw_indirect(2, 0);
00236    struct brw_indirect v1ptr = brw_indirect(3, 0);
00237 
00238    /* Need a seperate loop for offset:
00239     */
00240    if (do_offset) {
00241       brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00242       brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00243 
00244       loop = brw_DO(p, BRW_EXECUTE_1);
00245       {
00246          brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00247          brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00248             
00249          apply_one_offset(c, v0);
00250             
00251          brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
00252          brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00253       }
00254       brw_WHILE(p, loop);
00255    }
00256 
00257    /* v1ptr = &inlist[nr_verts]
00258     * *v1ptr = v0
00259     */
00260    brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00261    brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00262    brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
00263    brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
00264    brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
00265 
00266    loop = brw_DO(p, BRW_EXECUTE_1);
00267    {
00268       brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00269       brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
00270       brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00271 
00272       /* draw edge if edgeflag != 0 */
00273       brw_CMP(p, 
00274               vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 
00275               deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
00276               brw_imm_f(0));
00277       draw_edge = brw_IF(p, BRW_EXECUTE_1);
00278       {
00279          brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
00280          brw_clip_emit_vue(c, v1, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
00281       }
00282       brw_ENDIF(p, draw_edge);
00283 
00284       brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
00285       brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00286    }
00287    brw_WHILE(p, loop);
00288 }
00289 
00290 
00291 
00292 static void emit_points(struct brw_clip_compile *c,
00293                         boolean do_offset )
00294 {
00295    struct brw_compile *p = &c->func;
00296    struct brw_instruction *loop;
00297    struct brw_instruction *draw_point;
00298 
00299    struct brw_indirect v0 = brw_indirect(0, 0);
00300    struct brw_indirect v0ptr = brw_indirect(2, 0);
00301 
00302    brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00303    brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00304 
00305    loop = brw_DO(p, BRW_EXECUTE_1);
00306    {
00307       brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00308       brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00309 
00310       /* draw if edgeflag != 0 
00311        */
00312       brw_CMP(p, 
00313               vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, 
00314               deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
00315               brw_imm_f(0));
00316       draw_point = brw_IF(p, BRW_EXECUTE_1);
00317       {
00318          if (do_offset)
00319             apply_one_offset(c, v0);
00320 
00321          brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END);
00322       }
00323       brw_ENDIF(p, draw_point);
00324 
00325       brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
00326       brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00327    }
00328    brw_WHILE(p, loop);
00329 }
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 static void emit_primitives( struct brw_clip_compile *c,
00338                              unsigned mode, 
00339                              boolean do_offset )
00340 {
00341    switch (mode) {
00342    case CLIP_FILL:
00343       brw_clip_tri_emit_polygon(c);
00344       break;
00345 
00346    case CLIP_LINE:
00347       emit_lines(c, do_offset);
00348       break;
00349 
00350    case CLIP_POINT:
00351       emit_points(c, do_offset);
00352       break;
00353 
00354    case CLIP_CULL:
00355       assert(0);
00356       break;
00357    }
00358 } 
00359 
00360 
00361 
00362 static void emit_unfilled_primitives( struct brw_clip_compile *c )
00363 {
00364    struct brw_compile *p = &c->func;
00365    struct brw_instruction *ccw;
00366 
00367    /* Direction culling has already been done.
00368     */
00369    if (c->key.fill_ccw != c->key.fill_cw &&
00370        c->key.fill_ccw != CLIP_CULL &&
00371        c->key.fill_cw != CLIP_CULL)
00372    {
00373       brw_CMP(p,
00374               vec1(brw_null_reg()),
00375               BRW_CONDITIONAL_GE,
00376               get_element(c->reg.dir, 2),
00377               brw_imm_f(0));
00378    
00379       ccw = brw_IF(p, BRW_EXECUTE_1);
00380       {
00381          emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
00382       }
00383       ccw = brw_ELSE(p, ccw);
00384       {
00385          emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
00386       }
00387       brw_ENDIF(p, ccw);
00388    }
00389    else if (c->key.fill_cw != CLIP_CULL) {
00390       emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
00391    }
00392    else if (c->key.fill_ccw != CLIP_CULL) { 
00393       emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
00394    }
00395 }
00396 
00397 
00398 
00399 
00400 static void check_nr_verts( struct brw_clip_compile *c )
00401 {
00402    struct brw_compile *p = &c->func;
00403    struct brw_instruction *if_insn;
00404 
00405    brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));      
00406    if_insn = brw_IF(p, BRW_EXECUTE_1);
00407    {
00408       brw_clip_kill_thread(c);
00409    }
00410    brw_ENDIF(p, if_insn);
00411 }
00412 
00413 
00414 void brw_emit_unfilled_clip( struct brw_clip_compile *c )
00415 {
00416    struct brw_compile *p = &c->func;
00417    struct brw_instruction *do_clip;
00418    
00419 
00420    c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
00421                         (c->key.fill_ccw != c->key.fill_cw) ||
00422                         c->key.fill_ccw == CLIP_CULL ||
00423                         c->key.fill_cw == CLIP_CULL ||
00424                         c->key.copy_bfc_cw ||
00425                         c->key.copy_bfc_ccw);
00426 
00427    brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
00428    brw_clip_tri_init_vertices(c);
00429 
00430    assert(c->offset[VERT_RESULT_EDGE]);
00431 
00432    if (c->key.fill_ccw == CLIP_CULL &&
00433        c->key.fill_cw == CLIP_CULL) {
00434       brw_clip_kill_thread(c);
00435       return;
00436    }
00437 
00438    merge_edgeflags(c);
00439 
00440    /* Need to use the inlist indirection here: 
00441     */
00442    if (c->need_direction) 
00443       compute_tri_direction(c);
00444    
00445    if (c->key.fill_ccw == CLIP_CULL ||
00446        c->key.fill_cw == CLIP_CULL)
00447       cull_direction(c);
00448 
00449    if (c->key.offset_ccw ||
00450        c->key.offset_cw)
00451       compute_offset(c);
00452 
00453    if (c->key.copy_bfc_ccw ||
00454        c->key.copy_bfc_cw)
00455       copy_bfc(c);
00456 
00457    /* Need to do this whether we clip or not:
00458     */
00459    if (c->key.do_flat_shading)
00460       brw_clip_tri_flat_shade(c);
00461    
00462    brw_clip_init_clipmask(c);
00463    brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
00464    do_clip = brw_IF(p, BRW_EXECUTE_1);
00465    {
00466       brw_clip_init_planes(c);
00467       brw_clip_tri(c);
00468       check_nr_verts(c);
00469    }
00470    brw_ENDIF(p, do_clip);
00471    
00472    emit_unfilled_primitives(c);
00473    brw_clip_kill_thread(c);
00474 }
00475 
00476 
00477 

Generated on Tue Sep 29 06:25:16 2009 for Gallium3D by  doxygen 1.5.4