17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
47117f1b4Smrg * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
57117f1b4Smrg *
67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
87117f1b4Smrg * to deal in the Software without restriction, including without limitation
97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
117117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
127117f1b4Smrg *
137117f1b4Smrg * The above copyright notice and this permission notice shall be included
147117f1b4Smrg * in all copies or substantial portions of the Software.
157117f1b4Smrg *
167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg */
247117f1b4Smrg
257117f1b4Smrg/*
267117f1b4Smrg * New (3.1) transformation code written by Keith Whitwell.
277117f1b4Smrg */
287117f1b4Smrg
297117f1b4Smrg
307117f1b4Smrg/* KW: a clever asm implementation would nestle integer versions
317117f1b4Smrg * of the outcode calculation underneath the division.  Gcc won't
327117f1b4Smrg * do this, strangely enough, so I only do the divide in
337117f1b4Smrg * the case where the cliptest passes.  This isn't essential,
347117f1b4Smrg * and an asm implementation needn't replicate that behaviour.
357117f1b4Smrg *
367117f1b4Smrg * \param clip_vec vector of incoming clip-space coords
377117f1b4Smrg * \param proj_vec vector of resultant NDC-space projected coords
387117f1b4Smrg * \param clipMask resulting array of clip flags
397117f1b4Smrg * \param orMask bitwise-OR of clipMask values
407117f1b4Smrg * \param andMask bitwise-AND of clipMask values
417117f1b4Smrg * \return proj_vec pointer
427117f1b4Smrg */
4301e04c3fSmrgstatic GLvector4f * TAG(cliptest_points4)( GLvector4f *clip_vec,
447117f1b4Smrg                                                     GLvector4f *proj_vec,
457117f1b4Smrg                                                     GLubyte clipMask[],
467117f1b4Smrg                                                     GLubyte *orMask,
474a49301eSmrg                                                     GLubyte *andMask,
484a49301eSmrg						     GLboolean viewport_z_clip )
497117f1b4Smrg{
507117f1b4Smrg   const GLuint stride = clip_vec->stride;
517117f1b4Smrg   const GLfloat *from = (GLfloat *)clip_vec->start;
527117f1b4Smrg   const GLuint count = clip_vec->count;
537117f1b4Smrg   GLuint c = 0;
547117f1b4Smrg   GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
557117f1b4Smrg   GLubyte tmpAndMask = *andMask;
567117f1b4Smrg   GLubyte tmpOrMask = *orMask;
577117f1b4Smrg   GLuint i;
587117f1b4Smrg   STRIDE_LOOP {
597117f1b4Smrg      const GLfloat cx = from[0];
607117f1b4Smrg      const GLfloat cy = from[1];
617117f1b4Smrg      const GLfloat cz = from[2];
627117f1b4Smrg      const GLfloat cw = from[3];
63af69d88dSmrg#if defined(__powerpc__)
647117f1b4Smrg      /* on powerpc cliptest is 17% faster in this way. */
657117f1b4Smrg      GLuint mask;
667117f1b4Smrg      mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
677117f1b4Smrg      mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
687117f1b4Smrg      mask |= (((cw < cy) << CLIP_TOP_SHIFT));
697117f1b4Smrg      mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
704a49301eSmrg      if (viewport_z_clip) {
714a49301eSmrg	 mask |= (((cw < cz) << CLIP_FAR_SHIFT));
724a49301eSmrg	 mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
734a49301eSmrg      }
74af69d88dSmrg#else
757117f1b4Smrg      GLubyte mask = 0;
767117f1b4Smrg      if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
777117f1b4Smrg      if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
787117f1b4Smrg      if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
797117f1b4Smrg      if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
804a49301eSmrg      if (viewport_z_clip) {
814a49301eSmrg	 if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
824a49301eSmrg	 if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
834a49301eSmrg      }
84af69d88dSmrg#endif
857117f1b4Smrg
867117f1b4Smrg      clipMask[i] = mask;
877117f1b4Smrg      if (mask) {
887117f1b4Smrg	 c++;
897117f1b4Smrg	 tmpAndMask &= mask;
907117f1b4Smrg	 tmpOrMask |= mask;
917117f1b4Smrg	 vProj[i][0] = 0;
927117f1b4Smrg	 vProj[i][1] = 0;
937117f1b4Smrg	 vProj[i][2] = 0;
947117f1b4Smrg	 vProj[i][3] = 1;
957117f1b4Smrg      } else {
967117f1b4Smrg	 GLfloat oow = 1.0F / cw;
977117f1b4Smrg	 vProj[i][0] = cx * oow;
987117f1b4Smrg	 vProj[i][1] = cy * oow;
997117f1b4Smrg	 vProj[i][2] = cz * oow;
1007117f1b4Smrg	 vProj[i][3] = oow;
1017117f1b4Smrg      }
1027117f1b4Smrg   }
1037117f1b4Smrg
1047117f1b4Smrg   *orMask = tmpOrMask;
1057117f1b4Smrg   *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
1067117f1b4Smrg
1077117f1b4Smrg   proj_vec->flags |= VEC_SIZE_4;
1087117f1b4Smrg   proj_vec->size = 4;
1097117f1b4Smrg   proj_vec->count = clip_vec->count;
1107117f1b4Smrg   return proj_vec;
1117117f1b4Smrg}
1127117f1b4Smrg
1137117f1b4Smrg
1147117f1b4Smrg
1157117f1b4Smrg/*
1167117f1b4Smrg * \param clip_vec vector of incoming clip-space coords
1177117f1b4Smrg * \param proj_vec vector of resultant NDC-space projected coords
1187117f1b4Smrg * \param clipMask resulting array of clip flags
1197117f1b4Smrg * \param orMask bitwise-OR of clipMask values
1207117f1b4Smrg * \param andMask bitwise-AND of clipMask values
1217117f1b4Smrg * \return clip_vec pointer
1227117f1b4Smrg */
12301e04c3fSmrgstatic GLvector4f * TAG(cliptest_np_points4)( GLvector4f *clip_vec,
1247117f1b4Smrg							GLvector4f *proj_vec,
1257117f1b4Smrg							GLubyte clipMask[],
1267117f1b4Smrg							GLubyte *orMask,
1274a49301eSmrg							GLubyte *andMask,
1284a49301eSmrg							GLboolean viewport_z_clip )
1297117f1b4Smrg{
1307117f1b4Smrg   const GLuint stride = clip_vec->stride;
1317117f1b4Smrg   const GLuint count = clip_vec->count;
1327117f1b4Smrg   const GLfloat *from = (GLfloat *)clip_vec->start;
1337117f1b4Smrg   GLuint c = 0;
1347117f1b4Smrg   GLubyte tmpAndMask = *andMask;
1357117f1b4Smrg   GLubyte tmpOrMask = *orMask;
1367117f1b4Smrg   GLuint i;
1377117f1b4Smrg   (void) proj_vec;
1387117f1b4Smrg   STRIDE_LOOP {
1397117f1b4Smrg      const GLfloat cx = from[0];
1407117f1b4Smrg      const GLfloat cy = from[1];
1417117f1b4Smrg      const GLfloat cz = from[2];
1427117f1b4Smrg      const GLfloat cw = from[3];
143af69d88dSmrg#if defined(__powerpc__)
1447117f1b4Smrg      /* on powerpc cliptest is 17% faster in this way. */
1457117f1b4Smrg      GLuint mask;
1467117f1b4Smrg      mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
1477117f1b4Smrg      mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
1487117f1b4Smrg      mask |= (((cw < cy) << CLIP_TOP_SHIFT));
1497117f1b4Smrg      mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
1504a49301eSmrg      if (viewport_z_clip) {
1514a49301eSmrg	 mask |= (((cw < cz) << CLIP_FAR_SHIFT));
1524a49301eSmrg	 mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
1534a49301eSmrg      }
154af69d88dSmrg#else
1557117f1b4Smrg      GLubyte mask = 0;
1567117f1b4Smrg      if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
1577117f1b4Smrg      if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
1587117f1b4Smrg      if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
1597117f1b4Smrg      if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
1604a49301eSmrg      if (viewport_z_clip) {
1614a49301eSmrg	 if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
1624a49301eSmrg	 if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
1634a49301eSmrg      }
164af69d88dSmrg#endif
1657117f1b4Smrg
1667117f1b4Smrg      clipMask[i] = mask;
1677117f1b4Smrg      if (mask) {
1687117f1b4Smrg	 c++;
1697117f1b4Smrg	 tmpAndMask &= mask;
1707117f1b4Smrg	 tmpOrMask |= mask;
1717117f1b4Smrg      }
1727117f1b4Smrg   }
1737117f1b4Smrg
1747117f1b4Smrg   *orMask = tmpOrMask;
1757117f1b4Smrg   *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
1767117f1b4Smrg   return clip_vec;
1777117f1b4Smrg}
1787117f1b4Smrg
1797117f1b4Smrg
18001e04c3fSmrgstatic GLvector4f * TAG(cliptest_points3)( GLvector4f *clip_vec,
1817117f1b4Smrg                                                     GLvector4f *proj_vec,
1827117f1b4Smrg                                                     GLubyte clipMask[],
1837117f1b4Smrg                                                     GLubyte *orMask,
1844a49301eSmrg                                                     GLubyte *andMask,
1854a49301eSmrg						     GLboolean viewport_z_clip )
1867117f1b4Smrg{
1877117f1b4Smrg   const GLuint stride = clip_vec->stride;
1887117f1b4Smrg   const GLuint count = clip_vec->count;
1897117f1b4Smrg   const GLfloat *from = (GLfloat *)clip_vec->start;
1907117f1b4Smrg   GLubyte tmpOrMask = *orMask;
1917117f1b4Smrg   GLubyte tmpAndMask = *andMask;
1927117f1b4Smrg   GLuint i;
1937117f1b4Smrg   (void) proj_vec;
1947117f1b4Smrg   STRIDE_LOOP {
1957117f1b4Smrg      const GLfloat cx = from[0], cy = from[1], cz = from[2];
1967117f1b4Smrg      GLubyte mask = 0;
19701e04c3fSmrg      if (cx >  1.0F)       mask |= CLIP_RIGHT_BIT;
19801e04c3fSmrg      else if (cx < -1.0F)  mask |= CLIP_LEFT_BIT;
19901e04c3fSmrg      if (cy >  1.0F)       mask |= CLIP_TOP_BIT;
20001e04c3fSmrg      else if (cy < -1.0F)  mask |= CLIP_BOTTOM_BIT;
2014a49301eSmrg      if (viewport_z_clip) {
20201e04c3fSmrg	 if (cz >  1.0F)       mask |= CLIP_FAR_BIT;
20301e04c3fSmrg	 else if (cz < -1.0F)  mask |= CLIP_NEAR_BIT;
2044a49301eSmrg      }
2057117f1b4Smrg      clipMask[i] = mask;
2067117f1b4Smrg      tmpOrMask |= mask;
2077117f1b4Smrg      tmpAndMask &= mask;
2087117f1b4Smrg   }
2097117f1b4Smrg
2107117f1b4Smrg   *orMask = tmpOrMask;
2117117f1b4Smrg   *andMask = tmpAndMask;
2127117f1b4Smrg   return clip_vec;
2137117f1b4Smrg}
2147117f1b4Smrg
2157117f1b4Smrg
21601e04c3fSmrgstatic GLvector4f * TAG(cliptest_points2)( GLvector4f *clip_vec,
2177117f1b4Smrg                                                     GLvector4f *proj_vec,
2187117f1b4Smrg                                                     GLubyte clipMask[],
2197117f1b4Smrg                                                     GLubyte *orMask,
2204a49301eSmrg                                                     GLubyte *andMask,
2214a49301eSmrg						     GLboolean viewport_z_clip )
2227117f1b4Smrg{
2237117f1b4Smrg   const GLuint stride = clip_vec->stride;
2247117f1b4Smrg   const GLuint count = clip_vec->count;
2257117f1b4Smrg   const GLfloat *from = (GLfloat *)clip_vec->start;
2267117f1b4Smrg   GLubyte tmpOrMask = *orMask;
2277117f1b4Smrg   GLubyte tmpAndMask = *andMask;
2287117f1b4Smrg   GLuint i;
2297117f1b4Smrg   (void) proj_vec;
2307117f1b4Smrg   STRIDE_LOOP {
2317117f1b4Smrg      const GLfloat cx = from[0], cy = from[1];
2327117f1b4Smrg      GLubyte mask = 0;
23301e04c3fSmrg      if (cx >  1.0F)       mask |= CLIP_RIGHT_BIT;
23401e04c3fSmrg      else if (cx < -1.0F)  mask |= CLIP_LEFT_BIT;
23501e04c3fSmrg      if (cy >  1.0F)       mask |= CLIP_TOP_BIT;
23601e04c3fSmrg      else if (cy < -1.0F)  mask |= CLIP_BOTTOM_BIT;
2377117f1b4Smrg      clipMask[i] = mask;
2387117f1b4Smrg      tmpOrMask |= mask;
2397117f1b4Smrg      tmpAndMask &= mask;
2407117f1b4Smrg   }
2417117f1b4Smrg
2427117f1b4Smrg   *orMask = tmpOrMask;
2437117f1b4Smrg   *andMask = tmpAndMask;
2447117f1b4Smrg   return clip_vec;
2457117f1b4Smrg}
2467117f1b4Smrg
2477117f1b4Smrg
2484a49301eSmrgvoid TAG(init_c_cliptest)( void )
2497117f1b4Smrg{
2507117f1b4Smrg   _mesa_clip_tab[4] = TAG(cliptest_points4);
2517117f1b4Smrg   _mesa_clip_tab[3] = TAG(cliptest_points3);
2527117f1b4Smrg   _mesa_clip_tab[2] = TAG(cliptest_points2);
2537117f1b4Smrg
2547117f1b4Smrg   _mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
2557117f1b4Smrg   _mesa_clip_np_tab[3] = TAG(cliptest_points3);
2567117f1b4Smrg   _mesa_clip_np_tab[2] = TAG(cliptest_points2);
2577117f1b4Smrg}
258