Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22.  * OTHER DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25.  
  26. /*
  27.  * Antialiased Triangle Rasterizer Template
  28.  *
  29.  * This file is #include'd to generate custom AA triangle rasterizers.
  30.  * NOTE: this code hasn't been optimized yet.  That'll come after it
  31.  * works correctly.
  32.  *
  33.  * The following macros may be defined to indicate what auxillary information
  34.  * must be copmuted across the triangle:
  35.  *    DO_Z         - if defined, compute Z values
  36.  *    DO_ATTRIBS   - if defined, compute texcoords, varying, etc.
  37.  */
  38.  
  39. /*void triangle( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
  40. {
  41.    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
  42.    const GLfloat *p0 = v0->attrib[VARYING_SLOT_POS];
  43.    const GLfloat *p1 = v1->attrib[VARYING_SLOT_POS];
  44.    const GLfloat *p2 = v2->attrib[VARYING_SLOT_POS];
  45.    const SWvertex *vMin, *vMid, *vMax;
  46.    GLint iyMin, iyMax;
  47.    GLfloat yMin, yMax;
  48.    GLboolean ltor;
  49.    GLfloat majDx, majDy;  /* major (i.e. long) edge dx and dy */
  50.    
  51.    SWspan span;
  52.    
  53. #ifdef DO_Z
  54.    GLfloat zPlane[4];
  55. #endif
  56.    GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
  57. #if defined(DO_ATTRIBS)
  58.    GLfloat attrPlane[VARYING_SLOT_MAX][4][4];
  59.    GLfloat wPlane[4];  /* win[3] */
  60. #endif
  61.    GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceCullSign;
  62.    
  63.    (void) swrast;
  64.  
  65.    INIT_SPAN(span, GL_POLYGON);
  66.    span.arrayMask = SPAN_COVERAGE;
  67.  
  68.    /* determine bottom to top order of vertices */
  69.    {
  70.       GLfloat y0 = v0->attrib[VARYING_SLOT_POS][1];
  71.       GLfloat y1 = v1->attrib[VARYING_SLOT_POS][1];
  72.       GLfloat y2 = v2->attrib[VARYING_SLOT_POS][1];
  73.       if (y0 <= y1) {
  74.          if (y1 <= y2) {
  75.             vMin = v0;   vMid = v1;   vMax = v2;   /* y0<=y1<=y2 */
  76.          }
  77.          else if (y2 <= y0) {
  78.             vMin = v2;   vMid = v0;   vMax = v1;   /* y2<=y0<=y1 */
  79.          }
  80.          else {
  81.             vMin = v0;   vMid = v2;   vMax = v1;  bf = -bf; /* y0<=y2<=y1 */
  82.          }
  83.       }
  84.       else {
  85.          if (y0 <= y2) {
  86.             vMin = v1;   vMid = v0;   vMax = v2;  bf = -bf; /* y1<=y0<=y2 */
  87.          }
  88.          else if (y2 <= y1) {
  89.             vMin = v2;   vMid = v1;   vMax = v0;  bf = -bf; /* y2<=y1<=y0 */
  90.          }
  91.          else {
  92.             vMin = v1;   vMid = v2;   vMax = v0;   /* y1<=y2<=y0 */
  93.          }
  94.       }
  95.    }
  96.  
  97.    majDx = vMax->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
  98.    majDy = vMax->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
  99.  
  100.    /* front/back-face determination and cullling */
  101.    {
  102.       const GLfloat botDx = vMid->attrib[VARYING_SLOT_POS][0] - vMin->attrib[VARYING_SLOT_POS][0];
  103.       const GLfloat botDy = vMid->attrib[VARYING_SLOT_POS][1] - vMin->attrib[VARYING_SLOT_POS][1];
  104.       const GLfloat area = majDx * botDy - botDx * majDy;
  105.       /* Do backface culling */
  106.       if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
  107.          return;
  108.       ltor = (GLboolean) (area < 0.0F);
  109.  
  110.       span.facing = area * swrast->_BackfaceSign > 0.0F;
  111.    }
  112.  
  113.    /* Plane equation setup:
  114.     * We evaluate plane equations at window (x,y) coordinates in order
  115.     * to compute color, Z, fog, texcoords, etc.  This isn't terribly
  116.     * efficient but it's easy and reliable.
  117.     */
  118. #ifdef DO_Z
  119.    compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
  120.    span.arrayMask |= SPAN_Z;
  121. #endif
  122.    if (ctx->Light.ShadeModel == GL_SMOOTH) {
  123.       compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
  124.       compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
  125.       compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
  126.       compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
  127.    }
  128.    else {
  129.       constant_plane(v2->color[RCOMP], rPlane);
  130.       constant_plane(v2->color[GCOMP], gPlane);
  131.       constant_plane(v2->color[BCOMP], bPlane);
  132.       constant_plane(v2->color[ACOMP], aPlane);
  133.    }
  134.    span.arrayMask |= SPAN_RGBA;
  135. #if defined(DO_ATTRIBS)
  136.    {
  137.       const GLfloat invW0 = v0->attrib[VARYING_SLOT_POS][3];
  138.       const GLfloat invW1 = v1->attrib[VARYING_SLOT_POS][3];
  139.       const GLfloat invW2 = v2->attrib[VARYING_SLOT_POS][3];
  140.       compute_plane(p0, p1, p2, invW0, invW1, invW2, wPlane);
  141.       span.attrStepX[VARYING_SLOT_POS][3] = plane_dx(wPlane);
  142.       span.attrStepY[VARYING_SLOT_POS][3] = plane_dy(wPlane);
  143.       ATTRIB_LOOP_BEGIN
  144.          GLuint c;
  145.          if (swrast->_InterpMode[attr] == GL_FLAT) {
  146.             for (c = 0; c < 4; c++) {
  147.                constant_plane(v2->attrib[attr][c] * invW2, attrPlane[attr][c]);
  148.             }
  149.          }
  150.          else {
  151.             for (c = 0; c < 4; c++) {
  152.                const GLfloat a0 = v0->attrib[attr][c] * invW0;
  153.                const GLfloat a1 = v1->attrib[attr][c] * invW1;
  154.                const GLfloat a2 = v2->attrib[attr][c] * invW2;
  155.                compute_plane(p0, p1, p2, a0, a1, a2, attrPlane[attr][c]);
  156.             }
  157.          }
  158.          for (c = 0; c < 4; c++) {
  159.             span.attrStepX[attr][c] = plane_dx(attrPlane[attr][c]);
  160.             span.attrStepY[attr][c] = plane_dy(attrPlane[attr][c]);
  161.          }
  162.       ATTRIB_LOOP_END
  163.    }
  164. #endif
  165.  
  166.    /* Begin bottom-to-top scan over the triangle.
  167.     * The long edge will either be on the left or right side of the
  168.     * triangle.  We always scan from the long edge toward the shorter
  169.     * edges, stopping when we find that coverage = 0.  If the long edge
  170.     * is on the left we scan left-to-right.  Else, we scan right-to-left.
  171.     */
  172.    yMin = vMin->attrib[VARYING_SLOT_POS][1];
  173.    yMax = vMax->attrib[VARYING_SLOT_POS][1];
  174.    iyMin = (GLint) yMin;
  175.    iyMax = (GLint) yMax + 1;
  176.  
  177.    if (ltor) {
  178.       /* scan left to right */
  179.       const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
  180.       const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
  181.       const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
  182.       const GLfloat dxdy = majDx / majDy;
  183.       const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
  184.       GLint iy;
  185. #ifdef _OPENMP
  186. #pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
  187. #endif
  188.       for (iy = iyMin; iy < iyMax; iy++) {
  189.          GLfloat x = pMin[0] - (yMin - iy) * dxdy;
  190.          GLint ix, startX = (GLint) (x - xAdj);
  191.          GLuint count;
  192.          GLfloat coverage = 0.0F;
  193.  
  194. #ifdef _OPENMP
  195.          /* each thread needs to use a different (global) SpanArrays variable */
  196.          span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
  197. #endif
  198.          /* skip over fragments with zero coverage */
  199.          while (startX < SWRAST_MAX_WIDTH) {
  200.             coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
  201.             if (coverage > 0.0F)
  202.                break;
  203.             startX++;
  204.          }
  205.  
  206.          /* enter interior of triangle */
  207.          ix = startX;
  208.  
  209. #if defined(DO_ATTRIBS)
  210.          /* compute attributes at left-most fragment */
  211.          span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 0.5F, iy + 0.5F, wPlane);
  212.          ATTRIB_LOOP_BEGIN
  213.             GLuint c;
  214.             for (c = 0; c < 4; c++) {
  215.                span.attrStart[attr][c] = solve_plane(ix + 0.5F, iy + 0.5F, attrPlane[attr][c]);
  216.             }
  217.          ATTRIB_LOOP_END
  218. #endif
  219.  
  220.          count = 0;
  221.          while (coverage > 0.0F) {
  222.             /* (cx,cy) = center of fragment */
  223.             const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
  224.             SWspanarrays *array = span.array;
  225.             array->coverage[count] = coverage;
  226. #ifdef DO_Z
  227.             array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
  228. #endif
  229.             array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
  230.             array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
  231.             array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
  232.             array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
  233.             ix++;
  234.             count++;
  235.             coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
  236.          }
  237.          
  238.          if (ix > startX) {
  239.             span.x = startX;
  240.             span.y = iy;
  241.             span.end = (GLuint) ix - (GLuint) startX;
  242.             _swrast_write_rgba_span(ctx, &span);
  243.          }
  244.       }
  245.    }
  246.    else {
  247.       /* scan right to left */
  248.       const GLfloat *pMin = vMin->attrib[VARYING_SLOT_POS];
  249.       const GLfloat *pMid = vMid->attrib[VARYING_SLOT_POS];
  250.       const GLfloat *pMax = vMax->attrib[VARYING_SLOT_POS];
  251.       const GLfloat dxdy = majDx / majDy;
  252.       const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
  253.       GLint iy;
  254. #ifdef _OPENMP
  255. #pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
  256. #endif
  257.       for (iy = iyMin; iy < iyMax; iy++) {
  258.          GLfloat x = pMin[0] - (yMin - iy) * dxdy;
  259.          GLint ix, left, startX = (GLint) (x + xAdj);
  260.          GLuint count, n;
  261.          GLfloat coverage = 0.0F;
  262.          
  263. #ifdef _OPENMP
  264.          /* each thread needs to use a different (global) SpanArrays variable */
  265.          span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
  266. #endif
  267.          /* make sure we're not past the window edge */
  268.          if (startX >= ctx->DrawBuffer->_Xmax) {
  269.             startX = ctx->DrawBuffer->_Xmax - 1;
  270.          }
  271.  
  272.          /* skip fragments with zero coverage */
  273.          while (startX > 0) {
  274.             coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
  275.             if (coverage > 0.0F)
  276.                break;
  277.             startX--;
  278.          }
  279.          
  280.          /* enter interior of triangle */
  281.          ix = startX;
  282.          count = 0;
  283.          while (coverage > 0.0F) {
  284.             /* (cx,cy) = center of fragment */
  285.             const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
  286.             SWspanarrays *array = span.array;
  287.             ASSERT(ix >= 0);
  288.             array->coverage[ix] = coverage;
  289. #ifdef DO_Z
  290.             array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
  291. #endif
  292.             array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
  293.             array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
  294.             array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
  295.             array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
  296.             ix--;
  297.             count++;
  298.             coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
  299.          }
  300.          
  301. #if defined(DO_ATTRIBS)
  302.          /* compute attributes at left-most fragment */
  303.          span.attrStart[VARYING_SLOT_POS][3] = solve_plane(ix + 1.5F, iy + 0.5F, wPlane);
  304.          ATTRIB_LOOP_BEGIN
  305.             GLuint c;
  306.             for (c = 0; c < 4; c++) {
  307.                span.attrStart[attr][c] = solve_plane(ix + 1.5F, iy + 0.5F, attrPlane[attr][c]);
  308.             }
  309.          ATTRIB_LOOP_END
  310. #endif
  311.  
  312.          if (startX > ix) {
  313.             n = (GLuint) startX - (GLuint) ix;
  314.  
  315.             left = ix + 1;
  316.  
  317.             /* shift all values to the left */
  318.             /* XXX this is temporary */
  319.             {
  320.                SWspanarrays *array = span.array;
  321.                GLint j;
  322.                for (j = 0; j < (GLint) n; j++) {
  323.                   array->coverage[j] = array->coverage[j + left];
  324.                   COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
  325. #ifdef DO_Z
  326.                   array->z[j] = array->z[j + left];
  327. #endif
  328.                }
  329.             }
  330.  
  331.             span.x = left;
  332.             span.y = iy;
  333.             span.end = n;
  334.             _swrast_write_rgba_span(ctx, &span);
  335.          }
  336.       }
  337.    }
  338. }
  339.  
  340.  
  341. #undef DO_Z
  342. #undef DO_ATTRIBS
  343. #undef DO_OCCLUSION_TEST
  344.