1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg
26848b8605Smrg/*
27848b8605Smrg * Line Rasterizer Template
28848b8605Smrg *
29848b8605Smrg * This file is #include'd to generate custom line rasterizers.
30848b8605Smrg *
31848b8605Smrg * The following macros may be defined to indicate what auxillary information
32848b8605Smrg * must be interplated along the line:
33848b8605Smrg *    INTERP_Z        - if defined, interpolate Z values
34848b8605Smrg *    INTERP_ATTRIBS  - if defined, interpolate attribs (texcoords, varying, etc)
35848b8605Smrg *
36848b8605Smrg * When one can directly address pixels in the color buffer the following
37848b8605Smrg * macros can be defined and used to directly compute pixel addresses during
38848b8605Smrg * rasterization (see pixelPtr):
39848b8605Smrg *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
40848b8605Smrg *    BYTES_PER_ROW       - number of bytes per row in the color buffer
41848b8605Smrg *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
42848b8605Smrg *                          Y==0 at bottom of screen and increases upward.
43848b8605Smrg *
44848b8605Smrg * Similarly, for direct depth buffer access, this type is used for depth
45848b8605Smrg * buffer addressing:
46848b8605Smrg *    DEPTH_TYPE          - either GLushort or GLuint
47848b8605Smrg *
48848b8605Smrg * Optionally, one may provide one-time setup code
49848b8605Smrg *    SETUP_CODE    - code which is to be executed once per line
50848b8605Smrg *
51848b8605Smrg * To actually "plot" each pixel the PLOT macro must be defined...
52848b8605Smrg *    PLOT(X,Y) - code to plot a pixel.  Example:
53848b8605Smrg *                if (Z < *zPtr) {
54848b8605Smrg *                   *zPtr = Z;
55848b8605Smrg *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
56848b8605Smrg *                                     FixedToInt(b0) );
57848b8605Smrg *                   put_pixel( X, Y, color );
58848b8605Smrg *                }
59848b8605Smrg *
60848b8605Smrg * This code was designed for the origin to be in the lower-left corner.
61848b8605Smrg *
62848b8605Smrg */
63848b8605Smrg
64848b8605Smrg
65848b8605Smrgstatic void
66848b8605SmrgNAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
67848b8605Smrg{
68848b8605Smrg   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
69848b8605Smrg   SWspan span;
70848b8605Smrg   GLuint interpFlags = 0;
71848b8605Smrg   GLint x0 = (GLint) vert0->attrib[VARYING_SLOT_POS][0];
72848b8605Smrg   GLint x1 = (GLint) vert1->attrib[VARYING_SLOT_POS][0];
73848b8605Smrg   GLint y0 = (GLint) vert0->attrib[VARYING_SLOT_POS][1];
74848b8605Smrg   GLint y1 = (GLint) vert1->attrib[VARYING_SLOT_POS][1];
75848b8605Smrg   GLint dx, dy;
76848b8605Smrg   GLint numPixels;
77848b8605Smrg   GLint xstep, ystep;
78848b8605Smrg#if defined(DEPTH_TYPE)
79848b8605Smrg   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
80848b8605Smrg   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
81848b8605Smrg   struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
82848b8605Smrg#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
83848b8605Smrg   GLint zPtrXstep, zPtrYstep;
84848b8605Smrg   DEPTH_TYPE *zPtr;
85848b8605Smrg#elif defined(INTERP_Z)
86848b8605Smrg   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
87848b8605Smrg#endif
88848b8605Smrg#ifdef PIXEL_ADDRESS
89848b8605Smrg   PIXEL_TYPE *pixelPtr;
90848b8605Smrg   GLint pixelXstep, pixelYstep;
91848b8605Smrg#endif
92848b8605Smrg
93848b8605Smrg#ifdef SETUP_CODE
94848b8605Smrg   SETUP_CODE
95848b8605Smrg#endif
96848b8605Smrg
97848b8605Smrg   (void) swrast;
98848b8605Smrg
99848b8605Smrg   /* Cull primitives with malformed coordinates.
100848b8605Smrg    */
101848b8605Smrg   {
102848b8605Smrg      GLfloat tmp = vert0->attrib[VARYING_SLOT_POS][0] + vert0->attrib[VARYING_SLOT_POS][1]
103848b8605Smrg                  + vert1->attrib[VARYING_SLOT_POS][0] + vert1->attrib[VARYING_SLOT_POS][1];
104848b8605Smrg      if (IS_INF_OR_NAN(tmp))
105848b8605Smrg	 return;
106848b8605Smrg   }
107848b8605Smrg
108848b8605Smrg   /*
109b8e80941Smrg   printf("%s():\n", __func__);
110848b8605Smrg   printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
111848b8605Smrg          vert0->attrib[VARYING_SLOT_POS][0],
112848b8605Smrg          vert0->attrib[VARYING_SLOT_POS][1],
113848b8605Smrg          vert0->attrib[VARYING_SLOT_POS][2],
114848b8605Smrg          vert1->attrib[VARYING_SLOT_POS][0],
115848b8605Smrg          vert1->attrib[VARYING_SLOT_POS][1],
116848b8605Smrg          vert1->attrib[VARYING_SLOT_POS][2]);
117848b8605Smrg   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
118848b8605Smrg          vert0->color[0], vert0->color[1], vert0->color[2],
119848b8605Smrg          vert1->color[0], vert1->color[1], vert1->color[2]);
120848b8605Smrg   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
121848b8605Smrg          vert0->specular[0], vert0->specular[1], vert0->specular[2],
122848b8605Smrg          vert1->specular[0], vert1->specular[1], vert1->specular[2]);
123848b8605Smrg   */
124848b8605Smrg
125848b8605Smrg/*
126848b8605Smrg * Despite being clipped to the view volume, the line's window coordinates
127848b8605Smrg * may just lie outside the window bounds.  That is, if the legal window
128848b8605Smrg * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
129848b8605Smrg * This quick and dirty code nudges the endpoints inside the window if
130848b8605Smrg * necessary.
131848b8605Smrg */
132848b8605Smrg#ifdef CLIP_HACK
133848b8605Smrg   {
134848b8605Smrg      GLint w = ctx->DrawBuffer->Width;
135848b8605Smrg      GLint h = ctx->DrawBuffer->Height;
136848b8605Smrg      if ((x0==w) | (x1==w)) {
137848b8605Smrg         if ((x0==w) & (x1==w))
138848b8605Smrg           return;
139848b8605Smrg         x0 -= x0==w;
140848b8605Smrg         x1 -= x1==w;
141848b8605Smrg      }
142848b8605Smrg      if ((y0==h) | (y1==h)) {
143848b8605Smrg         if ((y0==h) & (y1==h))
144848b8605Smrg           return;
145848b8605Smrg         y0 -= y0==h;
146848b8605Smrg         y1 -= y1==h;
147848b8605Smrg      }
148848b8605Smrg   }
149848b8605Smrg#endif
150848b8605Smrg
151848b8605Smrg   dx = x1 - x0;
152848b8605Smrg   dy = y1 - y0;
153848b8605Smrg   if (dx == 0 && dy == 0)
154848b8605Smrg      return;
155848b8605Smrg
156848b8605Smrg   /*
157b8e80941Smrg   printf("%s %d,%d  %g %g %g %g  %g %g %g %g\n", __func__, dx, dy,
158848b8605Smrg          vert0->attrib[VARYING_SLOT_COL1][0],
159848b8605Smrg          vert0->attrib[VARYING_SLOT_COL1][1],
160848b8605Smrg          vert0->attrib[VARYING_SLOT_COL1][2],
161848b8605Smrg          vert0->attrib[VARYING_SLOT_COL1][3],
162848b8605Smrg          vert1->attrib[VARYING_SLOT_COL1][0],
163848b8605Smrg          vert1->attrib[VARYING_SLOT_COL1][1],
164848b8605Smrg          vert1->attrib[VARYING_SLOT_COL1][2],
165848b8605Smrg          vert1->attrib[VARYING_SLOT_COL1][3]);
166848b8605Smrg   */
167848b8605Smrg
168848b8605Smrg#ifdef DEPTH_TYPE
169848b8605Smrg   zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0);
170848b8605Smrg#endif
171848b8605Smrg#ifdef PIXEL_ADDRESS
172848b8605Smrg   pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
173848b8605Smrg#endif
174848b8605Smrg
175848b8605Smrg   if (dx<0) {
176848b8605Smrg      dx = -dx;   /* make positive */
177848b8605Smrg      xstep = -1;
178848b8605Smrg#ifdef DEPTH_TYPE
179848b8605Smrg      zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
180848b8605Smrg#endif
181848b8605Smrg#ifdef PIXEL_ADDRESS
182848b8605Smrg      pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
183848b8605Smrg#endif
184848b8605Smrg   }
185848b8605Smrg   else {
186848b8605Smrg      xstep = 1;
187848b8605Smrg#ifdef DEPTH_TYPE
188848b8605Smrg      zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
189848b8605Smrg#endif
190848b8605Smrg#ifdef PIXEL_ADDRESS
191848b8605Smrg      pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
192848b8605Smrg#endif
193848b8605Smrg   }
194848b8605Smrg
195848b8605Smrg   if (dy<0) {
196848b8605Smrg      dy = -dy;   /* make positive */
197848b8605Smrg      ystep = -1;
198848b8605Smrg#ifdef DEPTH_TYPE
199848b8605Smrg      zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
200848b8605Smrg#endif
201848b8605Smrg#ifdef PIXEL_ADDRESS
202848b8605Smrg      pixelYstep = BYTES_PER_ROW;
203848b8605Smrg#endif
204848b8605Smrg   }
205848b8605Smrg   else {
206848b8605Smrg      ystep = 1;
207848b8605Smrg#ifdef DEPTH_TYPE
208848b8605Smrg      zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
209848b8605Smrg#endif
210848b8605Smrg#ifdef PIXEL_ADDRESS
211848b8605Smrg      pixelYstep = -(BYTES_PER_ROW);
212848b8605Smrg#endif
213848b8605Smrg   }
214848b8605Smrg
215b8e80941Smrg   assert(dx >= 0);
216b8e80941Smrg   assert(dy >= 0);
217848b8605Smrg
218848b8605Smrg   numPixels = MAX2(dx, dy);
219848b8605Smrg
220848b8605Smrg   /*
221848b8605Smrg    * Span setup: compute start and step values for all interpolated values.
222848b8605Smrg    */
223848b8605Smrg   interpFlags |= SPAN_RGBA;
224848b8605Smrg   if (ctx->Light.ShadeModel == GL_SMOOTH) {
225848b8605Smrg      span.red   = ChanToFixed(vert0->color[0]);
226848b8605Smrg      span.green = ChanToFixed(vert0->color[1]);
227848b8605Smrg      span.blue  = ChanToFixed(vert0->color[2]);
228848b8605Smrg      span.alpha = ChanToFixed(vert0->color[3]);
229848b8605Smrg      span.redStep   = (ChanToFixed(vert1->color[0]) - span.red  ) / numPixels;
230848b8605Smrg      span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
231848b8605Smrg      span.blueStep  = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
232848b8605Smrg      span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
233848b8605Smrg   }
234848b8605Smrg   else {
235848b8605Smrg      span.red   = ChanToFixed(vert1->color[0]);
236848b8605Smrg      span.green = ChanToFixed(vert1->color[1]);
237848b8605Smrg      span.blue  = ChanToFixed(vert1->color[2]);
238848b8605Smrg      span.alpha = ChanToFixed(vert1->color[3]);
239848b8605Smrg      span.redStep   = 0;
240848b8605Smrg      span.greenStep = 0;
241848b8605Smrg      span.blueStep  = 0;
242848b8605Smrg      span.alphaStep = 0;
243848b8605Smrg   }
244848b8605Smrg#if defined(INTERP_Z) || defined(DEPTH_TYPE)
245848b8605Smrg   interpFlags |= SPAN_Z;
246848b8605Smrg   {
247848b8605Smrg      if (depthBits <= 16) {
248848b8605Smrg         span.z = FloatToFixed(vert0->attrib[VARYING_SLOT_POS][2]) + FIXED_HALF;
249848b8605Smrg         span.zStep = FloatToFixed(  vert1->attrib[VARYING_SLOT_POS][2]
250848b8605Smrg                                   - vert0->attrib[VARYING_SLOT_POS][2]) / numPixels;
251848b8605Smrg      }
252848b8605Smrg      else {
253848b8605Smrg         /* don't use fixed point */
254848b8605Smrg         span.z = (GLuint) vert0->attrib[VARYING_SLOT_POS][2];
255848b8605Smrg         span.zStep = (GLint) ((  vert1->attrib[VARYING_SLOT_POS][2]
256848b8605Smrg                                - vert0->attrib[VARYING_SLOT_POS][2]) / numPixels);
257848b8605Smrg      }
258848b8605Smrg   }
259848b8605Smrg#endif
260848b8605Smrg#if defined(INTERP_ATTRIBS)
261848b8605Smrg   {
262848b8605Smrg      const GLfloat invLen = 1.0F / numPixels;
263848b8605Smrg      const GLfloat invw0 = vert0->attrib[VARYING_SLOT_POS][3];
264848b8605Smrg      const GLfloat invw1 = vert1->attrib[VARYING_SLOT_POS][3];
265848b8605Smrg
266848b8605Smrg      span.attrStart[VARYING_SLOT_POS][3] = invw0;
267848b8605Smrg      span.attrStepX[VARYING_SLOT_POS][3] = (invw1 - invw0) * invLen;
268848b8605Smrg      span.attrStepY[VARYING_SLOT_POS][3] = 0.0;
269848b8605Smrg
270848b8605Smrg      ATTRIB_LOOP_BEGIN
271848b8605Smrg         if (swrast->_InterpMode[attr] == GL_FLAT) {
272848b8605Smrg            COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
273848b8605Smrg            ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
274848b8605Smrg         }
275848b8605Smrg         else {
276848b8605Smrg            GLuint c;
277848b8605Smrg            for (c = 0; c < 4; c++) {
278848b8605Smrg               float da;
279848b8605Smrg               span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
280848b8605Smrg               da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
281848b8605Smrg               span.attrStepX[attr][c] = da * invLen;
282848b8605Smrg            }
283848b8605Smrg         }
284848b8605Smrg         ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
285848b8605Smrg      ATTRIB_LOOP_END
286848b8605Smrg   }
287848b8605Smrg#endif
288848b8605Smrg
289848b8605Smrg   INIT_SPAN(span, GL_LINE);
290848b8605Smrg   span.end = numPixels;
291848b8605Smrg   span.interpMask = interpFlags;
292848b8605Smrg   span.arrayMask = SPAN_XY;
293848b8605Smrg
294848b8605Smrg   span.facing = swrast->PointLineFacing;
295848b8605Smrg
296848b8605Smrg
297848b8605Smrg   /*
298848b8605Smrg    * Draw
299848b8605Smrg    */
300848b8605Smrg
301848b8605Smrg   if (dx > dy) {
302848b8605Smrg      /*** X-major line ***/
303848b8605Smrg      GLint i;
304848b8605Smrg      GLint errorInc = dy+dy;
305848b8605Smrg      GLint error = errorInc-dx;
306848b8605Smrg      GLint errorDec = error-dx;
307848b8605Smrg
308848b8605Smrg      for (i = 0; i < dx; i++) {
309848b8605Smrg#ifdef DEPTH_TYPE
310848b8605Smrg         GLuint Z = FixedToDepth(span.z);
311848b8605Smrg#endif
312848b8605Smrg#ifdef PLOT
313848b8605Smrg         PLOT( x0, y0 );
314848b8605Smrg#else
315848b8605Smrg         span.array->x[i] = x0;
316848b8605Smrg         span.array->y[i] = y0;
317848b8605Smrg#endif
318848b8605Smrg         x0 += xstep;
319848b8605Smrg#ifdef DEPTH_TYPE
320848b8605Smrg         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
321848b8605Smrg         span.z += span.zStep;
322848b8605Smrg#endif
323848b8605Smrg#ifdef PIXEL_ADDRESS
324848b8605Smrg         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
325848b8605Smrg#endif
326848b8605Smrg         if (error < 0) {
327848b8605Smrg            error += errorInc;
328848b8605Smrg         }
329848b8605Smrg         else {
330848b8605Smrg            error += errorDec;
331848b8605Smrg            y0 += ystep;
332848b8605Smrg#ifdef DEPTH_TYPE
333848b8605Smrg            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
334848b8605Smrg#endif
335848b8605Smrg#ifdef PIXEL_ADDRESS
336848b8605Smrg            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
337848b8605Smrg#endif
338848b8605Smrg         }
339848b8605Smrg      }
340848b8605Smrg   }
341848b8605Smrg   else {
342848b8605Smrg      /*** Y-major line ***/
343848b8605Smrg      GLint i;
344848b8605Smrg      GLint errorInc = dx+dx;
345848b8605Smrg      GLint error = errorInc-dy;
346848b8605Smrg      GLint errorDec = error-dy;
347848b8605Smrg
348848b8605Smrg      for (i=0;i<dy;i++) {
349848b8605Smrg#ifdef DEPTH_TYPE
350848b8605Smrg         GLuint Z = FixedToDepth(span.z);
351848b8605Smrg#endif
352848b8605Smrg#ifdef PLOT
353848b8605Smrg         PLOT( x0, y0 );
354848b8605Smrg#else
355848b8605Smrg         span.array->x[i] = x0;
356848b8605Smrg         span.array->y[i] = y0;
357848b8605Smrg#endif
358848b8605Smrg         y0 += ystep;
359848b8605Smrg#ifdef DEPTH_TYPE
360848b8605Smrg         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
361848b8605Smrg         span.z += span.zStep;
362848b8605Smrg#endif
363848b8605Smrg#ifdef PIXEL_ADDRESS
364848b8605Smrg         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
365848b8605Smrg#endif
366848b8605Smrg         if (error<0) {
367848b8605Smrg            error += errorInc;
368848b8605Smrg         }
369848b8605Smrg         else {
370848b8605Smrg            error += errorDec;
371848b8605Smrg            x0 += xstep;
372848b8605Smrg#ifdef DEPTH_TYPE
373848b8605Smrg            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
374848b8605Smrg#endif
375848b8605Smrg#ifdef PIXEL_ADDRESS
376848b8605Smrg            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
377848b8605Smrg#endif
378848b8605Smrg         }
379848b8605Smrg      }
380848b8605Smrg   }
381848b8605Smrg
382848b8605Smrg#ifdef RENDER_SPAN
383848b8605Smrg   RENDER_SPAN( span );
384848b8605Smrg#endif
385848b8605Smrg
386848b8605Smrg   (void)span;
387848b8605Smrg
388848b8605Smrg}
389848b8605Smrg
390848b8605Smrg
391848b8605Smrg#undef NAME
392848b8605Smrg#undef INTERP_Z
393848b8605Smrg#undef INTERP_ATTRIBS
394848b8605Smrg#undef PIXEL_ADDRESS
395848b8605Smrg#undef PIXEL_TYPE
396848b8605Smrg#undef DEPTH_TYPE
397848b8605Smrg#undef BYTES_PER_ROW
398848b8605Smrg#undef SETUP_CODE
399848b8605Smrg#undef PLOT
400848b8605Smrg#undef CLIP_HACK
401848b8605Smrg#undef FixedToDepth
402848b8605Smrg#undef RENDER_SPAN
403