s_linetemp.h revision 7117f1b4
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.3
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_FOG      - if defined, interpolate FOG values
35 *    INTERP_RGBA     - if defined, interpolate RGBA values
36 *    INTERP_SPEC     - if defined, interpolate specular RGB values
37 *    INTERP_INDEX    - if defined, interpolate color index values
38 *    INTERP_ATTRIBS  - if defined, interpolate attribs (texcoords, varying, etc)
39 *
40 * When one can directly address pixels in the color buffer the following
41 * macros can be defined and used to directly compute pixel addresses during
42 * rasterization (see pixelPtr):
43 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
44 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
45 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
46 *                          Y==0 at bottom of screen and increases upward.
47 *
48 * Similarly, for direct depth buffer access, this type is used for depth
49 * buffer addressing:
50 *    DEPTH_TYPE          - either GLushort or GLuint
51 *
52 * Optionally, one may provide one-time setup code
53 *    SETUP_CODE    - code which is to be executed once per line
54 *
55 * To actually "plot" each pixel the PLOT macro must be defined...
56 *    PLOT(X,Y) - code to plot a pixel.  Example:
57 *                if (Z < *zPtr) {
58 *                   *zPtr = Z;
59 *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
60 *                                     FixedToInt(b0) );
61 *                   put_pixel( X, Y, color );
62 *                }
63 *
64 * This code was designed for the origin to be in the lower-left corner.
65 *
66 */
67
68
69static void
70NAME( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
71{
72   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
73   SWspan span;
74   GLuint interpFlags = 0;
75   GLint x0 = (GLint) vert0->win[0];
76   GLint x1 = (GLint) vert1->win[0];
77   GLint y0 = (GLint) vert0->win[1];
78   GLint y1 = (GLint) vert1->win[1];
79   GLint dx, dy;
80   GLint numPixels;
81   GLint xstep, ystep;
82#if defined(DEPTH_TYPE)
83   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
84   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
85   struct gl_renderbuffer *zrb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
86#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
87   GLint zPtrXstep, zPtrYstep;
88   DEPTH_TYPE *zPtr;
89#elif defined(INTERP_Z)
90   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
91/*ctx->Visual.depthBits;*/
92#endif
93#ifdef PIXEL_ADDRESS
94   PIXEL_TYPE *pixelPtr;
95   GLint pixelXstep, pixelYstep;
96#endif
97
98#ifdef SETUP_CODE
99   SETUP_CODE
100#endif
101
102   (void) swrast;
103
104   /* Cull primitives with malformed coordinates.
105    */
106   {
107      GLfloat tmp = vert0->win[0] + vert0->win[1]
108                  + vert1->win[0] + vert1->win[1];
109      if (IS_INF_OR_NAN(tmp))
110	 return;
111   }
112
113   /*
114   printf("%s():\n", __FUNCTION__);
115   printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
116          vert0->win[0], vert0->win[1], vert0->win[2],
117          vert1->win[0], vert1->win[1], vert1->win[2]);
118   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
119          vert0->color[0], vert0->color[1], vert0->color[2],
120          vert1->color[0], vert1->color[1], vert1->color[2]);
121   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
122          vert0->specular[0], vert0->specular[1], vert0->specular[2],
123          vert1->specular[0], vert1->specular[1], vert1->specular[2]);
124   */
125
126/*
127 * Despite being clipped to the view volume, the line's window coordinates
128 * may just lie outside the window bounds.  That is, if the legal window
129 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
130 * This quick and dirty code nudges the endpoints inside the window if
131 * necessary.
132 */
133#ifdef CLIP_HACK
134   {
135      GLint w = ctx->DrawBuffer->Width;
136      GLint h = ctx->DrawBuffer->Height;
137      if ((x0==w) | (x1==w)) {
138         if ((x0==w) & (x1==w))
139           return;
140         x0 -= x0==w;
141         x1 -= x1==w;
142      }
143      if ((y0==h) | (y1==h)) {
144         if ((y0==h) & (y1==h))
145           return;
146         y0 -= y0==h;
147         y1 -= y1==h;
148      }
149   }
150#endif
151
152   dx = x1 - x0;
153   dy = y1 - y0;
154   if (dx == 0 && dy == 0)
155      return;
156
157#ifdef DEPTH_TYPE
158   zPtr = (DEPTH_TYPE *) zrb->GetPointer(ctx, zrb, x0, y0);
159#endif
160#ifdef PIXEL_ADDRESS
161   pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
162#endif
163
164   if (dx<0) {
165      dx = -dx;   /* make positive */
166      xstep = -1;
167#ifdef DEPTH_TYPE
168      zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
169#endif
170#ifdef PIXEL_ADDRESS
171      pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
172#endif
173   }
174   else {
175      xstep = 1;
176#ifdef DEPTH_TYPE
177      zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
178#endif
179#ifdef PIXEL_ADDRESS
180      pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
181#endif
182   }
183
184   if (dy<0) {
185      dy = -dy;   /* make positive */
186      ystep = -1;
187#ifdef DEPTH_TYPE
188      zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
189#endif
190#ifdef PIXEL_ADDRESS
191      pixelYstep = BYTES_PER_ROW;
192#endif
193   }
194   else {
195      ystep = 1;
196#ifdef DEPTH_TYPE
197      zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
198#endif
199#ifdef PIXEL_ADDRESS
200      pixelYstep = -(BYTES_PER_ROW);
201#endif
202   }
203
204   ASSERT(dx >= 0);
205   ASSERT(dy >= 0);
206
207   numPixels = MAX2(dx, dy);
208
209   /*
210    * Span setup: compute start and step values for all interpolated values.
211    */
212#ifdef INTERP_RGBA
213   interpFlags |= SPAN_RGBA;
214   if (ctx->Light.ShadeModel == GL_SMOOTH) {
215      span.red   = ChanToFixed(vert0->color[0]);
216      span.green = ChanToFixed(vert0->color[1]);
217      span.blue  = ChanToFixed(vert0->color[2]);
218      span.alpha = ChanToFixed(vert0->color[3]);
219      span.redStep   = (ChanToFixed(vert1->color[0]) - span.red  ) / numPixels;
220      span.greenStep = (ChanToFixed(vert1->color[1]) - span.green) / numPixels;
221      span.blueStep  = (ChanToFixed(vert1->color[2]) - span.blue ) / numPixels;
222      span.alphaStep = (ChanToFixed(vert1->color[3]) - span.alpha) / numPixels;
223   }
224   else {
225      span.red   = ChanToFixed(vert1->color[0]);
226      span.green = ChanToFixed(vert1->color[1]);
227      span.blue  = ChanToFixed(vert1->color[2]);
228      span.alpha = ChanToFixed(vert1->color[3]);
229      span.redStep   = 0;
230      span.greenStep = 0;
231      span.blueStep  = 0;
232      span.alphaStep = 0;
233   }
234#endif
235#ifdef INTERP_SPEC
236   interpFlags |= SPAN_SPEC;
237   if (ctx->Light.ShadeModel == GL_SMOOTH) {
238      span.specRed       = ChanToFixed(vert0->specular[0]);
239      span.specGreen     = ChanToFixed(vert0->specular[1]);
240      span.specBlue      = ChanToFixed(vert0->specular[2]);
241      span.specRedStep   = (ChanToFixed(vert1->specular[0]) - span.specRed) / numPixels;
242      span.specGreenStep = (ChanToFixed(vert1->specular[1]) - span.specBlue) / numPixels;
243      span.specBlueStep  = (ChanToFixed(vert1->specular[2]) - span.specGreen) / numPixels;
244   }
245   else {
246      span.specRed       = ChanToFixed(vert1->specular[0]);
247      span.specGreen     = ChanToFixed(vert1->specular[1]);
248      span.specBlue      = ChanToFixed(vert1->specular[2]);
249      span.specRedStep   = 0;
250      span.specGreenStep = 0;
251      span.specBlueStep  = 0;
252   }
253#endif
254#ifdef INTERP_INDEX
255   interpFlags |= SPAN_INDEX;
256   if (ctx->Light.ShadeModel == GL_SMOOTH) {
257      span.index = FloatToFixed(vert0->index);
258      span.indexStep = FloatToFixed(vert1->index - vert0->index) / numPixels;
259   }
260   else {
261      span.index = FloatToFixed(vert1->index);
262      span.indexStep = 0;
263   }
264#endif
265#if defined(INTERP_Z) || defined(DEPTH_TYPE)
266   interpFlags |= SPAN_Z;
267   {
268      if (depthBits <= 16) {
269         span.z = FloatToFixed(vert0->win[2]) + FIXED_HALF;
270         span.zStep = FloatToFixed(vert1->win[2] - vert0->win[2]) / numPixels;
271      }
272      else {
273         /* don't use fixed point */
274         span.z = (GLuint) vert0->win[2];
275         span.zStep = (GLint) ((vert1->win[2] - vert0->win[2]) / numPixels);
276      }
277   }
278#endif
279#ifdef INTERP_FOG
280   interpFlags |= SPAN_FOG;
281   span.attrStart[FRAG_ATTRIB_FOGC][0] = vert0->attrib[FRAG_ATTRIB_FOGC][0];
282   span.attrStepX[FRAG_ATTRIB_FOGC][0] = (vert1->attrib[FRAG_ATTRIB_FOGC][0]
283                                          - vert0->attrib[FRAG_ATTRIB_FOGC][0]) / numPixels;
284#endif
285#if defined(INTERP_ATTRIBS)
286   interpFlags |= (SPAN_TEXTURE | SPAN_VARYING);
287   {
288      const GLfloat invLen = 1.0F / numPixels;
289      const GLfloat invw0 = vert0->win[3];
290      const GLfloat invw1 = vert1->win[3];
291      ATTRIB_LOOP_BEGIN
292         GLfloat ds, dt, dr, dq;
293         span.attrStart[attr][0] = invw0 * vert0->attrib[attr][0];
294         span.attrStart[attr][1] = invw0 * vert0->attrib[attr][1];
295         span.attrStart[attr][2] = invw0 * vert0->attrib[attr][2];
296         span.attrStart[attr][3] = invw0 * vert0->attrib[attr][3];
297         ds = (invw1 * vert1->attrib[attr][0]) - span.attrStart[attr][0];
298         dt = (invw1 * vert1->attrib[attr][1]) - span.attrStart[attr][1];
299         dr = (invw1 * vert1->attrib[attr][2]) - span.attrStart[attr][2];
300         dq = (invw1 * vert1->attrib[attr][3]) - span.attrStart[attr][3];
301         span.attrStepX[attr][0] = ds * invLen;
302         span.attrStepX[attr][1] = dt * invLen;
303         span.attrStepX[attr][2] = dr * invLen;
304         span.attrStepX[attr][3] = dq * invLen;
305         span.attrStepY[attr][0] = 0.0F;
306         span.attrStepY[attr][1] = 0.0F;
307         span.attrStepY[attr][2] = 0.0F;
308         span.attrStepY[attr][3] = 0.0F;
309      ATTRIB_LOOP_END
310   }
311#endif
312
313   INIT_SPAN(span, GL_LINE, numPixels, interpFlags, SPAN_XY);
314
315   /* Need these for fragment prog texcoord interpolation */
316   span.attrStart[FRAG_ATTRIB_WPOS][3] = 1.0F;
317   span.attrStepX[FRAG_ATTRIB_WPOS][3] = 0.0F;
318   span.attrStepY[FRAG_ATTRIB_WPOS][3] = 0.0F;
319
320   span.facing = swrast->PointLineFacing;
321
322
323   /*
324    * Draw
325    */
326
327   if (dx > dy) {
328      /*** X-major line ***/
329      GLint i;
330      GLint errorInc = dy+dy;
331      GLint error = errorInc-dx;
332      GLint errorDec = error-dx;
333
334      for (i = 0; i < dx; i++) {
335#ifdef DEPTH_TYPE
336         GLuint Z = FixedToDepth(span.z);
337#endif
338#ifdef PLOT
339         PLOT( x0, y0 );
340#else
341         span.array->x[i] = x0;
342         span.array->y[i] = y0;
343#endif
344         x0 += xstep;
345#ifdef DEPTH_TYPE
346         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
347         span.z += span.zStep;
348#endif
349#ifdef PIXEL_ADDRESS
350         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
351#endif
352         if (error<0) {
353            error += errorInc;
354         }
355         else {
356            error += errorDec;
357            y0 += ystep;
358#ifdef DEPTH_TYPE
359            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
360#endif
361#ifdef PIXEL_ADDRESS
362            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
363#endif
364         }
365      }
366   }
367   else {
368      /*** Y-major line ***/
369      GLint i;
370      GLint errorInc = dx+dx;
371      GLint error = errorInc-dy;
372      GLint errorDec = error-dy;
373
374      for (i=0;i<dy;i++) {
375#ifdef DEPTH_TYPE
376         GLuint Z = FixedToDepth(span.z);
377#endif
378#ifdef PLOT
379         PLOT( x0, y0 );
380#else
381         span.array->x[i] = x0;
382         span.array->y[i] = y0;
383#endif
384         y0 += ystep;
385#ifdef DEPTH_TYPE
386         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
387         span.z += span.zStep;
388#endif
389#ifdef PIXEL_ADDRESS
390         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
391#endif
392         if (error<0) {
393            error += errorInc;
394         }
395         else {
396            error += errorDec;
397            x0 += xstep;
398#ifdef DEPTH_TYPE
399            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
400#endif
401#ifdef PIXEL_ADDRESS
402            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
403#endif
404         }
405      }
406   }
407
408#ifdef RENDER_SPAN
409   RENDER_SPAN( span );
410#endif
411
412   (void)span;
413
414}
415
416
417#undef NAME
418#undef INTERP_Z
419#undef INTERP_FOG
420#undef INTERP_RGBA
421#undef INTERP_SPEC
422#undef INTERP_ATTRIBS
423#undef INTERP_INDEX
424#undef PIXEL_ADDRESS
425#undef PIXEL_TYPE
426#undef DEPTH_TYPE
427#undef BYTES_PER_ROW
428#undef SETUP_CODE
429#undef PLOT
430#undef CLIP_HACK
431#undef FixedToDepth
432#undef RENDER_SPAN
433