Replaced struct gl_visual with struct __GLcontextModesRec from glcore.h.
[mesa.git] / src / mesa / swrast / s_linetemp.h
1 /* $Id: s_linetemp.h,v 1.4 2001/01/23 23:39:37 brianp 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, const SWvertex *vert0, const 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