1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.0
4  *
5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 
26 /*
27  * Line Rasterizer Template
28  *
29  * This file is #include'd to generate custom line rasterizers.
30  *
31  * The following macros may be defined to indicate what auxillary information
32  * must be interplated along the line:
33  *    INTERP_Z        - if defined, interpolate Z values
34  *    INTERP_ATTRIBS  - if defined, interpolate attribs (texcoords, varying, etc)
35  *
36  * When one can directly address pixels in the color buffer the following
37  * macros can be defined and used to directly compute pixel addresses during
38  * rasterization (see pixelPtr):
39  *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
40  *    BYTES_PER_ROW       - number of bytes per row in the color buffer
41  *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
42  *                          Y==0 at bottom of screen and increases upward.
43  *
44  * Similarly, for direct depth buffer access, this type is used for depth
45  * buffer addressing:
46  *    DEPTH_TYPE          - either GLushort or GLuint
47  *
48  * Optionally, one may provide one-time setup code
49  *    SETUP_CODE    - code which is to be executed once per line
50  *
51  * To actually "plot" each pixel the PLOT macro must be defined...
52  *    PLOT(X,Y) - code to plot a pixel.  Example:
53  *                if (Z < *zPtr) {
54  *                   *zPtr = Z;
55  *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
56  *                                     FixedToInt(b0) );
57  *                   put_pixel( X, Y, color );
58  *                }
59  *
60  * This code was designed for the origin to be in the lower-left corner.
61  *
62  */
63 
64 
65 static void
NAME(struct gl_context * ctx,const SWvertex * vert0,const SWvertex * vert1)66 NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 )
67 {
68    const SWcontext *swrast = SWRAST_CONTEXT(ctx);
69    SWspan span;
70    GLuint interpFlags = 0;
71    GLint x0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][0];
72    GLint x1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
73    GLint y0 = (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1];
74    GLint y1 = (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][1];
75    GLint dx, dy;
76    GLint numPixels;
77    GLint xstep, ystep;
78 #if defined(DEPTH_TYPE)
79    const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
80    const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
81    struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
82 #define FixedToDepth(F)  ((F) >> fixedToDepthShift)
83    GLint zPtrXstep, zPtrYstep;
84    DEPTH_TYPE *zPtr;
85 #elif defined(INTERP_Z)
86    const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
87 #endif
88 #ifdef PIXEL_ADDRESS
89    PIXEL_TYPE *pixelPtr;
90    GLint pixelXstep, pixelYstep;
91 #endif
92 
93 #ifdef SETUP_CODE
94    SETUP_CODE
95 #endif
96 
97    (void) swrast;
98 
99    /* Cull primitives with malformed coordinates.
100     */
101    {
102       GLfloat tmp = vert0->attrib[FRAG_ATTRIB_WPOS][0] + vert0->attrib[FRAG_ATTRIB_WPOS][1]
103                   + vert1->attrib[FRAG_ATTRIB_WPOS][0] + vert1->attrib[FRAG_ATTRIB_WPOS][1];
104       if (IS_INF_OR_NAN(tmp))
105 	 return;
106    }
107 
108    /*
109    printf("%s():\n", __FUNCTION__);
110    printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
111           vert0->attrib[FRAG_ATTRIB_WPOS][0],
112           vert0->attrib[FRAG_ATTRIB_WPOS][1],
113           vert0->attrib[FRAG_ATTRIB_WPOS][2],
114           vert1->attrib[FRAG_ATTRIB_WPOS][0],
115           vert1->attrib[FRAG_ATTRIB_WPOS][1],
116           vert1->attrib[FRAG_ATTRIB_WPOS][2]);
117    printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
118           vert0->color[0], vert0->color[1], vert0->color[2],
119           vert1->color[0], vert1->color[1], vert1->color[2]);
120    printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
121           vert0->specular[0], vert0->specular[1], vert0->specular[2],
122           vert1->specular[0], vert1->specular[1], vert1->specular[2]);
123    */
124 
125 /*
126  * Despite being clipped to the view volume, the line's window coordinates
127  * may just lie outside the window bounds.  That is, if the legal window
128  * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
129  * This quick and dirty code nudges the endpoints inside the window if
130  * necessary.
131  */
132 #ifdef CLIP_HACK
133    {
134       GLint w = ctx->DrawBuffer->Width;
135       GLint h = ctx->DrawBuffer->Height;
136       if ((x0==w) | (x1==w)) {
137          if ((x0==w) & (x1==w))
138            return;
139          x0 -= x0==w;
140          x1 -= x1==w;
141       }
142       if ((y0==h) | (y1==h)) {
143          if ((y0==h) & (y1==h))
144            return;
145          y0 -= y0==h;
146          y1 -= y1==h;
147       }
148    }
149 #endif
150 
151    dx = x1 - x0;
152    dy = y1 - y0;
153    if (dx == 0 && dy == 0)
154       return;
155 
156    /*
157    printf("%s %d,%d  %g %g %g %g  %g %g %g %g\n", __FUNCTION__, dx, dy,
158           vert0->attrib[FRAG_ATTRIB_COL1][0],
159           vert0->attrib[FRAG_ATTRIB_COL1][1],
160           vert0->attrib[FRAG_ATTRIB_COL1][2],
161           vert0->attrib[FRAG_ATTRIB_COL1][3],
162           vert1->attrib[FRAG_ATTRIB_COL1][0],
163           vert1->attrib[FRAG_ATTRIB_COL1][1],
164           vert1->attrib[FRAG_ATTRIB_COL1][2],
165           vert1->attrib[FRAG_ATTRIB_COL1][3]);
166    */
167 
168 #ifdef DEPTH_TYPE
169    zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0);
170 #endif
171 #ifdef PIXEL_ADDRESS
172    pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
173 #endif
174 
175    if (dx<0) {
176       dx = -dx;   /* make positive */
177       xstep = -1;
178 #ifdef DEPTH_TYPE
179       zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
180 #endif
181 #ifdef PIXEL_ADDRESS
182       pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
183 #endif
184    }
185    else {
186       xstep = 1;
187 #ifdef DEPTH_TYPE
188       zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
189 #endif
190 #ifdef PIXEL_ADDRESS
191       pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
192 #endif
193    }
194 
195    if (dy<0) {
196       dy = -dy;   /* make positive */
197       ystep = -1;
198 #ifdef DEPTH_TYPE
199       zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
200 #endif
201 #ifdef PIXEL_ADDRESS
202       pixelYstep = BYTES_PER_ROW;
203 #endif
204    }
205    else {
206       ystep = 1;
207 #ifdef DEPTH_TYPE
208       zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
209 #endif
210 #ifdef PIXEL_ADDRESS
211       pixelYstep = -(BYTES_PER_ROW);
212 #endif
213    }
214 
215    ASSERT(dx >= 0);
216    ASSERT(dy >= 0);
217 
218    numPixels = MAX2(dx, dy);
219 
220    /*
221     * Span setup: compute start and step values for all interpolated values.
222     */
223    interpFlags |= SPAN_RGBA;
224    if (ctx->Light.ShadeModel == GL_SMOOTH) {
225       span.red   = ChanToFixed(vert0->color[0]);
226       span.green = ChanToFixed(vert0->color[1]);
227       span.blue  = ChanToFixed(vert0->color[2]);
228       span.alpha = ChanToFixed(vert0->color[3]);
229       span.redStep   = (ChanToFixed(vert1->color[0]) - span.red  ) / numPixels;
230       span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
231       span.blueStep  = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
232       span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
233    }
234    else {
235       span.red   = ChanToFixed(vert1->color[0]);
236       span.green = ChanToFixed(vert1->color[1]);
237       span.blue  = ChanToFixed(vert1->color[2]);
238       span.alpha = ChanToFixed(vert1->color[3]);
239       span.redStep   = 0;
240       span.greenStep = 0;
241       span.blueStep  = 0;
242       span.alphaStep = 0;
243    }
244 #if defined(INTERP_Z) || defined(DEPTH_TYPE)
245    interpFlags |= SPAN_Z;
246    {
247       if (depthBits <= 16) {
248          span.z = FloatToFixed(vert0->attrib[FRAG_ATTRIB_WPOS][2]) + FIXED_HALF;
249          span.zStep = FloatToFixed(  vert1->attrib[FRAG_ATTRIB_WPOS][2]
250                                    - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels;
251       }
252       else {
253          /* don't use fixed point */
254          span.z = (GLuint) vert0->attrib[FRAG_ATTRIB_WPOS][2];
255          span.zStep = (GLint) ((  vert1->attrib[FRAG_ATTRIB_WPOS][2]
256                                 - vert0->attrib[FRAG_ATTRIB_WPOS][2]) / numPixels);
257       }
258    }
259 #endif
260 #if defined(INTERP_ATTRIBS)
261    {
262       const GLfloat invLen = 1.0F / numPixels;
263       const GLfloat invw0 = vert0->attrib[FRAG_ATTRIB_WPOS][3];
264       const GLfloat invw1 = vert1->attrib[FRAG_ATTRIB_WPOS][3];
265 
266       span.attrStart[FRAG_ATTRIB_WPOS][3] = invw0;
267       span.attrStepX[FRAG_ATTRIB_WPOS][3] = (invw1 - invw0) * invLen;
268       span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0;
269 
270       ATTRIB_LOOP_BEGIN
271          if (swrast->_InterpMode[attr] == GL_FLAT) {
272             COPY_4V(span.attrStart[attr], vert1->attrib[attr]);
273             ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
274          }
275          else {
276             GLuint c;
277             for (c = 0; c < 4; c++) {
278                float da;
279                span.attrStart[attr][c] = invw0 * vert0->attrib[attr][c];
280                da = (invw1 * vert1->attrib[attr][c]) - span.attrStart[attr][c];
281                span.attrStepX[attr][c] = da * invLen;
282             }
283          }
284          ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
285       ATTRIB_LOOP_END
286    }
287 #endif
288 
289    INIT_SPAN(span, GL_LINE);
290    span.end = numPixels;
291    span.interpMask = interpFlags;
292    span.arrayMask = SPAN_XY;
293 
294    span.facing = swrast->PointLineFacing;
295 
296 
297    /*
298     * Draw
299     */
300 
301    if (dx > dy) {
302       /*** X-major line ***/
303       GLint i;
304       GLint errorInc = dy+dy;
305       GLint error = errorInc-dx;
306       GLint errorDec = error-dx;
307 
308       for (i = 0; i < dx; i++) {
309 #ifdef DEPTH_TYPE
310          GLuint Z = FixedToDepth(span.z);
311 #endif
312 #ifdef PLOT
313          PLOT( x0, y0 );
314 #else
315          span.array->x[i] = x0;
316          span.array->y[i] = y0;
317 #endif
318          x0 += xstep;
319 #ifdef DEPTH_TYPE
320          zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
321          span.z += span.zStep;
322 #endif
323 #ifdef PIXEL_ADDRESS
324          pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
325 #endif
326          if (error < 0) {
327             error += errorInc;
328          }
329          else {
330             error += errorDec;
331             y0 += ystep;
332 #ifdef DEPTH_TYPE
333             zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
334 #endif
335 #ifdef PIXEL_ADDRESS
336             pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
337 #endif
338          }
339       }
340    }
341    else {
342       /*** Y-major line ***/
343       GLint i;
344       GLint errorInc = dx+dx;
345       GLint error = errorInc-dy;
346       GLint errorDec = error-dy;
347 
348       for (i=0;i<dy;i++) {
349 #ifdef DEPTH_TYPE
350          GLuint Z = FixedToDepth(span.z);
351 #endif
352 #ifdef PLOT
353          PLOT( x0, y0 );
354 #else
355          span.array->x[i] = x0;
356          span.array->y[i] = y0;
357 #endif
358          y0 += ystep;
359 #ifdef DEPTH_TYPE
360          zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
361          span.z += span.zStep;
362 #endif
363 #ifdef PIXEL_ADDRESS
364          pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
365 #endif
366          if (error<0) {
367             error += errorInc;
368          }
369          else {
370             error += errorDec;
371             x0 += xstep;
372 #ifdef DEPTH_TYPE
373             zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
374 #endif
375 #ifdef PIXEL_ADDRESS
376             pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
377 #endif
378          }
379       }
380    }
381 
382 #ifdef RENDER_SPAN
383    RENDER_SPAN( span );
384 #endif
385 
386    (void)span;
387 
388 }
389 
390 
391 #undef NAME
392 #undef INTERP_Z
393 #undef INTERP_ATTRIBS
394 #undef PIXEL_ADDRESS
395 #undef PIXEL_TYPE
396 #undef DEPTH_TYPE
397 #undef BYTES_PER_ROW
398 #undef SETUP_CODE
399 #undef PLOT
400 #undef CLIP_HACK
401 #undef FixedToDepth
402 #undef RENDER_SPAN
403