1e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
2e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Mesa 3-D graphics library
322a374fc3fdf97a9cc50e9fdc24049c997e6896eBrian * Version:  7.0.3
422144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
5dd34fe8679fa200e55cfaf8e80bbecdecea084e3Brian * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
7e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
8e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * copy of this software and associated documentation files (the "Software"),
9e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * to deal in the Software without restriction, including without limitation
10e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * and/or sell copies of the Software, and to permit persons to whom the
12e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Software is furnished to do so, subject to the following conditions:
1322144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
14e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The above copyright notice and this permission notice shall be included
15e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * in all copies or substantial portions of the Software.
1622144ab7552f0799bcfca506bf4ffa7f70a06649Gareth Hughes *
17e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
24e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
25e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
26e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell/*
27e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * Antialiased Triangle Rasterizer Template
28e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *
29e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * This file is #include'd to generate custom AA triangle rasterizers.
30e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * NOTE: this code hasn't been optimized yet.  That'll come after it
31e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * works correctly.
32e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *
33e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * The following macros may be defined to indicate what auxillary information
34e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell * must be copmuted across the triangle:
35e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell *    DO_Z         - if defined, compute Z values
36eca456b63d41700617987ba45a09e8f2168b9577Brian *    DO_ATTRIBS   - if defined, compute texcoords, varying, etc.
37e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell */
38e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
39f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg/*void triangle( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
40e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell{
41dd34fe8679fa200e55cfaf8e80bbecdecea084e3Brian   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLfloat *p0 = v0->attrib[FRAG_ATTRIB_WPOS];
439e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLfloat *p1 = v1->attrib[FRAG_ATTRIB_WPOS];
449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   const GLfloat *p2 = v2->attrib[FRAG_ATTRIB_WPOS];
45a852378a6289d154364dde440f89a39bbfc33e2dBrian Paul   const SWvertex *vMin, *vMid, *vMax;
46ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   GLint iyMin, iyMax;
47ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   GLfloat yMin, yMax;
48ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   GLboolean ltor;
49ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   GLfloat majDx, majDy;  /* major (i.e. long) edge dx and dy */
5010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
51cdb27e8242215271364602995d85607cfc06d441Brian Paul   SWspan span;
5210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
53e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#ifdef DO_Z
5447cf442c1164b6b406117fccfb8b564602741ee3Brian Paul   GLfloat zPlane[4];
5580532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul#endif
5647cf442c1164b6b406117fccfb8b564602741ee3Brian Paul   GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4];
57eca456b63d41700617987ba45a09e8f2168b9577Brian#if defined(DO_ATTRIBS)
589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat attrPlane[FRAG_ATTRIB_MAX][4][4];
599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   GLfloat wPlane[4];  /* win[3] */
60e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#endif
61fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceCullSign;
6210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
63dd34fe8679fa200e55cfaf8e80bbecdecea084e3Brian   (void) swrast;
64dd34fe8679fa200e55cfaf8e80bbecdecea084e3Brian
65f4b103dc993491355ec3e3640d9cb060138175c2Brian   INIT_SPAN(span, GL_POLYGON);
66f4b103dc993491355ec3e3640d9cb060138175c2Brian   span.arrayMask = SPAN_COVERAGE;
672a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
68e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   /* determine bottom to top order of vertices */
69e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   {
709e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLfloat y0 = v0->attrib[FRAG_ATTRIB_WPOS][1];
719e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLfloat y1 = v1->attrib[FRAG_ATTRIB_WPOS][1];
729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      GLfloat y2 = v2->attrib[FRAG_ATTRIB_WPOS][1];
73e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      if (y0 <= y1) {
74e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 if (y1 <= y2) {
75e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v0;   vMid = v1;   vMax = v2;   /* y0<=y1<=y2 */
76e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
77e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 else if (y2 <= y0) {
78e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v2;   vMid = v0;   vMax = v1;   /* y2<=y0<=y1 */
79e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
80e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 else {
81e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v0;   vMid = v2;   vMax = v1;  bf = -bf; /* y0<=y2<=y1 */
82e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
83e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
84e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      else {
85e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 if (y0 <= y2) {
86e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v1;   vMid = v0;   vMax = v2;  bf = -bf; /* y1<=y0<=y2 */
87e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
88e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 else if (y2 <= y1) {
89e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v2;   vMid = v1;   vMax = v0;  bf = -bf; /* y2<=y1<=y0 */
90e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
91e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 else {
92e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	    vMin = v1;   vMid = v2;   vMax = v0;   /* y1<=y2<=y0 */
93e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell	 }
94e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell      }
95e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
96e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
979e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   majDx = vMax->attrib[FRAG_ATTRIB_WPOS][0] - vMin->attrib[FRAG_ATTRIB_WPOS][0];
989e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   majDy = vMax->attrib[FRAG_ATTRIB_WPOS][1] - vMin->attrib[FRAG_ATTRIB_WPOS][1];
99ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul
100fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian   /* front/back-face determination and cullling */
101ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   {
1029e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat botDx = vMid->attrib[FRAG_ATTRIB_WPOS][0] - vMin->attrib[FRAG_ATTRIB_WPOS][0];
1039e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat botDy = vMid->attrib[FRAG_ATTRIB_WPOS][1] - vMin->attrib[FRAG_ATTRIB_WPOS][1];
104ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      const GLfloat area = majDx * botDy - botDx * majDy;
105ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      /* Do backface culling */
106ef4f5b391e560e535b25b372f797e41edeef09f1Keith Whitwell      if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area))
107ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul	 return;
10802de45dcedc38b0e4ceacba440bfc11930ec90bbBrian Paul      ltor = (GLboolean) (area < 0.0F);
109fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian
110fcd7c37fd3d0f61cf6ac81170bc0b3fca64ad9bbBrian      span.facing = area * swrast->_BackfaceSign > 0.0F;
111ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   }
112e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
11380532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul   /* Plane equation setup:
11480532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * We evaluate plane equations at window (x,y) coordinates in order
11580532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * to compute color, Z, fog, texcoords, etc.  This isn't terribly
116ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul    * efficient but it's easy and reliable.
11780532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    */
118e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#ifdef DO_Z
119e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane);
12077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   span.arrayMask |= SPAN_Z;
12180532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul#endif
122e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   if (ctx->Light.ShadeModel == GL_SMOOTH) {
1238f95d790daee7c012364d689e7d86524340469c1Brian Paul      compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane);
1248f95d790daee7c012364d689e7d86524340469c1Brian Paul      compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane);
1258f95d790daee7c012364d689e7d86524340469c1Brian Paul      compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane);
1268f95d790daee7c012364d689e7d86524340469c1Brian Paul      compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane);
127e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
128e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   else {
12958e991705392a2e17a1c8b034f4083a0adaf1943Keith Whitwell      constant_plane(v2->color[RCOMP], rPlane);
13058e991705392a2e17a1c8b034f4083a0adaf1943Keith Whitwell      constant_plane(v2->color[GCOMP], gPlane);
13158e991705392a2e17a1c8b034f4083a0adaf1943Keith Whitwell      constant_plane(v2->color[BCOMP], bPlane);
13258e991705392a2e17a1c8b034f4083a0adaf1943Keith Whitwell      constant_plane(v2->color[ACOMP], aPlane);
133e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
13477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul   span.arrayMask |= SPAN_RGBA;
135eca456b63d41700617987ba45a09e8f2168b9577Brian#if defined(DO_ATTRIBS)
136e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   {
1379e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat invW0 = v0->attrib[FRAG_ATTRIB_WPOS][3];
1389e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat invW1 = v1->attrib[FRAG_ATTRIB_WPOS][3];
1399e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat invW2 = v2->attrib[FRAG_ATTRIB_WPOS][3];
1409e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      compute_plane(p0, p1, p2, invW0, invW1, invW2, wPlane);
1419e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span.attrStepX[FRAG_ATTRIB_WPOS][3] = plane_dx(wPlane);
1429e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      span.attrStepY[FRAG_ATTRIB_WPOS][3] = plane_dy(wPlane);
1430bdf216dd06d5136b8529297297aa962bab548c2Brian      ATTRIB_LOOP_BEGIN
1449e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         GLuint c;
1459e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         if (swrast->_InterpMode[attr] == GL_FLAT) {
1469e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            for (c = 0; c < 4; c++) {
1479e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian               constant_plane(v2->attrib[attr][c] * invW2, attrPlane[attr][c]);
1489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            }
149e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
1500bdf216dd06d5136b8529297297aa962bab548c2Brian         else {
1519e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            for (c = 0; c < 4; c++) {
1529e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian               const GLfloat a0 = v0->attrib[attr][c] * invW0;
1539e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian               const GLfloat a1 = v1->attrib[attr][c] * invW1;
1549e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian               const GLfloat a2 = v2->attrib[attr][c] * invW2;
1559e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian               compute_plane(p0, p1, p2, a0, a1, a2, attrPlane[attr][c]);
1569e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            }
1579e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         }
1589e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         for (c = 0; c < 4; c++) {
1599e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span.attrStepX[attr][c] = plane_dx(attrPlane[attr][c]);
1609e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            span.attrStepY[attr][c] = plane_dy(attrPlane[attr][c]);
1610bdf216dd06d5136b8529297297aa962bab548c2Brian         }
1620bdf216dd06d5136b8529297297aa962bab548c2Brian      ATTRIB_LOOP_END
163e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
164e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#endif
165e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
16680532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul   /* Begin bottom-to-top scan over the triangle.
16780532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * The long edge will either be on the left or right side of the
16880532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * triangle.  We always scan from the long edge toward the shorter
16980532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * edges, stopping when we find that coverage = 0.  If the long edge
17080532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    * is on the left we scan left-to-right.  Else, we scan right-to-left.
17180532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul    */
1729e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   yMin = vMin->attrib[FRAG_ATTRIB_WPOS][1];
1739e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian   yMax = vMax->attrib[FRAG_ATTRIB_WPOS][1];
174ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   iyMin = (GLint) yMin;
175ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   iyMax = (GLint) yMax + 1;
176ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul
177ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   if (ltor) {
178ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      /* scan left to right */
1799e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMin = vMin->attrib[FRAG_ATTRIB_WPOS];
1809e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMid = vMid->attrib[FRAG_ATTRIB_WPOS];
1819e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMax = vMax->attrib[FRAG_ATTRIB_WPOS];
182ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      const GLfloat dxdy = majDx / majDy;
183ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F;
184470a7b48745d0e467973c9b9d751a8be4abec0e6Brian Paul      GLint iy;
185e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#ifdef _OPENMP
186e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
187e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#endif
188e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger      for (iy = iyMin; iy < iyMax; iy++) {
189e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         GLfloat x = pMin[0] - (yMin - iy) * dxdy;
190ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         GLint ix, startX = (GLint) (x - xAdj);
191f1e236987829393c81dc86ea19cb49eefe190317Brian Paul         GLuint count;
192e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         GLfloat coverage = 0.0F;
19310f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
194e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#ifdef _OPENMP
195e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         /* each thread needs to use a different (global) SpanArrays variable */
196e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
197e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#endif
198ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         /* skip over fragments with zero coverage */
19947d88ef204b42a9220c6be3e98c92df9c9aa0860Brian Paul         while (startX < SWRAST_MAX_WIDTH) {
200ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            coverage = compute_coveragef(pMin, pMid, pMax, startX, iy);
201ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            if (coverage > 0.0F)
202ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul               break;
203ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            startX++;
204f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul         }
205f431a3fb4dc1bf860203d79e54657e3a62bc50dfBrian Paul
206ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         /* enter interior of triangle */
207ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         ix = startX;
2089e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
2099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if defined(DO_ATTRIBS)
2109e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* compute attributes at left-most fragment */
211880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul         span.attrStart[FRAG_ATTRIB_WPOS][3] = solve_plane(ix + 0.5F, iy + 0.5F, wPlane);
2129e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ATTRIB_LOOP_BEGIN
2139e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            GLuint c;
2149e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            for (c = 0; c < 4; c++) {
215880411c72aee7c0ec81366bdf6ab8cf25bebb9d5Brian Paul               span.attrStart[attr][c] = solve_plane(ix + 0.5F, iy + 0.5F, attrPlane[attr][c]);
2169e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            }
2179e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ATTRIB_LOOP_END
2189e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
2199e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
220ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         count = 0;
221ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         while (coverage > 0.0F) {
222ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            /* (cx,cy) = center of fragment */
223ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
224cdb27e8242215271364602995d85607cfc06d441Brian Paul            SWspanarrays *array = span.array;
22577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->coverage[count] = coverage;
226e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#ifdef DO_Z
22714570e6d7ccf43b228d09d6fc01a45b2ba31947bBrian Paul            array->z[count] = (GLuint) solve_plane(cx, cy, zPlane);
22880532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul#endif
22977df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane);
23077df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane);
23177df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane);
23277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane);
233ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            ix++;
234ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            count++;
235ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            coverage = compute_coveragef(pMin, pMid, pMax, ix, iy);
236ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         }
23710f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
238e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         if (ix > startX) {
239e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.x = startX;
240e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.y = iy;
241e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.end = (GLuint) ix - (GLuint) startX;
242e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            _swrast_write_rgba_span(ctx, &span);
243e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         }
244ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      }
245ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   }
246ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul   else {
247ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      /* scan right to left */
2489e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMin = vMin->attrib[FRAG_ATTRIB_WPOS];
2499e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMid = vMid->attrib[FRAG_ATTRIB_WPOS];
2509e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian      const GLfloat *pMax = vMax->attrib[FRAG_ATTRIB_WPOS];
251ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      const GLfloat dxdy = majDx / majDy;
252ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F;
253ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      GLint iy;
254e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#ifdef _OPENMP
255e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#pragma omp parallel for schedule(dynamic) private(iy) firstprivate(span)
256e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#endif
257e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger      for (iy = iyMin; iy < iyMax; iy++) {
258e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         GLfloat x = pMin[0] - (yMin - iy) * dxdy;
259ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         GLint ix, left, startX = (GLint) (x + xAdj);
260ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         GLuint count, n;
261ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         GLfloat coverage = 0.0F;
26210f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
263e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#ifdef _OPENMP
264e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         /* each thread needs to use a different (global) SpanArrays variable */
265e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         span.array = SWRAST_CONTEXT(ctx)->SpanArrays + omp_get_thread_num();
266e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger#endif
267ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         /* make sure we're not past the window edge */
268ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         if (startX >= ctx->DrawBuffer->_Xmax) {
269ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            startX = ctx->DrawBuffer->_Xmax - 1;
270ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         }
271d082417daeb3f8a35a490eb44b6c88463289fa5dBrian Paul
272ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         /* skip fragments with zero coverage */
27322a374fc3fdf97a9cc50e9fdc24049c997e6896eBrian         while (startX > 0) {
274ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            coverage = compute_coveragef(pMin, pMax, pMid, startX, iy);
275ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            if (coverage > 0.0F)
276ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul               break;
277ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            startX--;
278ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         }
27910f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
280ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         /* enter interior of triangle */
281ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         ix = startX;
282ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         count = 0;
283ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul         while (coverage > 0.0F) {
284ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            /* (cx,cy) = center of fragment */
285ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            const GLfloat cx = ix + 0.5F, cy = iy + 0.5F;
286cdb27e8242215271364602995d85607cfc06d441Brian Paul            SWspanarrays *array = span.array;
28722a374fc3fdf97a9cc50e9fdc24049c997e6896eBrian            ASSERT(ix >= 0);
28877df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->coverage[ix] = coverage;
289e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#ifdef DO_Z
29014570e6d7ccf43b228d09d6fc01a45b2ba31947bBrian Paul            array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane);
29180532da3bf2a83448c6f38c34dbaf32898acea2dBrian Paul#endif
29277df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane);
29377df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane);
29477df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane);
29577df88727cb0a423dd5cb41498c2302d9df4fce7Brian Paul            array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane);
296ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            ix--;
297ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            count++;
298ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul            coverage = compute_coveragef(pMin, pMax, pMid, ix, iy);
299e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell         }
30010f30eb43835c57c00783390a02d72daf4f78e26Brian Paul
3019e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#if defined(DO_ATTRIBS)
3029e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         /* compute attributes at left-most fragment */
303b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz         span.attrStart[FRAG_ATTRIB_WPOS][3] = solve_plane(ix + 1.5F, iy + 0.5F, wPlane);
3049e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ATTRIB_LOOP_BEGIN
3059e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            GLuint c;
3069e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            for (c = 0; c < 4; c++) {
307b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz               span.attrStart[attr][c] = solve_plane(ix + 1.5F, iy + 0.5F, attrPlane[attr][c]);
3089e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian            }
3099e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian         ATTRIB_LOOP_END
3109e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian#endif
3119e8a961dd7d7b717a9fb4ecdea1c1b60ea355efeBrian
312e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         if (startX > ix) {
313e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            n = (GLuint) startX - (GLuint) ix;
314ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul
315e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            left = ix + 1;
316f1e236987829393c81dc86ea19cb49eefe190317Brian Paul
317e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            /* shift all values to the left */
318e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            /* XXX this is temporary */
319e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            {
320e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger               SWspanarrays *array = span.array;
321e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger               GLint j;
322e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger               for (j = 0; j < (GLint) n; j++) {
323e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger                  array->coverage[j] = array->coverage[j + left];
324e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger                  COPY_CHAN4(array->rgba[j], array->rgba[j + left]);
325f1e236987829393c81dc86ea19cb49eefe190317Brian Paul#ifdef DO_Z
326e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger                  array->z[j] = array->z[j + left];
327f1e236987829393c81dc86ea19cb49eefe190317Brian Paul#endif
328e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger               }
329f1e236987829393c81dc86ea19cb49eefe190317Brian Paul            }
3302a182a98973edc9ecf2936b1288485bb2b3fa722Brian Paul
331e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.x = left;
332e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.y = iy;
333e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            span.end = n;
334e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger            _swrast_write_rgba_span(ctx, &span);
335e411cd7b0a54d2f9b9f4cda4918aa7742ed5c2a6Andreas Fänger         }
336ee6cf4c6b081dbad7366b80637718d068530d79cBrian Paul      }
337e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell   }
338e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell}
339e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
340e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell
341e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#undef DO_Z
342eca456b63d41700617987ba45a09e8f2168b9577Brian#undef DO_ATTRIBS
343e3a051e0538a605551f4d58294c94f5eb00ed07fKeith Whitwell#undef DO_OCCLUSION_TEST
344