Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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. static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
  29.                                  struct draw_vertex_info *info,
  30.                                  const struct draw_prim_info *prim_info )
  31. {
  32.    struct vertex_header *out = info->verts;
  33.    /* const */ float (*plane)[4] = pvs->draw->plane;
  34.    const unsigned pos = draw_current_shader_position_output(pvs->draw);
  35.    const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
  36.    unsigned cd[2];
  37.    const unsigned ef = pvs->draw->vs.edgeflag_output;
  38.    unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
  39.    unsigned flags = (FLAGS);
  40.    unsigned need_pipeline = 0;
  41.    unsigned j;
  42.    unsigned i;
  43.    bool have_cd = false;
  44.    unsigned viewport_index_output =
  45.       draw_current_shader_viewport_index_output(pvs->draw);
  46.    int viewport_index =
  47.       draw_current_shader_uses_viewport_index(pvs->draw) ?
  48.       *((unsigned*)out->data[viewport_index_output]): 0;
  49.    int num_written_clipdistance =
  50.       draw_current_shader_num_written_clipdistances(pvs->draw);
  51.  
  52.    cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
  53.    cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
  54.  
  55.    if (cd[0] != pos || cd[1] != pos)
  56.       have_cd = true;
  57.  
  58.    /* If clipdistance semantic has been written by the shader
  59.     * that means we're expected to do 'user plane clipping' */
  60.    if (num_written_clipdistance && !(flags & DO_CLIP_USER)) {
  61.       flags |= DO_CLIP_USER;
  62.       ucp_enable = (1 << num_written_clipdistance) - 1;
  63.    }
  64.  
  65.    for (j = 0; j < info->count; j++) {
  66.       float *position = out->data[pos];
  67.       unsigned mask = 0x0;
  68.       float *scale = pvs->draw->viewports[0].scale;
  69.       float *trans = pvs->draw->viewports[0].translate;
  70.       if (draw_current_shader_uses_viewport_index(pvs->draw)) {
  71.          unsigned verts_per_prim = u_vertices_per_prim(prim_info->prim);
  72.          /* only change the viewport_index for the leading vertex */
  73.          if (!(j % verts_per_prim)) {
  74.             viewport_index = *((unsigned*)out->data[viewport_index_output]);
  75.             viewport_index = draw_clamp_viewport_idx(viewport_index);
  76.          }
  77.          scale = pvs->draw->viewports[viewport_index].scale;
  78.          trans = pvs->draw->viewports[viewport_index].translate;
  79.       }
  80.  
  81.       initialize_vertex_header(out);
  82.  
  83.       if (flags & (DO_CLIP_XY | DO_CLIP_XY_GUARD_BAND |
  84.                    DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
  85.          float *clipvertex = position;
  86.  
  87.          if ((flags & DO_CLIP_USER) && cv != pos)
  88.             clipvertex = out->data[cv];
  89.  
  90.          for (i = 0; i < 4; i++) {
  91.             out->clip[i] = clipvertex[i];
  92.             out->pre_clip_pos[i] = position[i];
  93.          }
  94.  
  95.          /* Do the hardwired planes first:
  96.           */
  97.          if (flags & DO_CLIP_XY_GUARD_BAND) {
  98.             if (-0.50 * position[0] + position[3] < 0) mask |= (1<<0);
  99.             if ( 0.50 * position[0] + position[3] < 0) mask |= (1<<1);
  100.             if (-0.50 * position[1] + position[3] < 0) mask |= (1<<2);
  101.             if ( 0.50 * position[1] + position[3] < 0) mask |= (1<<3);
  102.          }
  103.          else if (flags & DO_CLIP_XY) {
  104.             if (-position[0] + position[3] < 0) mask |= (1<<0);
  105.             if ( position[0] + position[3] < 0) mask |= (1<<1);
  106.             if (-position[1] + position[3] < 0) mask |= (1<<2);
  107.             if ( position[1] + position[3] < 0) mask |= (1<<3);
  108.          }
  109.  
  110.          /* Clip Z planes according to full cube, half cube or none.
  111.           */
  112.          if (flags & DO_CLIP_FULL_Z) {
  113.             if ( position[2] + position[3] < 0) mask |= (1<<4);
  114.             if (-position[2] + position[3] < 0) mask |= (1<<5);
  115.          }
  116.          else if (flags & DO_CLIP_HALF_Z) {
  117.             if ( position[2]               < 0) mask |= (1<<4);
  118.             if (-position[2] + position[3] < 0) mask |= (1<<5);
  119.          }
  120.  
  121.          if (flags & DO_CLIP_USER) {
  122.             unsigned ucp_mask = ucp_enable;
  123.  
  124.             while (ucp_mask) {
  125.                unsigned plane_idx = ffs(ucp_mask)-1;
  126.                ucp_mask &= ~(1 << plane_idx);
  127.                plane_idx += 6;
  128.  
  129.                /*
  130.                 * for user clipping check if we have a clip distance output
  131.                 * and the shader has written to it, otherwise use clipvertex
  132.                 * to decide when the plane is clipping.
  133.                 */
  134.                if (have_cd && num_written_clipdistance) {
  135.                   float clipdist;
  136.                   i = plane_idx - 6;
  137.                   out->have_clipdist = 1;
  138.                   /* first four clip distance in first vector etc. */
  139.                   if (i < 4)
  140.                      clipdist = out->data[cd[0]][i];
  141.                   else
  142.                      clipdist = out->data[cd[1]][i-4];
  143.                   if (clipdist < 0)
  144.                      mask |= 1 << plane_idx;
  145.                } else {
  146.                   if (dot4(clipvertex, plane[plane_idx]) < 0)
  147.                      mask |= 1 << plane_idx;
  148.                }
  149.             }
  150.          }
  151.  
  152.          out->clipmask = mask;
  153.          need_pipeline |= out->clipmask;
  154.       }
  155.  
  156.       /*
  157.        * Transform the vertex position from clip coords to window coords,
  158.        * if the vertex is unclipped.
  159.        */
  160.       if ((flags & DO_VIEWPORT) && mask == 0)
  161.       {
  162.          /* divide by w */
  163.          float w = 1.0f / position[3];
  164.  
  165.          /* Viewport mapping */
  166.          position[0] = position[0] * w * scale[0] + trans[0];
  167.          position[1] = position[1] * w * scale[1] + trans[1];
  168.          position[2] = position[2] * w * scale[2] + trans[2];
  169.          position[3] = w;
  170.       }
  171. #ifdef DEBUG
  172.       /* For debug builds, set the clipped vertex's window coordinate
  173.        * to NaN to help catch potential errors later.
  174.        */
  175.       else {
  176.          float zero = 0.0f;
  177.          position[0] =
  178.          position[1] =
  179.          position[2] =
  180.          position[3] = zero / zero; /* MSVC doesn't accept 0.0 / 0.0 */
  181.       }
  182. #endif
  183.  
  184.       if ((flags & DO_EDGEFLAG) && ef) {
  185.          const float *edgeflag = out->data[ef];
  186.          out->edgeflag = !(edgeflag[0] != 1.0f);
  187.          need_pipeline |= !out->edgeflag;
  188.       }
  189.  
  190.       out = (struct vertex_header *)( (char *)out + info->stride );
  191.    }
  192.  
  193.    return need_pipeline != 0;
  194. }
  195.  
  196.  
  197. #undef FLAGS
  198. #undef TAG
  199.