Subversion Repositories Kolibri OS

Rev

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