Home | History | Annotate | Download | only in core
      1 /****************************************************************************
      2 * Copyright (C) 2014-2015 Intel Corporation.   All Rights Reserved.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the next
     12 * paragraph) shall be included in all copies or substantial portions of the
     13 * Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21 * IN THE SOFTWARE.
     22 *
     23 * @file clip.cpp
     24 *
     25 * @brief Implementation for clipping
     26 *
     27 ******************************************************************************/
     28 
     29 #include <assert.h>
     30 
     31 #include "common/os.h"
     32 #include "core/clip.h"
     33 
     34 // Temp storage used by the clipper
     35 THREAD SIMDVERTEX_T<SIMD256> tlsTempVertices[7];
     36 #if USE_SIMD16_FRONTEND
     37 THREAD SIMDVERTEX_T<SIMD512> tlsTempVertices_simd16[7];
     38 #endif
     39 
     40 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
     41 {
     42     return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
     43 }
     44 
     45 template<SWR_CLIPCODES ClippingPlane>
     46 inline void intersect(
     47     int s,                       // index to first edge vertex v0 in pInPts.
     48     int p,                       // index to second edge vertex v1 in pInPts.
     49     const float *pInPts,         // array of all the input positions.
     50     const float *pInAttribs,     // array of all attributes for all vertex. All the attributes for each vertex is contiguous.
     51     int numInAttribs,            // number of attributes per vertex.
     52     int i,                       // output index.
     53     float *pOutPts,              // array of output positions. We'll write our new intersection point at i*4.
     54     float *pOutAttribs)          // array of output attributes. We'll write our new attributes at i*numInAttribs.
     55 {
     56     float t;
     57 
     58     // Find the parameter of the intersection.
     59     //        t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
     60     const float *v1 = &pInPts[s*4];
     61     const float *v2 = &pInPts[p*4];
     62 
     63     switch (ClippingPlane)
     64     {
     65     case FRUSTUM_LEFT:      t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]); break;
     66     case FRUSTUM_RIGHT:     t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]); break;
     67     case FRUSTUM_TOP:       t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]); break;
     68     case FRUSTUM_BOTTOM:    t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]); break;
     69     case FRUSTUM_NEAR:      t = ComputeInterpFactor(v1[2], v2[2]); break;
     70     case FRUSTUM_FAR:       t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]); break;
     71     default: SWR_INVALID("invalid clipping plane: %d", ClippingPlane);
     72     };
     73 
     74 
     75     const float *a1 = &pInAttribs[s*numInAttribs];
     76     const float *a2 = &pInAttribs[p*numInAttribs];
     77 
     78     float *pOutP    = &pOutPts[i*4];
     79     float *pOutA    = &pOutAttribs[i*numInAttribs];
     80 
     81     // Interpolate new position.
     82     for(int j = 0; j < 4; ++j)
     83     {
     84         pOutP[j] = v1[j] + (v2[j]-v1[j])*t;
     85     }
     86 
     87     // Interpolate Attributes
     88     for(int attr = 0; attr < numInAttribs; ++attr)
     89     {
     90         pOutA[attr] = a1[attr] + (a2[attr]-a1[attr])*t;
     91     }
     92 }
     93 
     94 
     95 // Checks whether vertex v lies inside clipping plane
     96 // in homogenous coords check -w < {x,y,z} < w;
     97 //
     98 template<SWR_CLIPCODES ClippingPlane>
     99 inline int inside(const float v[4])
    100 {
    101     switch (ClippingPlane)
    102     {
    103     case FRUSTUM_LEFT   : return (v[0]>=-v[3]);
    104     case FRUSTUM_RIGHT  : return (v[0]<= v[3]);
    105     case FRUSTUM_TOP    : return (v[1]>=-v[3]);
    106     case FRUSTUM_BOTTOM : return (v[1]<= v[3]);
    107     case FRUSTUM_NEAR   : return (v[2]>=0.0f);
    108     case FRUSTUM_FAR    : return (v[2]<= v[3]);
    109     default:
    110         SWR_INVALID("invalid clipping plane: %d", ClippingPlane);
    111         return 0;
    112     }
    113 }
    114 
    115 
    116 // Clips a polygon in homogenous coordinates to a particular clipping plane.
    117 // Takes in vertices of the polygon (InPts) and the clipping plane
    118 // Puts the vertices of the clipped polygon in OutPts
    119 // Returns number of points in clipped polygon
    120 //
    121 template<SWR_CLIPCODES ClippingPlane>
    122 int ClipTriToPlane( const float *pInPts, int numInPts,
    123                     const float *pInAttribs, int numInAttribs,
    124                     float *pOutPts, float *pOutAttribs)
    125 {
    126     int i=0; // index number of OutPts, # of vertices in OutPts = i div 4;
    127 
    128     for (int j = 0; j < numInPts; ++j)
    129     {
    130         int s = j;
    131         int p = (j + 1) % numInPts;
    132 
    133         int s_in = inside<ClippingPlane>(&pInPts[s*4]);
    134         int p_in = inside<ClippingPlane>(&pInPts[p*4]);
    135 
    136         // test if vertex is to be added to output vertices
    137         if (s_in != p_in)  // edge crosses clipping plane
    138         {
    139             // find point of intersection
    140             intersect<ClippingPlane>(s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs);
    141             i++;
    142         }
    143         if (p_in) // 2nd vertex is inside clipping volume, add it to output
    144         {
    145             // Copy 2nd vertex position of edge over to output.
    146             for(int k = 0; k < 4; ++k)
    147             {
    148                 pOutPts[i*4 + k] = pInPts[p*4 + k];
    149             }
    150             // Copy 2nd vertex attributes of edge over to output.
    151             for(int attr = 0; attr < numInAttribs; ++attr)
    152             {
    153                 pOutAttribs[i*numInAttribs+attr] = pInAttribs[p*numInAttribs+attr];
    154             }
    155             i++;
    156         }
    157         // edge does not cross clipping plane and vertex outside clipping volume
    158         //  => do not add vertex
    159     }
    160     return i;
    161 }
    162 
    163 void ClipTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask,
    164                    simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx)
    165 {
    166     SWR_CONTEXT *pContext = pDC->pContext;
    167     AR_BEGIN(FEClipTriangles, pDC->drawId);
    168     Clipper<SIMD256, 3> clipper(workerId, pDC);
    169     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    170     AR_END(FEClipTriangles, 1);
    171 }
    172 
    173 void ClipLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask,
    174                simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx)
    175 {
    176     SWR_CONTEXT *pContext = pDC->pContext;
    177     AR_BEGIN(FEClipLines, pDC->drawId);
    178     Clipper<SIMD256, 2> clipper(workerId, pDC);
    179     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    180     AR_END(FEClipLines, 1);
    181 }
    182 
    183 void ClipPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask,
    184                 simdscalari const &primId, simdscalari const &viewportIdx, simdscalari const &rtIdx)
    185 {
    186     SWR_CONTEXT *pContext = pDC->pContext;
    187     AR_BEGIN(FEClipPoints, pDC->drawId);
    188     Clipper<SIMD256, 1> clipper(workerId, pDC);
    189     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    190     AR_END(FEClipPoints, 1);
    191 }
    192 
    193 #if USE_SIMD16_FRONTEND
    194 void SIMDCALL ClipTriangles_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask,
    195                                    simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx)
    196 {
    197     SWR_CONTEXT *pContext = pDC->pContext;
    198     AR_BEGIN(FEClipTriangles, pDC->drawId);
    199 
    200     enum { VERTS_PER_PRIM = 3 };
    201 
    202     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
    203 
    204     pa.useAlternateOffset = false;
    205     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    206 
    207     AR_END(FEClipTriangles, 1);
    208 }
    209 
    210 void SIMDCALL ClipLines_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask,
    211                                simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx)
    212 {
    213     SWR_CONTEXT *pContext = pDC->pContext;
    214     AR_BEGIN(FEClipLines, pDC->drawId);
    215 
    216     enum { VERTS_PER_PRIM = 2 };
    217 
    218     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
    219 
    220     pa.useAlternateOffset = false;
    221     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    222 
    223     AR_END(FEClipLines, 1);
    224 }
    225 
    226 void SIMDCALL ClipPoints_simd16(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simd16vector prims[], uint32_t primMask,
    227                                 simd16scalari const &primId, simd16scalari const &viewportIdx, simd16scalari const &rtIdx)
    228 {
    229     SWR_CONTEXT *pContext = pDC->pContext;
    230     AR_BEGIN(FEClipPoints, pDC->drawId);
    231 
    232     enum { VERTS_PER_PRIM = 1 };
    233 
    234     Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC);
    235 
    236     pa.useAlternateOffset = false;
    237     clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx);
    238 
    239     AR_END(FEClipPoints, 1);
    240 }
    241 
    242 #endif
    243