template code for span functions for flat, memory-based frame buffers
[mesa.git] / src / mesa / swrast / s_linetemp.h
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