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