Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2010, VMware, inc.
      4  * All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * 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, sub license, 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 portions
     16  * of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     21  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     25  *
     26  **************************************************************************/
     27 
     28 
     29 
     30 static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
     31                                  struct draw_vertex_info *info )
     32 {
     33    struct vertex_header *out = info->verts;
     34    const float *scale = pvs->draw->viewport.scale;
     35    const float *trans = pvs->draw->viewport.translate;
     36    /* const */ float (*plane)[4] = pvs->draw->plane;
     37    const unsigned pos = draw_current_shader_position_output(pvs->draw);
     38    const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
     39    unsigned cd[2];
     40    const unsigned ef = pvs->draw->vs.edgeflag_output;
     41    const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
     42    const unsigned flags = (FLAGS);
     43    unsigned need_pipeline = 0;
     44    unsigned j;
     45    unsigned i;
     46    bool have_cd = false;
     47    cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
     48    cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
     49 
     50    if (cd[0] != pos || cd[1] != pos)
     51      have_cd = true;
     52 
     53    for (j = 0; j < info->count; j++) {
     54       float *position = out->data[pos];
     55       unsigned mask = 0x0;
     56 
     57       initialize_vertex_header(out);
     58 
     59       if (flags & (DO_CLIP_XY | DO_CLIP_XY_GUARD_BAND |
     60                    DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
     61          float *clipvertex = position;
     62 
     63          if ((flags & DO_CLIP_USER) && cv != pos)
     64             clipvertex = out->data[cv];
     65 
     66          for (i = 0; i < 4; i++) {
     67             out->clip[i] = clipvertex[i];
     68             out->pre_clip_pos[i] = position[i];
     69          }
     70 
     71          /* Do the hardwired planes first:
     72           */
     73          if (flags & DO_CLIP_XY_GUARD_BAND) {
     74             if (-0.50 * position[0] + position[3] < 0) mask |= (1<<0);
     75             if ( 0.50 * position[0] + position[3] < 0) mask |= (1<<1);
     76             if (-0.50 * position[1] + position[3] < 0) mask |= (1<<2);
     77             if ( 0.50 * position[1] + position[3] < 0) mask |= (1<<3);
     78          }
     79          else if (flags & DO_CLIP_XY) {
     80             if (-position[0] + position[3] < 0) mask |= (1<<0);
     81             if ( position[0] + position[3] < 0) mask |= (1<<1);
     82             if (-position[1] + position[3] < 0) mask |= (1<<2);
     83             if ( position[1] + position[3] < 0) mask |= (1<<3);
     84          }
     85 
     86          /* Clip Z planes according to full cube, half cube or none.
     87           */
     88          if (flags & DO_CLIP_FULL_Z) {
     89             if ( position[2] + position[3] < 0) mask |= (1<<4);
     90             if (-position[2] + position[3] < 0) mask |= (1<<5);
     91          }
     92          else if (flags & DO_CLIP_HALF_Z) {
     93             if ( position[2]               < 0) mask |= (1<<4);
     94             if (-position[2] + position[3] < 0) mask |= (1<<5);
     95          }
     96 
     97          if (flags & DO_CLIP_USER) {
     98             unsigned ucp_mask = ucp_enable;
     99             int num_written_clipdistance = pvs->draw->vs.vertex_shader->info.num_written_clipdistance;
    100             while (ucp_mask) {
    101                unsigned plane_idx = ffs(ucp_mask)-1;
    102                ucp_mask &= ~(1 << plane_idx);
    103                plane_idx += 6;
    104 
    105                /*
    106                 * for user clipping check if we have a clip distance output
    107                 * and the shader has written to it, otherwise use clipvertex
    108                 * to decide when the plane is clipping.
    109                 */
    110                if (have_cd && num_written_clipdistance) {
    111                   float clipdist;
    112                   i = plane_idx - 6;
    113                   out->have_clipdist = 1;
    114                   /* first four clip distance in first vector etc. */
    115                   if (i < 4)
    116                      clipdist = out->data[cd[0]][i];
    117                   else
    118                      clipdist = out->data[cd[1]][i-4];
    119                   if (clipdist < 0)
    120                      mask |= 1 << plane_idx;
    121                } else {
    122                   if (dot4(clipvertex, plane[plane_idx]) < 0)
    123                      mask |= 1 << plane_idx;
    124                }
    125             }
    126          }
    127 
    128          out->clipmask = mask;
    129          need_pipeline |= out->clipmask;
    130       }
    131 
    132       if ((flags & DO_VIEWPORT) && mask == 0)
    133       {
    134 	 /* divide by w */
    135 	 float w = 1.0f / position[3];
    136 
    137 	 /* Viewport mapping */
    138 	 position[0] = position[0] * w * scale[0] + trans[0];
    139 	 position[1] = position[1] * w * scale[1] + trans[1];
    140 	 position[2] = position[2] * w * scale[2] + trans[2];
    141 	 position[3] = w;
    142       }
    143 
    144       if ((flags & DO_EDGEFLAG) && ef) {
    145          const float *edgeflag = out->data[ef];
    146          out->edgeflag = !(edgeflag[0] != 1.0f);
    147          need_pipeline |= !out->edgeflag;
    148       }
    149 
    150       out = (struct vertex_header *)( (char *)out + info->stride );
    151    }
    152 
    153    return need_pipeline != 0;
    154 }
    155 
    156 
    157 #undef FLAGS
    158 #undef TAG
    159