Converted line drawing over to new span code, pb no longer used.
[mesa.git] / src / mesa / swrast / s_linetemp.h
1 /* $Id: s_linetemp.h,v 1.12 2002/02/02 21:40:33 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
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)\n",
180 vert0->win[0], vert0->win[1], vert1->win[0], vert1->win[1]);
181 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
182 vert0->color[0], vert0->color[1], vert0->color[2],
183 vert1->color[0], vert1->color[1], vert1->color[2]);
184 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
185 vert0->specular[0], vert0->specular[1], vert0->specular[2],
186 vert1->specular[0], vert1->specular[1], vert1->specular[2]);
187 */
188
189 /*
190 * Despite being clipped to the view volume, the line's window coordinates
191 * may just lie outside the window bounds. That is, if the legal window
192 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
193 * This quick and dirty code nudges the endpoints inside the window if
194 * necessary.
195 */
196 #ifdef CLIP_HACK
197 {
198 GLint w = ctx->DrawBuffer->Width;
199 GLint h = ctx->DrawBuffer->Height;
200 if ((x0==w) | (x1==w)) {
201 if ((x0==w) & (x1==w))
202 return;
203 x0 -= x0==w;
204 x1 -= x1==w;
205 }
206 if ((y0==h) | (y1==h)) {
207 if ((y0==h) & (y1==h))
208 return;
209 y0 -= y0==h;
210 y1 -= y1==h;
211 }
212 }
213 #endif
214 dx = x1 - x0;
215 dy = y1 - y0;
216 if (dx==0 && dy==0) {
217 return;
218 }
219
220 /*
221 * Setup
222 */
223 #ifdef SETUP_CODE
224 SETUP_CODE
225 #endif
226
227 #ifdef INTERP_Z
228 # ifdef DEPTH_TYPE
229 zPtr = (DEPTH_TYPE *) _mesa_zbuffer_address(ctx, x0, y0);
230 # endif
231 if (depthBits <= 16) {
232 z0 = FloatToFixed(vert0->win[2]);
233 z1 = FloatToFixed(vert1->win[2]);
234 }
235 else {
236 z0 = (int) vert0->win[2];
237 z1 = (int) vert1->win[2];
238 }
239 #endif
240 #ifdef PIXEL_ADDRESS
241 pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0);
242 #endif
243
244 if (dx<0) {
245 dx = -dx; /* make positive */
246 #ifdef INTERP_XY
247 xstep = -1;
248 #endif
249 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
250 zPtrXstep = -((GLint)sizeof(DEPTH_TYPE));
251 #endif
252 #ifdef PIXEL_ADDRESS
253 pixelXstep = -((GLint)sizeof(PIXEL_TYPE));
254 #endif
255 }
256 else {
257 #ifdef INTERP_XY
258 xstep = 1;
259 #endif
260 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
261 zPtrXstep = ((GLint)sizeof(DEPTH_TYPE));
262 #endif
263 #ifdef PIXEL_ADDRESS
264 pixelXstep = ((GLint)sizeof(PIXEL_TYPE));
265 #endif
266 }
267
268 if (dy<0) {
269 dy = -dy; /* make positive */
270 #ifdef INTERP_XY
271 ystep = -1;
272 #endif
273 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
274 zPtrYstep = -ctx->DrawBuffer->Width * ((GLint)sizeof(DEPTH_TYPE));
275 #endif
276 #ifdef PIXEL_ADDRESS
277 pixelYstep = BYTES_PER_ROW;
278 #endif
279 }
280 else {
281 #ifdef INTERP_XY
282 ystep = 1;
283 #endif
284 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
285 zPtrYstep = ctx->DrawBuffer->Width * ((GLint)sizeof(DEPTH_TYPE));
286 #endif
287 #ifdef PIXEL_ADDRESS
288 pixelYstep = -(BYTES_PER_ROW);
289 #endif
290 }
291
292 /*
293 * Draw
294 */
295
296 if (dx>dy) {
297 /*** X-major line ***/
298 GLint i;
299 GLint errorInc = dy+dy;
300 GLint error = errorInc-dx;
301 GLint errorDec = error-dx;
302 #ifdef SET_XMAJOR
303 xMajor = GL_TRUE;
304 #endif
305 #ifdef INTERP_Z
306 dz = (z1-z0) / dx;
307 #endif
308 #ifdef INTERP_FOG
309 dfog /= dx;
310 #endif
311 #ifdef INTERP_RGB
312 dr /= dx; /* convert from whole line delta to per-pixel delta */
313 dg /= dx;
314 db /= dx;
315 #endif
316 #ifdef INTERP_SPEC
317 dsr /= dx; /* convert from whole line delta to per-pixel delta */
318 dsg /= dx;
319 dsb /= dx;
320 #endif
321 #ifdef INTERP_ALPHA
322 da /= dx;
323 #endif
324 #ifdef INTERP_INDEX
325 di /= dx;
326 #endif
327 #ifdef INTERP_TEX
328 {
329 const GLfloat invDx = 1.0F / (GLfloat) dx;
330 dtex[0] *= invDx;
331 dtex[1] *= invDx;
332 dtex[2] *= invDx;
333 dtex[3] *= invDx;
334 }
335 #endif
336 #ifdef INTERP_MULTITEX
337 {
338 const GLfloat invDx = 1.0F / (GLfloat) dx;
339 GLuint u;
340 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
341 if (ctx->Texture.Unit[u]._ReallyEnabled) {
342 dtex[u][0] *= invDx;
343 dtex[u][1] *= invDx;
344 dtex[u][2] *= invDx;
345 dtex[u][3] *= invDx;
346 }
347 }
348 }
349 #endif
350
351 for (i=0;i<dx;i++) {
352 #ifdef INTERP_Z
353 GLdepth Z = FixedToDepth(z0);
354 #endif
355 #ifdef INTERP_INDEX
356 GLint I = i0 >> 8;
357 #endif
358 #ifdef INTERP_TEX
359 {
360 const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
361 fragTexcoord[0] = tex[0] * invQ;
362 fragTexcoord[1] = tex[1] * invQ;
363 fragTexcoord[2] = tex[2] * invQ;
364 fragTexcoord[3] = tex[3];
365 }
366 #endif
367 #ifdef INTERP_MULTITEX
368 {
369 GLuint u;
370 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
371 if (ctx->Texture.Unit[u]._ReallyEnabled) {
372 const GLfloat invQ = 1.0F / tex[u][3];
373 fragTexcoord[u][0] = tex[u][0] * invQ;
374 fragTexcoord[u][1] = tex[u][1] * invQ;
375 fragTexcoord[u][2] = tex[u][2] * invQ;
376 fragTexcoord[u][3] = tex[u][3];
377 }
378 }
379 }
380 #endif
381
382 PLOT( x0, y0 );
383
384 #ifdef INTERP_XY
385 x0 += xstep;
386 #endif
387 #ifdef INTERP_Z
388 # ifdef DEPTH_TYPE
389 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
390 # endif
391 z0 += dz;
392 #endif
393 #ifdef INTERP_FOG
394 fog0 += dfog;
395 #endif
396 #ifdef INTERP_RGB
397 r0 += dr;
398 g0 += dg;
399 b0 += db;
400 #endif
401 #ifdef INTERP_SPEC
402 sr0 += dsr;
403 sg0 += dsg;
404 sb0 += dsb;
405 #endif
406 #ifdef INTERP_ALPHA
407 a0 += da;
408 #endif
409 #ifdef INTERP_INDEX
410 i0 += di;
411 #endif
412 #ifdef INTERP_TEX
413 tex[0] += dtex[0];
414 tex[1] += dtex[1];
415 tex[2] += dtex[2];
416 tex[3] += dtex[3];
417 #endif
418 #ifdef INTERP_MULTITEX
419 {
420 GLuint u;
421 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
422 if (ctx->Texture.Unit[u]._ReallyEnabled) {
423 tex[u][0] += dtex[u][0];
424 tex[u][1] += dtex[u][1];
425 tex[u][2] += dtex[u][2];
426 tex[u][3] += dtex[u][3];
427 }
428 }
429 }
430 #endif
431
432 #ifdef PIXEL_ADDRESS
433 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
434 #endif
435 if (error<0) {
436 error += errorInc;
437 }
438 else {
439 error += errorDec;
440 #ifdef INTERP_XY
441 y0 += ystep;
442 #endif
443 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
444 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
445 #endif
446 #ifdef PIXEL_ADDRESS
447 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
448 #endif
449 }
450 }
451 }
452 else {
453 /*** Y-major line ***/
454 GLint i;
455 GLint errorInc = dx+dx;
456 GLint error = errorInc-dy;
457 GLint errorDec = error-dy;
458 #ifdef INTERP_Z
459 dz = (z1-z0) / dy;
460 #endif
461 #ifdef INTERP_FOG
462 dfog /= dy;
463 #endif
464 #ifdef INTERP_RGB
465 dr /= dy; /* convert from whole line delta to per-pixel delta */
466 dg /= dy;
467 db /= dy;
468 #endif
469 #ifdef INTERP_SPEC
470 dsr /= dy; /* convert from whole line delta to per-pixel delta */
471 dsg /= dy;
472 dsb /= dy;
473 #endif
474 #ifdef INTERP_ALPHA
475 da /= dy;
476 #endif
477 #ifdef INTERP_INDEX
478 di /= dy;
479 #endif
480 #ifdef INTERP_TEX
481 {
482 const GLfloat invDy = 1.0F / (GLfloat) dy;
483 dtex[0] *= invDy;
484 dtex[1] *= invDy;
485 dtex[2] *= invDy;
486 dtex[3] *= invDy;
487 }
488 #endif
489 #ifdef INTERP_MULTITEX
490 {
491 const GLfloat invDy = 1.0F / (GLfloat) dy;
492 GLuint u;
493 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
494 if (ctx->Texture.Unit[u]._ReallyEnabled) {
495 dtex[u][0] *= invDy;
496 dtex[u][1] *= invDy;
497 dtex[u][2] *= invDy;
498 dtex[u][3] *= invDy;
499 }
500 }
501 }
502 #endif
503
504 for (i=0;i<dy;i++) {
505 #ifdef INTERP_Z
506 GLdepth Z = FixedToDepth(z0);
507 #endif
508 #ifdef INTERP_INDEX
509 GLint I = i0 >> 8;
510 #endif
511 #ifdef INTERP_TEX
512 {
513 const GLfloat invQ = tex[3] ? (1.0F / tex[3]) : 1.0F;
514 fragTexcoord[0] = tex[0] * invQ;
515 fragTexcoord[1] = tex[1] * invQ;
516 fragTexcoord[2] = tex[2] * invQ;
517 fragTexcoord[3] = tex[3];
518 }
519 #endif
520 #ifdef INTERP_MULTITEX
521 {
522 GLuint u;
523 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
524 if (ctx->Texture.Unit[u]._ReallyEnabled) {
525 const GLfloat invQ = 1.0F / tex[u][3];
526 fragTexcoord[u][0] = tex[u][0] * invQ;
527 fragTexcoord[u][1] = tex[u][1] * invQ;
528 fragTexcoord[u][2] = tex[u][2] * invQ;
529 fragTexcoord[u][3] = tex[u][3];
530 }
531 }
532 }
533 #endif
534
535 PLOT( x0, y0 );
536
537 #ifdef INTERP_XY
538 y0 += ystep;
539 #endif
540 #ifdef INTERP_Z
541 # ifdef DEPTH_TYPE
542 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep);
543 # endif
544 z0 += dz;
545 #endif
546 #ifdef INTERP_FOG
547 fog0 += dfog;
548 #endif
549 #ifdef INTERP_RGB
550 r0 += dr;
551 g0 += dg;
552 b0 += db;
553 #endif
554 #ifdef INTERP_SPEC
555 sr0 += dsr;
556 sg0 += dsg;
557 sb0 += dsb;
558 #endif
559 #ifdef INTERP_ALPHA
560 a0 += da;
561 #endif
562 #ifdef INTERP_INDEX
563 i0 += di;
564 #endif
565 #ifdef INTERP_TEX
566 tex[0] += dtex[0];
567 tex[1] += dtex[1];
568 tex[2] += dtex[2];
569 tex[3] += dtex[3];
570 #endif
571 #ifdef INTERP_MULTITEX
572 {
573 GLuint u;
574 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
575 if (ctx->Texture.Unit[u]._ReallyEnabled) {
576 tex[u][0] += dtex[u][0];
577 tex[u][1] += dtex[u][1];
578 tex[u][2] += dtex[u][2];
579 tex[u][3] += dtex[u][3];
580 }
581 }
582 }
583 #endif
584 #ifdef PIXEL_ADDRESS
585 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep);
586 #endif
587 if (error<0) {
588 error += errorInc;
589 }
590 else {
591 error += errorDec;
592 #ifdef INTERP_XY
593 x0 += xstep;
594 #endif
595 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
596 zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep);
597 #endif
598 #ifdef PIXEL_ADDRESS
599 pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep);
600 #endif
601 }
602 }
603 }
604
605 }
606
607
608 #undef INTERP_XY
609 #undef INTERP_Z
610 #undef INTERP_FOG
611 #undef INTERP_RGB
612 #undef INTERP_SPEC
613 #undef INTERP_ALPHA
614 #undef INTERP_TEX
615 #undef INTERP_MULTITEX
616 #undef INTERP_INDEX
617 #undef PIXEL_ADDRESS
618 #undef PIXEL_TYPE
619 #undef DEPTH_TYPE
620 #undef BYTES_PER_ROW
621 #undef SETUP_CODE
622 #undef PLOT
623 #undef CLIP_HACK
624 #undef FixedToDepth
625 #undef SET_XMAJOR