s_linetemp.h revision cd03ed4f54444d96e4e47cdb118a3dfd94d92bb0
1/* $Id: s_linetemp.h,v 1.2 2000/11/05 18:24:40 keithw Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2000  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 and FOG values
36 *    INTERP_RGB      - if defined, interpolate RGB values
37 *    INTERP_SPEC     - if defined, interpolate specular RGB values
38 *    INTERP_ALPHA    - if defined, interpolate Alpha values
39 *    INTERP_INDEX    - if defined, interpolate color index values
40 *    INTERP_TEX      - if defined, interpolate unit 0 texcoords
41 *    INTERP_MULTITEX - if defined, interpolate multi-texcoords
42 *
43 * When one can directly address pixels in the color buffer the following
44 * macros can be defined and used to directly compute pixel addresses during
45 * rasterization (see pixelPtr):
46 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
47 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
48 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
49 *                          Y==0 at bottom of screen and increases upward.
50 *
51 * Similarly, for direct depth buffer access, this type is used for depth
52 * buffer addressing:
53 *    DEPTH_TYPE          - either GLushort or GLuint
54 *
55 * Optionally, one may provide one-time setup code
56 *    SETUP_CODE    - code which is to be executed once per line
57 *
58 * To enable line stippling define STIPPLE = 1
59 * To enable wide lines define WIDE = 1
60 *
61 * To actually "plot" each pixel either the PLOT macro or
62 * (XMAJOR_PLOT and YMAJOR_PLOT macros) must be defined...
63 *    PLOT(X,Y) - code to plot a pixel.  Example:
64 *                if (Z < *zPtr) {
65 *                   *zPtr = Z;
66 *                   color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
67 *                                     FixedToInt(b0) );
68 *                   put_pixel( X, Y, color );
69 *                }
70 *
71 * This code was designed for the origin to be in the lower-left corner.
72 *
73 */
74
75
76/*void line( GLcontext *ctx, SWvertex *vert0, SWvertex *vert1 )*/
77{
78   GLint x0 = (GLint) vert0->win[0];
79   GLint x1 = (GLint) vert1->win[0];
80   GLint y0 = (GLint) vert0->win[1];
81   GLint y1 = (GLint) vert1->win[1];
82   GLint dx, dy;
83#ifdef INTERP_XY
84   GLint xstep, ystep;
85#endif
86#ifdef INTERP_Z
87   GLint z0, z1, dz;
88   const GLint depthBits = ctx->Visual.DepthBits;
89   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
90#  define FixedToDepth(F)  ((F) >> fixedToDepthShift)
91#  ifdef DEPTH_TYPE
92   GLint zPtrXstep, zPtrYstep;
93   DEPTH_TYPE *zPtr;
94#  endif
95   GLfixed fog0 = FloatToFixed(vert0->fog);
96   GLfixed dfog = FloatToFixed(vert1->fog) - fog0;
97#endif
98#ifdef INTERP_RGB
99   GLfixed r0 = IntToFixed(vert0->color[0]);
100   GLfixed dr = IntToFixed(vert1->color[0]) - r0;
101   GLfixed g0 = IntToFixed(vert0->color[1]);
102   GLfixed dg = IntToFixed(vert1->color[1]) - g0;
103   GLfixed b0 = IntToFixed(vert0->color[2]);
104   GLfixed db = IntToFixed(vert1->color[2]) - b0;
105#endif
106#ifdef INTERP_SPEC
107   GLfixed sr0 = IntToFixed(vert0->specular[0]);
108   GLfixed dsr = IntToFixed(vert1->specular[0]) - sr0;
109   GLfixed sg0 = IntToFixed(vert0->specular[1]);
110   GLfixed dsg = IntToFixed(vert1->specular[1]) - sg0;
111   GLfixed sb0 = IntToFixed(vert0->specular[2]);
112   GLfixed dsb = IntToFixed(vert1->specular[2]) - sb0;
113#endif
114#ifdef INTERP_ALPHA
115   GLfixed a0 = IntToFixed(vert0->color[3]);
116   GLfixed da = IntToFixed(vert1->color[3]) - a0;
117#endif
118#ifdef INTERP_INDEX
119   GLint i0 = vert0->index << 8;
120   GLint di = (GLint) (vert1->index << 8) - i0;
121#endif
122#ifdef INTERP_TEX
123   const GLfloat invw0 = vert0->win[3];
124   const GLfloat invw1 = vert1->win[3];
125   GLfloat tex[4];
126   GLfloat dtex[4];
127   GLfloat fragTexcoord[4];
128#endif
129#ifdef INTERP_MULTITEX
130   const GLfloat invw0 = vert0->win[3];
131   const GLfloat invw1 = vert1->win[3];
132   GLfloat tex[MAX_TEXTURE_UNITS][4];
133   GLfloat dtex[MAX_TEXTURE_UNITS][4];
134   GLfloat fragTexcoord[MAX_TEXTURE_UNITS][4];
135#endif
136#ifdef PIXEL_ADDRESS
137   PIXEL_TYPE *pixelPtr;
138   GLint pixelXstep, pixelYstep;
139#endif
140#ifdef STIPPLE
141   SWcontext *swrast = SWRAST_CONTEXT(ctx);
142#endif
143#ifdef WIDE
144   /* for wide lines, draw all X in [x+min, x+max] or Y in [y+min, y+max] */
145   GLint width, min, max;
146   width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
147   min = (width-1) / -2;
148   max = min + width - 1;
149#endif
150#ifdef INTERP_TEX
151   {
152      tex[0]  = invw0 * vert0->texcoord[0][0];
153      dtex[0] = invw1 * vert1->texcoord[0][0] - tex[0];
154      tex[1]  = invw0 * vert0->texcoord[0][1];
155      dtex[1] = invw1 * vert1->texcoord[0][1] - tex[1];
156      tex[2]  = invw0 * vert0->texcoord[0][2];
157      dtex[2] = invw1 * vert1->texcoord[0][2] - tex[2];
158      tex[3]  = invw0 * vert0->texcoord[0][3];
159      dtex[3] = invw1 * vert1->texcoord[0][3] - tex[3];
160   }
161#endif
162#ifdef INTERP_MULTITEX
163   {
164      GLuint u;
165      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
166         if (ctx->Texture.Unit[u]._ReallyEnabled) {
167            tex[u][0]  = invw0 * vert0->texcoord[u][0];
168            dtex[u][0] = invw1 * vert1->texcoord[u][0] - tex[u][0];
169	    tex[u][1]  = invw0 * vert0->texcoord[u][1];
170	    dtex[u][1] = invw1 * vert1->texcoord[u][1] - tex[u][1];
171	    tex[u][2]  = invw0 * vert0->texcoord[u][2];
172	    dtex[u][2] = invw1 * vert1->texcoord[u][2] - tex[u][2];
173	    tex[u][3]  = invw0 * vert0->texcoord[u][3];
174	    dtex[u][3] = invw1 * vert1->texcoord[u][3] - tex[u][3];
175	 }
176      }
177   }
178#endif
179
180
181/*
182 * Despite being clipped to the view volume, the line's window coordinates
183 * may just lie outside the window bounds.  That is, if the legal window
184 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
185 * This quick and dirty code nudges the endpoints inside the window if
186 * necessary.
187 */
188#ifdef CLIP_HACK
189   {
190      GLint w = ctx->DrawBuffer->Width;
191      GLint h = ctx->DrawBuffer->Height;
192      if ((x0==w) | (x1==w)) {
193         if ((x0==w) & (x1==w))
194           return;
195         x0 -= x0==w;
196         x1 -= x1==w;
197      }
198      if ((y0==h) | (y1==h)) {
199         if ((y0==h) & (y1==h))
200           return;
201         y0 -= y0==h;
202         y1 -= y1==h;
203      }
204   }
205#endif
206   dx = x1 - x0;
207   dy = y1 - y0;
208   if (dx==0 && dy==0) {
209      return;
210   }
211
212   /*
213    * Setup
214    */
215#ifdef SETUP_CODE
216   SETUP_CODE
217#endif
218
219#ifdef INTERP_Z
220#  ifdef DEPTH_TYPE
221     zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0);
222#  endif
223   if (depthBits <= 16) {
224      z0 = FloatToFixed(vert0->win[2]);
225      z1 = FloatToFixed(vert1->win[2]);
226   }
227   else {
228      z0 = (int) vert0->win[2];
229      z1 = (int) vert1->win[2];
230   }
231#endif
232#ifdef PIXEL_ADDRESS
233   pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
234#endif
235
236   if (dx<0) {
237      dx = -dx;   /* make positive */
238#ifdef INTERP_XY
239      xstep = -1;
240#endif
241#if defined(INTERP_Z) && defined(DEPTH_TYPE)
242      zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
243#endif
244#ifdef PIXEL_ADDRESS
245      pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
246#endif
247   }
248   else {
249#ifdef INTERP_XY
250      xstep = 1;
251#endif
252#if defined(INTERP_Z) && defined(DEPTH_TYPE)
253      zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
254#endif
255#ifdef PIXEL_ADDRESS
256      pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
257#endif
258   }
259
260   if (dy<0) {
261      dy = -dy;   /* make positive */
262#ifdef INTERP_XY
263      ystep = -1;
264#endif
265#if defined(INTERP_Z) && defined(DEPTH_TYPE)
266      zPtrYstep = -ctx->DrawBuffer->Width * ((GLint)sizeof(DEPTH_TYPE));
267#endif
268#ifdef PIXEL_ADDRESS
269      pixelYstep = BYTES_PER_ROW;
270#endif
271   }
272   else {
273#ifdef INTERP_XY
274      ystep = 1;
275#endif
276#if defined(INTERP_Z) && defined(DEPTH_TYPE)
277      zPtrYstep = ctx->DrawBuffer->Width * ((GLint)sizeof(DEPTH_TYPE));
278#endif
279#ifdef PIXEL_ADDRESS
280      pixelYstep = -(BYTES_PER_ROW);
281#endif
282   }
283
284   /*
285    * Draw
286    */
287
288   if (dx>dy) {
289      /*** X-major line ***/
290      GLint i;
291      GLint errorInc = dy+dy;
292      GLint error = errorInc-dx;
293      GLint errorDec = error-dx;
294#ifdef INTERP_Z
295      dz = (z1-z0) / dx;
296      dfog /= dx;
297#endif
298#ifdef INTERP_RGB
299      dr /= dx;   /* convert from whole line delta to per-pixel delta */
300      dg /= dx;
301      db /= dx;
302#endif
303#ifdef INTERP_SPEC
304      dsr /= dx;   /* convert from whole line delta to per-pixel delta */
305      dsg /= dx;
306      dsb /= dx;
307#endif
308#ifdef INTERP_ALPHA
309      da /= dx;
310#endif
311#ifdef INTERP_INDEX
312      di /= dx;
313#endif
314#ifdef INTERP_TEX
315      {
316         const GLfloat invDx = 1.0F / (GLfloat) dx;
317         dtex[0] *= invDx;
318         dtex[1] *= invDx;
319         dtex[2] *= invDx;
320         dtex[3] *= invDx;
321      }
322#endif
323#ifdef INTERP_MULTITEX
324      {
325         const GLfloat invDx = 1.0F / (GLfloat) dx;
326         GLuint u;
327         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
328            if (ctx->Texture.Unit[u]._ReallyEnabled) {
329               dtex[u][0] *= invDx;
330               dtex[u][1] *= invDx;
331               dtex[u][2] *= invDx;
332               dtex[u][3] *= invDx;
333            }
334         }
335      }
336#endif
337
338      for (i=0;i<dx;i++) {
339#ifdef STIPPLE
340         GLushort m;
341         m = 1 << ((swrast->StippleCounter/ctx->Line.StippleFactor) & 0xf);
342         if (ctx->Line.StipplePattern & m) {
343#endif
344#ifdef INTERP_Z
345            GLdepth Z = FixedToDepth(z0);
346#endif
347#ifdef INTERP_INDEX
348            GLint I = i0 >> 8;
349#endif
350#ifdef INTERP_TEX
351            {
352               const GLfloat invQ = 1.0F / tex[3];
353               fragTexcoord[0] = tex[0] * invQ;
354               fragTexcoord[1] = tex[1] * invQ;
355               fragTexcoord[2] = tex[2] * invQ;
356            }
357#endif
358#ifdef INTERP_MULTITEX
359            {
360               GLuint u;
361               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
362                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
363                     const GLfloat invQ = 1.0F / tex[u][3];
364                     fragTexcoord[u][0] = tex[u][0] * invQ;
365                     fragTexcoord[u][1] = tex[u][1] * invQ;
366                     fragTexcoord[u][2] = tex[u][2] * invQ;
367                  }
368               }
369            }
370#endif
371#ifdef WIDE
372            {
373               GLint yy;
374               GLint ymin = y0 + min;
375               GLint ymax = y0 + max;
376               for (yy=ymin;yy<=ymax;yy++) {
377                  PLOT( x0, yy );
378               }
379            }
380#else
381#  ifdef XMAJOR_PLOT
382            XMAJOR_PLOT( x0, y0 );
383#  else
384            PLOT( x0, y0 );
385#  endif
386#endif /*WIDE*/
387#ifdef STIPPLE
388        }
389	swrast->StippleCounter++;
390#endif
391#ifdef INTERP_XY
392         x0 += xstep;
393#endif
394#ifdef INTERP_Z
395#  ifdef DEPTH_TYPE
396         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
397#  endif
398         z0 += dz;
399	 fog0 += dfog;
400#endif
401#ifdef INTERP_RGB
402         r0 += dr;
403         g0 += dg;
404         b0 += db;
405#endif
406#ifdef INTERP_SPEC
407         sr0 += dsr;
408         sg0 += dsg;
409         sb0 += dsb;
410#endif
411#ifdef INTERP_ALPHA
412         a0 += da;
413#endif
414#ifdef INTERP_INDEX
415         i0 += di;
416#endif
417#ifdef INTERP_TEX
418         tex[0] += dtex[0];
419         tex[1] += dtex[1];
420         tex[2] += dtex[2];
421         tex[3] += dtex[3];
422#endif
423#ifdef INTERP_MULTITEX
424         {
425            GLuint u;
426            for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
427               if (ctx->Texture.Unit[u]._ReallyEnabled) {
428                  tex[u][0] += dtex[u][0];
429                  tex[u][1] += dtex[u][1];
430                  tex[u][2] += dtex[u][2];
431                  tex[u][3] += dtex[u][3];
432               }
433            }
434         }
435#endif
436
437#ifdef PIXEL_ADDRESS
438         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
439#endif
440         if (error<0) {
441            error += errorInc;
442         }
443         else {
444            error += errorDec;
445#ifdef INTERP_XY
446            y0 += ystep;
447#endif
448#if defined(INTERP_Z) && defined(DEPTH_TYPE)
449            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
450#endif
451#ifdef PIXEL_ADDRESS
452            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
453#endif
454         }
455      }
456   }
457   else {
458      /*** Y-major line ***/
459      GLint i;
460      GLint errorInc = dx+dx;
461      GLint error = errorInc-dy;
462      GLint errorDec = error-dy;
463#ifdef INTERP_Z
464      dz = (z1-z0) / dy;
465      dfog /= dy;
466#endif
467#ifdef INTERP_RGB
468      dr /= dy;   /* convert from whole line delta to per-pixel delta */
469      dg /= dy;
470      db /= dy;
471#endif
472#ifdef INTERP_SPEC
473      dsr /= dy;   /* convert from whole line delta to per-pixel delta */
474      dsg /= dy;
475      dsb /= dy;
476#endif
477#ifdef INTERP_ALPHA
478      da /= dy;
479#endif
480#ifdef INTERP_INDEX
481      di /= dy;
482#endif
483#ifdef INTERP_TEX
484      {
485         const GLfloat invDy = 1.0F / (GLfloat) dy;
486         dtex[0] *= invDy;
487         dtex[1] *= invDy;
488         dtex[2] *= invDy;
489         dtex[3] *= invDy;
490      }
491#endif
492#ifdef INTERP_MULTITEX
493      {
494         const GLfloat invDy = 1.0F / (GLfloat) dy;
495         GLuint u;
496         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
497            if (ctx->Texture.Unit[u]._ReallyEnabled) {
498               dtex[u][0] *= invDy;
499               dtex[u][1] *= invDy;
500               dtex[u][2] *= invDy;
501               dtex[u][3] *= invDy;
502            }
503         }
504      }
505#endif
506
507      for (i=0;i<dy;i++) {
508#ifdef STIPPLE
509         GLushort m;
510         m = 1 << ((swrast->StippleCounter/ctx->Line.StippleFactor) & 0xf);
511         if (ctx->Line.StipplePattern & m) {
512#endif
513#ifdef INTERP_Z
514            GLdepth Z = FixedToDepth(z0);
515#endif
516#ifdef INTERP_INDEX
517            GLint I = i0 >> 8;
518#endif
519#ifdef INTERP_TEX
520            {
521               const GLfloat invQ = 1.0F / tex[3];
522               fragTexcoord[0] = tex[0] * invQ;
523               fragTexcoord[1] = tex[1] * invQ;
524               fragTexcoord[2] = tex[2] * invQ;
525            }
526#endif
527#ifdef INTERP_MULTITEX
528            {
529               GLuint u;
530               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
531                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
532                     const GLfloat invQ = 1.0F / tex[u][3];
533                     fragTexcoord[u][0] = tex[u][0] * invQ;
534                     fragTexcoord[u][1] = tex[u][1] * invQ;
535                     fragTexcoord[u][2] = tex[u][2] * invQ;
536                  }
537               }
538            }
539#endif
540#ifdef WIDE
541            {
542               GLint xx;
543               GLint xmin = x0 + min;
544               GLint xmax = x0 + max;
545               for (xx=xmin;xx<=xmax;xx++) {
546                  PLOT( xx, y0 );
547               }
548            }
549#else
550#  ifdef YMAJOR_PLOT
551            YMAJOR_PLOT( x0, y0 );
552#  else
553            PLOT( x0, y0 );
554#  endif
555#endif /*WIDE*/
556#ifdef STIPPLE
557        }
558	swrast->StippleCounter++;
559#endif
560#ifdef INTERP_XY
561         y0 += ystep;
562#endif
563#ifdef INTERP_Z
564#  ifdef DEPTH_TYPE
565         zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
566#  endif
567         z0 += dz;
568	 fog0 += dfog;
569#endif
570#ifdef INTERP_RGB
571         r0 += dr;
572         g0 += dg;
573         b0 += db;
574#endif
575#ifdef INTERP_SPEC
576         sr0 += dsr;
577         sg0 += dsg;
578         sb0 += dsb;
579#endif
580#ifdef INTERP_ALPHA
581         a0 += da;
582#endif
583#ifdef INTERP_INDEX
584         i0 += di;
585#endif
586#ifdef INTERP_TEX
587         tex[0] += dtex[0];
588         tex[1] += dtex[1];
589         tex[2] += dtex[2];
590         tex[3] += dtex[3];
591#endif
592#ifdef INTERP_MULTITEX
593         {
594            GLuint u;
595            for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
596               if (ctx->Texture.Unit[u]._ReallyEnabled) {
597                  tex[u][0] += dtex[u][0];
598                  tex[u][1] += dtex[u][1];
599                  tex[u][2] += dtex[u][2];
600                  tex[u][3] += dtex[u][3];
601               }
602            }
603         }
604#endif
605#ifdef PIXEL_ADDRESS
606         pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
607#endif
608         if (error<0) {
609            error += errorInc;
610         }
611         else {
612            error += errorDec;
613#ifdef INTERP_XY
614            x0 += xstep;
615#endif
616#if defined(INTERP_Z) && defined(DEPTH_TYPE)
617            zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
618#endif
619#ifdef PIXEL_ADDRESS
620            pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
621#endif
622         }
623      }
624   }
625
626}
627
628
629#undef INTERP_XY
630#undef INTERP_Z
631#undef INTERP_RGB
632#undef INTERP_SPEC
633#undef INTERP_ALPHA
634#undef INTERP_TEX
635#undef INTERP_MULTITEX
636#undef INTERP_INDEX
637#undef PIXEL_ADDRESS
638#undef PIXEL_TYPE
639#undef DEPTH_TYPE
640#undef BYTES_PER_ROW
641#undef SETUP_CODE
642#undef PLOT
643#undef XMAJOR_PLOT
644#undef YMAJOR_PLOT
645#undef CLIP_HACK
646#undef STIPPLE
647#undef WIDE
648#undef FixedToDepth
649