| /**************************************************************************** |
| * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice (including the next |
| * paragraph) shall be included in all copies or substantial portions of the |
| * Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| * IN THE SOFTWARE. |
| * |
| * @file clip.cpp |
| * |
| * @brief Implementation for clipping |
| * |
| ******************************************************************************/ |
| |
| #include <assert.h> |
| |
| #include "common/os.h" |
| #include "core/clip.h" |
| |
| // Temp storage used by the clipper |
| THREAD SIMDVERTEX_T<SIMD256> tlsTempVertices[7]; |
| #if USE_SIMD16_FRONTEND |
| THREAD SIMDVERTEX_T<SIMD512> tlsTempVertices_simd16[7]; |
| #endif |
| |
| float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1) |
| { |
| return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1)); |
| } |
| |
| template <SWR_CLIPCODES ClippingPlane> |
| inline void intersect( |
| int s, // index to first edge vertex v0 in pInPts. |
| int p, // index to second edge vertex v1 in pInPts. |
| const float* pInPts, // array of all the input positions. |
| const float* pInAttribs, // array of all attributes for all vertex. All the attributes for each |
| // vertex is contiguous. |
| int numInAttribs, // number of attributes per vertex. |
| int i, // output index. |
| float* pOutPts, // array of output positions. We'll write our new intersection point at i*4. |
| float* pOutAttribs) // array of output attributes. We'll write our new attributes at |
| // i*numInAttribs. |
| { |
| float t; |
| |
| // Find the parameter of the intersection. |
| // t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc. |
| const float* v1 = &pInPts[s * 4]; |
| const float* v2 = &pInPts[p * 4]; |
| |
| switch (ClippingPlane) |
| { |
| case FRUSTUM_LEFT: |
| t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]); |
| break; |
| case FRUSTUM_RIGHT: |
| t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]); |
| break; |
| case FRUSTUM_TOP: |
| t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]); |
| break; |
| case FRUSTUM_BOTTOM: |
| t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]); |
| break; |
| case FRUSTUM_NEAR: |
| t = ComputeInterpFactor(v1[2], v2[2]); |
| break; |
| case FRUSTUM_FAR: |
| t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]); |
| break; |
| default: |
| SWR_INVALID("invalid clipping plane: %d", ClippingPlane); |
| }; |
| |
| const float* a1 = &pInAttribs[s * numInAttribs]; |
| const float* a2 = &pInAttribs[p * numInAttribs]; |
| |
| float* pOutP = &pOutPts[i * 4]; |
| float* pOutA = &pOutAttribs[i * numInAttribs]; |
| |
| // Interpolate new position. |
| for (int j = 0; j < 4; ++j) |
| { |
| pOutP[j] = v1[j] + (v2[j] - v1[j]) * t; |
| } |
| |
| // Interpolate Attributes |
| for (int attr = 0; attr < numInAttribs; ++attr) |
| { |
| pOutA[attr] = a1[attr] + (a2[attr] - a1[attr]) * t; |
| } |
| } |
| |
| // Checks whether vertex v lies inside clipping plane |
| // in homogenous coords check -w < {x,y,z} < w; |
| // |
| template <SWR_CLIPCODES ClippingPlane> |
| inline int inside(const float v[4]) |
| { |
| switch (ClippingPlane) |
| { |
| case FRUSTUM_LEFT: |
| return (v[0] >= -v[3]); |
| case FRUSTUM_RIGHT: |
| return (v[0] <= v[3]); |
| case FRUSTUM_TOP: |
| return (v[1] >= -v[3]); |
| case FRUSTUM_BOTTOM: |
| return (v[1] <= v[3]); |
| case FRUSTUM_NEAR: |
| return (v[2] >= 0.0f); |
| case FRUSTUM_FAR: |
| return (v[2] <= v[3]); |
| default: |
| SWR_INVALID("invalid clipping plane: %d", ClippingPlane); |
| return 0; |
| } |
| } |
| |
| // Clips a polygon in homogenous coordinates to a particular clipping plane. |
| // Takes in vertices of the polygon (InPts) and the clipping plane |
| // Puts the vertices of the clipped polygon in OutPts |
| // Returns number of points in clipped polygon |
| // |
| template <SWR_CLIPCODES ClippingPlane> |
| int ClipTriToPlane(const float* pInPts, |
| int numInPts, |
| const float* pInAttribs, |
| int numInAttribs, |
| float* pOutPts, |
| float* pOutAttribs) |
| { |
| int i = 0; // index number of OutPts, # of vertices in OutPts = i div 4; |
| |
| for (int j = 0; j < numInPts; ++j) |
| { |
| int s = j; |
| int p = (j + 1) % numInPts; |
| |
| int s_in = inside<ClippingPlane>(&pInPts[s * 4]); |
| int p_in = inside<ClippingPlane>(&pInPts[p * 4]); |
| |
| // test if vertex is to be added to output vertices |
| if (s_in != p_in) // edge crosses clipping plane |
| { |
| // find point of intersection |
| intersect<ClippingPlane>( |
| s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs); |
| i++; |
| } |
| if (p_in) // 2nd vertex is inside clipping volume, add it to output |
| { |
| // Copy 2nd vertex position of edge over to output. |
| for (int k = 0; k < 4; ++k) |
| { |
| pOutPts[i * 4 + k] = pInPts[p * 4 + k]; |
| } |
| // Copy 2nd vertex attributes of edge over to output. |
| for (int attr = 0; attr < numInAttribs; ++attr) |
| { |
| pOutAttribs[i * numInAttribs + attr] = pInAttribs[p * numInAttribs + attr]; |
| } |
| i++; |
| } |
| // edge does not cross clipping plane and vertex outside clipping volume |
| // => do not add vertex |
| } |
| return i; |
| } |
| |
| void ClipRectangles(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simdvector prims[], |
| uint32_t primMask, |
| simdscalari const& primId, |
| simdscalari const& viewportIdx, |
| simdscalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipRectangles, pDC->drawId); |
| Clipper<SIMD256, 3> clipper(workerId, pDC); |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| RDTSC_END(FEClipRectangles, 1); |
| } |
| |
| void ClipTriangles(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simdvector prims[], |
| uint32_t primMask, |
| simdscalari const& primId, |
| simdscalari const& viewportIdx, |
| simdscalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipTriangles, pDC->drawId); |
| Clipper<SIMD256, 3> clipper(workerId, pDC); |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| RDTSC_END(FEClipTriangles, 1); |
| } |
| |
| void ClipLines(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simdvector prims[], |
| uint32_t primMask, |
| simdscalari const& primId, |
| simdscalari const& viewportIdx, |
| simdscalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipLines, pDC->drawId); |
| Clipper<SIMD256, 2> clipper(workerId, pDC); |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| RDTSC_END(FEClipLines, 1); |
| } |
| |
| void ClipPoints(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simdvector prims[], |
| uint32_t primMask, |
| simdscalari const& primId, |
| simdscalari const& viewportIdx, |
| simdscalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipPoints, pDC->drawId); |
| Clipper<SIMD256, 1> clipper(workerId, pDC); |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| RDTSC_END(FEClipPoints, 1); |
| } |
| |
| #if USE_SIMD16_FRONTEND |
| void SIMDCALL ClipRectangles_simd16(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simd16vector prims[], |
| uint32_t primMask, |
| simd16scalari const& primId, |
| simd16scalari const& viewportIdx, |
| simd16scalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipRectangles, pDC->drawId); |
| |
| enum |
| { |
| VERTS_PER_PRIM = 3 |
| }; |
| |
| Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); |
| |
| pa.useAlternateOffset = false; |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| |
| RDTSC_END(FEClipRectangles, 1); |
| } |
| |
| void SIMDCALL ClipTriangles_simd16(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simd16vector prims[], |
| uint32_t primMask, |
| simd16scalari const& primId, |
| simd16scalari const& viewportIdx, |
| simd16scalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipTriangles, pDC->drawId); |
| |
| enum |
| { |
| VERTS_PER_PRIM = 3 |
| }; |
| |
| Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); |
| |
| pa.useAlternateOffset = false; |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| |
| RDTSC_END(FEClipTriangles, 1); |
| } |
| |
| void SIMDCALL ClipLines_simd16(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simd16vector prims[], |
| uint32_t primMask, |
| simd16scalari const& primId, |
| simd16scalari const& viewportIdx, |
| simd16scalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipLines, pDC->drawId); |
| |
| enum |
| { |
| VERTS_PER_PRIM = 2 |
| }; |
| |
| Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); |
| |
| pa.useAlternateOffset = false; |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| |
| RDTSC_END(FEClipLines, 1); |
| } |
| |
| void SIMDCALL ClipPoints_simd16(DRAW_CONTEXT* pDC, |
| PA_STATE& pa, |
| uint32_t workerId, |
| simd16vector prims[], |
| uint32_t primMask, |
| simd16scalari const& primId, |
| simd16scalari const& viewportIdx, |
| simd16scalari const& rtIdx) |
| { |
| RDTSC_BEGIN(FEClipPoints, pDC->drawId); |
| |
| enum |
| { |
| VERTS_PER_PRIM = 1 |
| }; |
| |
| Clipper<SIMD512, VERTS_PER_PRIM> clipper(workerId, pDC); |
| |
| pa.useAlternateOffset = false; |
| clipper.ExecuteStage(pa, prims, primMask, primId, viewportIdx, rtIdx); |
| |
| RDTSC_END(FEClipPoints, 1); |
| } |
| |
| #endif |