gallium/swr: add OpenSWR rasterizer
[mesa.git] / src / gallium / drivers / swr / rasterizer / core / clip.cpp
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 float ComputeInterpFactor(float boundaryCoord0, float boundaryCoord1)
35 {
36 return (boundaryCoord0 / (boundaryCoord0 - boundaryCoord1));
37 }
38
39 template<SWR_CLIPCODES ClippingPlane>
40 inline void intersect(
41 int s, // index to first edge vertex v0 in pInPts.
42 int p, // index to second edge vertex v1 in pInPts.
43 const float *pInPts, // array of all the input positions.
44 const float *pInAttribs, // array of all attributes for all vertex. All the attributes for each vertex is contiguous.
45 int numInAttribs, // number of attributes per vertex.
46 int i, // output index.
47 float *pOutPts, // array of output positions. We'll write our new intersection point at i*4.
48 float *pOutAttribs) // array of output attributes. We'll write our new attributes at i*numInAttribs.
49 {
50 float t;
51
52 // Find the parameter of the intersection.
53 // t = (v1.w - v1.x) / ((v2.x - v1.x) - (v2.w - v1.w)) for x = w (RIGHT) plane, etc.
54 const float *v1 = &pInPts[s*4];
55 const float *v2 = &pInPts[p*4];
56
57 switch (ClippingPlane)
58 {
59 case FRUSTUM_LEFT: t = ComputeInterpFactor(v1[3] + v1[0], v2[3] + v2[0]); break;
60 case FRUSTUM_RIGHT: t = ComputeInterpFactor(v1[3] - v1[0], v2[3] - v2[0]); break;
61 case FRUSTUM_TOP: t = ComputeInterpFactor(v1[3] + v1[1], v2[3] + v2[1]); break;
62 case FRUSTUM_BOTTOM: t = ComputeInterpFactor(v1[3] - v1[1], v2[3] - v2[1]); break;
63 case FRUSTUM_NEAR: t = ComputeInterpFactor(v1[2], v2[2]); break;
64 case FRUSTUM_FAR: t = ComputeInterpFactor(v1[3] - v1[2], v2[3] - v2[2]); break;
65 default: SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane);
66 };
67
68
69 const float *a1 = &pInAttribs[s*numInAttribs];
70 const float *a2 = &pInAttribs[p*numInAttribs];
71
72 float *pOutP = &pOutPts[i*4];
73 float *pOutA = &pOutAttribs[i*numInAttribs];
74
75 // Interpolate new position.
76 for(int j = 0; j < 4; ++j)
77 {
78 pOutP[j] = v1[j] + (v2[j]-v1[j])*t;
79 }
80
81 // Interpolate Attributes
82 for(int attr = 0; attr < numInAttribs; ++attr)
83 {
84 pOutA[attr] = a1[attr] + (a2[attr]-a1[attr])*t;
85 }
86 }
87
88
89 // Checks whether vertex v lies inside clipping plane
90 // in homogenous coords check -w < {x,y,z} < w;
91 //
92 template<SWR_CLIPCODES ClippingPlane>
93 inline int inside(const float v[4])
94 {
95 switch (ClippingPlane)
96 {
97 case FRUSTUM_LEFT : return (v[0]>=-v[3]);
98 case FRUSTUM_RIGHT : return (v[0]<= v[3]);
99 case FRUSTUM_TOP : return (v[1]>=-v[3]);
100 case FRUSTUM_BOTTOM : return (v[1]<= v[3]);
101 case FRUSTUM_NEAR : return (v[2]>=0.0f);
102 case FRUSTUM_FAR : return (v[2]<= v[3]);
103 default:
104 SWR_ASSERT(false, "invalid clipping plane: %d", ClippingPlane);
105 return 0;
106 }
107 }
108
109
110 // Clips a polygon in homogenous coordinates to a particular clipping plane.
111 // Takes in vertices of the polygon (InPts) and the clipping plane
112 // Puts the vertices of the clipped polygon in OutPts
113 // Returns number of points in clipped polygon
114 //
115 template<SWR_CLIPCODES ClippingPlane>
116 int ClipTriToPlane( const float *pInPts, int numInPts,
117 const float *pInAttribs, int numInAttribs,
118 float *pOutPts, float *pOutAttribs)
119 {
120 int i=0; // index number of OutPts, # of vertices in OutPts = i div 4;
121
122 for (int j = 0; j < numInPts; ++j)
123 {
124 int s = j;
125 int p = (j + 1) % numInPts;
126
127 int s_in = inside<ClippingPlane>(&pInPts[s*4]);
128 int p_in = inside<ClippingPlane>(&pInPts[p*4]);
129
130 // test if vertex is to be added to output vertices
131 if (s_in != p_in) // edge crosses clipping plane
132 {
133 // find point of intersection
134 intersect<ClippingPlane>(s, p, pInPts, pInAttribs, numInAttribs, i, pOutPts, pOutAttribs);
135 i++;
136 }
137 if (p_in) // 2nd vertex is inside clipping volume, add it to output
138 {
139 // Copy 2nd vertex position of edge over to output.
140 for(int k = 0; k < 4; ++k)
141 {
142 pOutPts[i*4 + k] = pInPts[p*4 + k];
143 }
144 // Copy 2nd vertex attributes of edge over to output.
145 for(int attr = 0; attr < numInAttribs; ++attr)
146 {
147 pOutAttribs[i*numInAttribs+attr] = pInAttribs[p*numInAttribs+attr];
148 }
149 i++;
150 }
151 // edge does not cross clipping plane and vertex outside clipping volume
152 // => do not add vertex
153 }
154 return i;
155 }
156
157
158
159 void Clip(const float *pTriangle, const float *pAttribs, int numAttribs, float *pOutTriangles, int *numVerts, float *pOutAttribs)
160 {
161 // temp storage to hold at least 6 sets of vertices, the max number that can be created during clipping
162 OSALIGN(float, 16) tempPts[6 * 4];
163 OSALIGN(float, 16) tempAttribs[6 * KNOB_NUM_ATTRIBUTES * 4];
164
165 // we opt to clip to viewport frustum to produce smaller triangles for rasterization precision
166 int NumOutPts = ClipTriToPlane<FRUSTUM_NEAR>(pTriangle, 3, pAttribs, numAttribs, tempPts, tempAttribs);
167 NumOutPts = ClipTriToPlane<FRUSTUM_FAR>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
168 NumOutPts = ClipTriToPlane<FRUSTUM_LEFT>(pOutTriangles, NumOutPts, pOutAttribs, numAttribs, tempPts, tempAttribs);
169 NumOutPts = ClipTriToPlane<FRUSTUM_RIGHT>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
170 NumOutPts = ClipTriToPlane<FRUSTUM_BOTTOM>(pOutTriangles, NumOutPts, pOutAttribs, numAttribs, tempPts, tempAttribs);
171 NumOutPts = ClipTriToPlane<FRUSTUM_TOP>(tempPts, NumOutPts, tempAttribs, numAttribs, pOutTriangles, pOutAttribs);
172
173 SWR_ASSERT(NumOutPts <= 6);
174
175 *numVerts = NumOutPts;
176 return;
177 }
178
179 void ClipTriangles(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId)
180 {
181 RDTSC_START(FEClipTriangles);
182 Clipper<3> clipper(workerId, pDC);
183 clipper.ExecuteStage(pa, prims, primMask, primId);
184 RDTSC_STOP(FEClipTriangles, 1, 0);
185 }
186
187 void ClipLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId)
188 {
189 RDTSC_START(FEClipLines);
190 Clipper<2> clipper(workerId, pDC);
191 clipper.ExecuteStage(pa, prims, primMask, primId);
192 RDTSC_STOP(FEClipLines, 1, 0);
193 }
194 void ClipPoints(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[], uint32_t primMask, simdscalari primId)
195 {
196 RDTSC_START(FEClipPoints);
197 Clipper<1> clipper(workerId, pDC);
198 clipper.ExecuteStage(pa, prims, primMask, primId);
199 RDTSC_STOP(FEClipPoints, 1, 0);
200 }
201