s_linetemp.h revision e307931314f1145305ac2946f13f5e2f020313ec
1/* $Id: s_linetemp.h,v 1.14 2002/11/09 21:26:41 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  5.0
6 *
7 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * Line Rasterizer Template
30 *
31 * This file is #include'd to generate custom line rasterizers.
32 *
33 * The following macros may be defined to indicate what auxillary information
34 * must be interplated along the line:
35 *    INTERP_Z        - if defined, interpolate Z values
36 *    INTERP_FOG      - if defined, interpolate FOG values
37 *    INTERP_RGB      - if defined, interpolate RGB values
38 *    INTERP_SPEC     - if defined, interpolate specular RGB values
39 *    INTERP_ALPHA    - if defined, interpolate Alpha values
40 *    INTERP_INDEX    - if defined, interpolate color index values
41 *    INTERP_TEX      - if defined, interpolate unit 0 texcoords
42 *    INTERP_MULTITEX - if defined, interpolate multi-texcoords
43 *
44 * When one can directly address pixels in the color buffer the following
45 * macros can be defined and used to directly compute pixel addresses during
46 * rasterization (see pixelPtr):
47 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
48 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
49 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
50 *                          Y==0 at bottom of screen and increases upward.
51 *
52 * Similarly, for direct depth buffer access, this type is used for depth
53 * buffer addressing:
54 *    DEPTH_TYPE          - either GLushort or GLuint
55 *
56 * Optionally, one may provide one-time setup code
57 *    SETUP_CODE    - code which is to be executed once per line
58 *
59 * To actually "plot" each pixel the PLOT macro must be defined...
60 *    PLOT(X,Y) - code to plot a pixel.  Example:
61 *                if (Z < *zPtr) {
62 *                   *zPtr = Z;
63 *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
64 *                                     FixedToInt(b0) );
65 *                   put_pixel( X, Y, color );
66 *                }
67 *
68 * This code was designed for the origin to be in the lower-left corner.
69 *
70 */
71
72
73/*void line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )*/
74{
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#ifdef INTERP_XY
81   GLint xstep, ystep;
82#endif
83#ifdef INTERP_Z
84   GLint z0, z1, dz;
85   const GLint depthBits = ctx->Visual.depthBits;
86   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
87#  define FixedToDepth(F)  ((F) >> fixedToDepthShift)
88#  ifdef DEPTH_TYPE
89   GLint zPtrXstep, zPtrYstep;
90   DEPTH_TYPE *zPtr;
91#  endif
92#endif
93#ifdef INTERP_FOG
94   GLfloat fog0 = vert0->fog;
95   GLfloat dfog = vert1->fog - fog0;
96#endif
97#ifdef INTERP_RGB
98   GLfixed r0 = ChanToFixed(vert0->color[0]);
99   GLfixed dr = ChanToFixed(vert1->color[0]) - r0;
100   GLfixed g0 = ChanToFixed(vert0->color[1]);
101   GLfixed dg = ChanToFixed(vert1->color[1]) - g0;
102   GLfixed b0 = ChanToFixed(vert0->color[2]);
103   GLfixed db = ChanToFixed(vert1->color[2]) - b0;
104#endif
105#ifdef INTERP_SPEC
106   GLfixed sr0 = ChanToFixed(vert0->specular[0]);
107   GLfixed dsr = ChanToFixed(vert1->specular[0]) - sr0;
108   GLfixed sg0 = ChanToFixed(vert0->specular[1]);
109   GLfixed dsg = ChanToFixed(vert1->specular[1]) - sg0;
110   GLfixed sb0 = ChanToFixed(vert0->specular[2]);
111   GLfixed dsb = ChanToFixed(vert1->specular[2]) - sb0;
112#endif
113#ifdef INTERP_ALPHA
114   GLfixed a0 = ChanToFixed(vert0->color[3]);
115   GLfixed da = ChanToFixed(vert1->color[3]) - a0;
116#endif
117#ifdef INTERP_INDEX
118   GLint i0 = vert0->index << 8;
119   GLint di = (GLint) (vert1->index << 8) - i0;
120#endif
121#ifdef INTERP_TEX
122   const GLfloat invw0 = vert0->win[3];
123   const GLfloat invw1 = vert1->win[3];
124   GLfloat tex[4];
125   GLfloat dtex[4];
126   GLfloat fragTexcoord[4];
127#endif
128#ifdef INTERP_MULTITEX
129   const GLfloat invw0 = vert0->win[3];
130   const GLfloat invw1 = vert1->win[3];
131   GLfloat tex[MAX_TEXTURE_UNITS][4];
132   GLfloat dtex[MAX_TEXTURE_UNITS][4];
133   GLfloat fragTexcoord[MAX_TEXTURE_UNITS][4];
134#endif
135#ifdef PIXEL_ADDRESS
136   PIXEL_TYPE *pixelPtr;
137   GLint pixelXstep, pixelYstep;
138#endif
139#ifdef INTERP_TEX
140   {
141      tex[0]  = invw0 * vert0->texcoord[0][0];
142      dtex[0] = invw1 * vert1->texcoord[0][0] - tex[0];
143      tex[1]  = invw0 * vert0->texcoord[0][1];
144      dtex[1] = invw1 * vert1->texcoord[0][1] - tex[1];
145      tex[2]  = invw0 * vert0->texcoord[0][2];
146      dtex[2] = invw1 * vert1->texcoord[0][2] - tex[2];
147      tex[3]  = invw0 * vert0->texcoord[0][3];
148      dtex[3] = invw1 * vert1->texcoord[0][3] - tex[3];
149   }
150#endif
151#ifdef INTERP_MULTITEX
152   {
153      GLuint u;
154      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
155         if (ctx->Texture.Unit[u]._ReallyEnabled) {
156            tex[u][0]  = invw0 * vert0->texcoord[u][0];
157            dtex[u][0] = invw1 * vert1->texcoord[u][0] - tex[u][0];
158	    tex[u][1]  = invw0 * vert0->texcoord[u][1];
159	    dtex[u][1] = invw1 * vert1->texcoord[u][1] - tex[u][1];
160	    tex[u][2]  = invw0 * vert0->texcoord[u][2];
161	    dtex[u][2] = invw1 * vert1->texcoord[u][2] - tex[u][2];
162	    tex[u][3]  = invw0 * vert0->texcoord[u][3];
163	    dtex[u][3] = invw1 * vert1->texcoord[u][3] - tex[u][3];
164	 }
165      }
166   }
167#endif
168
169   /* Cull primitives with malformed coordinates.
170    */
171   {
172      float tmp = vert0->win[0] + vert0->win[1] + vert1->win[0] + vert1->win[1];
173      if (IS_INF_OR_NAN(tmp))
174	 return;
175   }
176
177   /*
178   printf("%s():\n", __FUNCTION__);
179   printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
180          vert0->win[0], vert0->win[1], vert0->win[2],
181          vert1->win[0], vert1->win[1], vert1->win[2]);
182   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
183          vert0->color[0], vert0->color[1], vert0->color[2],
184          vert1->color[0], vert1->color[1], vert1->color[2]);
185   printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
186          vert0->specular[0], vert0->specular[1], vert0->specular[2],
187          vert1->specular[0], vert1->specular[1], vert1->specular[2]);
188   */
189
190/*
191 * Despite being clipped to the view volume, the line's window coordinates
192 * may just lie outside the window bounds.  That is, if the legal window
193 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
194 * This quick and dirty code nudges the endpoints inside the window if
195 * necessary.
196 */
197#ifdef CLIP_HACK
198   {
199      GLint w = ctx->DrawBuffer->Width;
200      GLint h = ctx->DrawBuffer->Height;
201      if ((x0==w) | (x1==w)) {
202         if ((x0==w) & (x1==w))
203           return;
204         x0 -= x0==w;
205         x1 -= x1==w;
206      }
207      if ((y0==h) | (y1==h)) {
208         if ((y0==h) & (y1==h))
209           return;
210         y0 -= y0==h;
211         y1 -= y1==h;
212      }
213   }
214#endif
215   dx = x1 - x0;
216   dy = y1 - y0;
217   if (dx==0 && dy==0) {
218      return;
219   }
220
221   /*
222    * Setup
223    */
224#ifdef SETUP_CODE
225   SETUP_CODE
226#endif
227
228#ifdef INTERP_Z
229#  ifdef DEPTH_TYPE
230     zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0);
231#  endif
232   if (depthBits <= 16) {
233      z0 = FloatToFixed(vert0->win[2]) + FIXED_HALF;
234      z1 = FloatToFixed(vert1->win[2]) + FIXED_HALF;
235   }
236   else {
237      z0 = (int) vert0->win[2];
238      z1 = (int) vert1->win[2];
239   }
240#endif
241#ifdef PIXEL_ADDRESS
242   pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
243#endif
244
245   if (dx<0) {
246      dx = -dx;   /* make positive */
247#ifdef INTERP_XY
248      xstep = -1;
249#endif
250#if defined(INTERP_Z) && defined(DEPTH_TYPE)
251      zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
252#endif
253#ifdef PIXEL_ADDRESS
254      pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
255#endif
256   }
257   else {
258#ifdef INTERP_XY
259      xstep = 1;
260#endif
261#if defined(INTERP_Z) && defined(DEPTH_TYPE)
262      zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
263#endif
264#ifdef PIXEL_ADDRESS
265      pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
266#endif
267   }
268
269   if (dy<0) {
270      dy = -dy;   /* make positive */
271#ifdef INTERP_XY
272      ystep = -1;
273#endif
274#if defined(INTERP_Z) && defined(DEPTH_TYPE)
275      zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)));
276#endif
277#ifdef PIXEL_ADDRESS
278      pixelYstep = BYTES_PER_ROW;
279#endif
280   }
281   else {
282#ifdef INTERP_XY
283      ystep = 1;
284#endif
285#if defined(INTERP_Z) && defined(DEPTH_TYPE)
286      zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE));
287#endif
288#ifdef PIXEL_ADDRESS
289      pixelYstep = -(BYTES_PER_ROW);
290#endif
291   }
292
293   /*
294    * Draw
295    */
296
297   if (dx>dy) {
298      /*** X-major line ***/
299      GLint i;
300      GLint errorInc = dy+dy;
301      GLint error = errorInc-dx;
302      GLint errorDec = error-dx;
303#ifdef SET_XMAJOR
304      xMajor = GL_TRUE;
305#endif
306#ifdef INTERP_Z
307      dz = (z1-z0) / dx;
308#endif
309#ifdef INTERP_FOG
310      dfog /= dx;
311#endif
312#ifdef INTERP_RGB
313      dr /= dx;   /* convert from whole line delta to per-pixel delta */
314      dg /= dx;
315      db /= dx;
316#endif
317#ifdef INTERP_SPEC
318      dsr /= dx;   /* convert from whole line delta to per-pixel delta */
319      dsg /= dx;
320      dsb /= dx;
321#endif
322#ifdef INTERP_ALPHA
323      da /= dx;
324#endif
325#ifdef INTERP_INDEX
326      di /= dx;
327#endif
328#ifdef INTERP_TEX
329      {
330         const GLfloat invDx = 1.0F / (GLfloat) dx;
331         dtex[0] *= invDx;
332         dtex[1] *= invDx;
333         dtex[2] *= invDx;
334         dtex[3] *= invDx;
335      }
336#endif
337#ifdef INTERP_MULTITEX
338      {
339         const GLfloat invDx = 1.0F / (GLfloat) dx;
340         GLuint u;
341         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
342            if (ctx->Texture.Unit[u]._ReallyEnabled) {
343               dtex[u][0] *= invDx;
344               dtex[u][1] *= invDx;
345               dtex[u][2] *= invDx;
346               dtex[u][3] *= invDx;
347            }
348         }
349      }
350#endif
351
352      for (i=0;i<dx;i++) {
353#ifdef INTERP_Z
354            GLdepth Z = FixedToDepth(z0);
355#endif
356#ifdef INTERP_INDEX
357            GLint I = i0 >> 8;
358#endif
359#ifdef INTERP_TEX
360            {
361               const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
362               fragTexcoord[0] = tex[0] * invQ;
363               fragTexcoord[1] = tex[1] * invQ;
364               fragTexcoord[2] = tex[2] * invQ;
365               fragTexcoord[3] = tex[3];
366            }
367#endif
368#ifdef INTERP_MULTITEX
369            {
370               GLuint u;
371               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
372                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
373                     const GLfloat invQ = 1.0F / tex[u][3];
374                     fragTexcoord[u][0] = tex[u][0] * invQ;
375                     fragTexcoord[u][1] = tex[u][1] * invQ;
376                     fragTexcoord[u][2] = tex[u][2] * invQ;
377                     fragTexcoord[u][3] = tex[u][3];
378                  }
379               }
380            }
381#endif
382
383            PLOT( x0, y0 );
384
385#ifdef INTERP_XY
386         x0 += xstep;
387#endif
388#ifdef INTERP_Z
389#  ifdef DEPTH_TYPE
390         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
391#  endif
392         z0 += dz;
393#endif
394#ifdef INTERP_FOG
395	 fog0 += dfog;
396#endif
397#ifdef INTERP_RGB
398         r0 += dr;
399         g0 += dg;
400         b0 += db;
401#endif
402#ifdef INTERP_SPEC
403         sr0 += dsr;
404         sg0 += dsg;
405         sb0 += dsb;
406#endif
407#ifdef INTERP_ALPHA
408         a0 += da;
409#endif
410#ifdef INTERP_INDEX
411         i0 += di;
412#endif
413#ifdef INTERP_TEX
414         tex[0] += dtex[0];
415         tex[1] += dtex[1];
416         tex[2] += dtex[2];
417         tex[3] += dtex[3];
418#endif
419#ifdef INTERP_MULTITEX
420         {
421            GLuint u;
422            for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
423               if (ctx->Texture.Unit[u]._ReallyEnabled) {
424                  tex[u][0] += dtex[u][0];
425                  tex[u][1] += dtex[u][1];
426                  tex[u][2] += dtex[u][2];
427                  tex[u][3] += dtex[u][3];
428               }
429            }
430         }
431#endif
432
433#ifdef PIXEL_ADDRESS
434         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
435#endif
436         if (error<0) {
437            error += errorInc;
438         }
439         else {
440            error += errorDec;
441#ifdef INTERP_XY
442            y0 += ystep;
443#endif
444#if defined(INTERP_Z) && defined(DEPTH_TYPE)
445            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
446#endif
447#ifdef PIXEL_ADDRESS
448            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
449#endif
450         }
451      }
452   }
453   else {
454      /*** Y-major line ***/
455      GLint i;
456      GLint errorInc = dx+dx;
457      GLint error = errorInc-dy;
458      GLint errorDec = error-dy;
459#ifdef INTERP_Z
460      dz = (z1-z0) / dy;
461#endif
462#ifdef INTERP_FOG
463      dfog /= dy;
464#endif
465#ifdef INTERP_RGB
466      dr /= dy;   /* convert from whole line delta to per-pixel delta */
467      dg /= dy;
468      db /= dy;
469#endif
470#ifdef INTERP_SPEC
471      dsr /= dy;   /* convert from whole line delta to per-pixel delta */
472      dsg /= dy;
473      dsb /= dy;
474#endif
475#ifdef INTERP_ALPHA
476      da /= dy;
477#endif
478#ifdef INTERP_INDEX
479      di /= dy;
480#endif
481#ifdef INTERP_TEX
482      {
483         const GLfloat invDy = 1.0F / (GLfloat) dy;
484         dtex[0] *= invDy;
485         dtex[1] *= invDy;
486         dtex[2] *= invDy;
487         dtex[3] *= invDy;
488      }
489#endif
490#ifdef INTERP_MULTITEX
491      {
492         const GLfloat invDy = 1.0F / (GLfloat) dy;
493         GLuint u;
494         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
495            if (ctx->Texture.Unit[u]._ReallyEnabled) {
496               dtex[u][0] *= invDy;
497               dtex[u][1] *= invDy;
498               dtex[u][2] *= invDy;
499               dtex[u][3] *= invDy;
500            }
501         }
502      }
503#endif
504
505      for (i=0;i<dy;i++) {
506#ifdef INTERP_Z
507            GLdepth Z = FixedToDepth(z0);
508#endif
509#ifdef INTERP_INDEX
510            GLint I = i0 >> 8;
511#endif
512#ifdef INTERP_TEX
513            {
514               const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
515               fragTexcoord[0] = tex[0] * invQ;
516               fragTexcoord[1] = tex[1] * invQ;
517               fragTexcoord[2] = tex[2] * invQ;
518               fragTexcoord[3] = tex[3];
519            }
520#endif
521#ifdef INTERP_MULTITEX
522            {
523               GLuint u;
524               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
525                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
526                     const GLfloat invQ = 1.0F / tex[u][3];
527                     fragTexcoord[u][0] = tex[u][0] * invQ;
528                     fragTexcoord[u][1] = tex[u][1] * invQ;
529                     fragTexcoord[u][2] = tex[u][2] * invQ;
530                     fragTexcoord[u][3] = tex[u][3];
531                  }
532               }
533            }
534#endif
535
536            PLOT( x0, y0 );
537
538#ifdef INTERP_XY
539         y0 += ystep;
540#endif
541#ifdef INTERP_Z
542#  ifdef DEPTH_TYPE
543         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
544#  endif
545         z0 += dz;
546#endif
547#ifdef INTERP_FOG
548	 fog0 += dfog;
549#endif
550#ifdef INTERP_RGB
551         r0 += dr;
552         g0 += dg;
553         b0 += db;
554#endif
555#ifdef INTERP_SPEC
556         sr0 += dsr;
557         sg0 += dsg;
558         sb0 += dsb;
559#endif
560#ifdef INTERP_ALPHA
561         a0 += da;
562#endif
563#ifdef INTERP_INDEX
564         i0 += di;
565#endif
566#ifdef INTERP_TEX
567         tex[0] += dtex[0];
568         tex[1] += dtex[1];
569         tex[2] += dtex[2];
570         tex[3] += dtex[3];
571#endif
572#ifdef INTERP_MULTITEX
573         {
574            GLuint u;
575            for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
576               if (ctx->Texture.Unit[u]._ReallyEnabled) {
577                  tex[u][0] += dtex[u][0];
578                  tex[u][1] += dtex[u][1];
579                  tex[u][2] += dtex[u][2];
580                  tex[u][3] += dtex[u][3];
581               }
582            }
583         }
584#endif
585#ifdef PIXEL_ADDRESS
586         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
587#endif
588         if (error<0) {
589            error += errorInc;
590         }
591         else {
592            error += errorDec;
593#ifdef INTERP_XY
594            x0 += xstep;
595#endif
596#if defined(INTERP_Z) && defined(DEPTH_TYPE)
597            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
598#endif
599#ifdef PIXEL_ADDRESS
600            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
601#endif
602         }
603      }
604   }
605
606}
607
608
609#undef INTERP_XY
610#undef INTERP_Z
611#undef INTERP_FOG
612#undef INTERP_RGB
613#undef INTERP_SPEC
614#undef INTERP_ALPHA
615#undef INTERP_TEX
616#undef INTERP_MULTITEX
617#undef INTERP_INDEX
618#undef PIXEL_ADDRESS
619#undef PIXEL_TYPE
620#undef DEPTH_TYPE
621#undef BYTES_PER_ROW
622#undef SETUP_CODE
623#undef PLOT
624#undef CLIP_HACK
625#undef FixedToDepth
626#undef SET_XMAJOR
627