1 /* $Id: s_linetemp.h,v 1.14 2002/11/09 21:26:41 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
29 * Line Rasterizer Template
31 * This file is #include'd to generate custom line rasterizers.
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
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.
52 * Similarly, for direct depth buffer access, this type is used for depth
54 * DEPTH_TYPE - either GLushort or GLuint
56 * Optionally, one may provide one-time setup code
57 * SETUP_CODE - code which is to be executed once per line
59 * To actually "plot" each pixel the PLOT macro must be defined...
60 * PLOT(X,Y) - code to plot a pixel. Example:
63 * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
65 * put_pixel( X, Y, color );
68 * This code was designed for the origin to be in the lower-left corner.
73 /*void line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )*/
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];
85 const GLint depthBits
= ctx
->Visual
.depthBits
;
86 const GLint fixedToDepthShift
= depthBits
<= 16 ? FIXED_SHIFT
: 0;
87 # define FixedToDepth(F) ((F) >> fixedToDepthShift)
89 GLint zPtrXstep
, zPtrYstep
;
94 GLfloat fog0
= vert0
->fog
;
95 GLfloat dfog
= vert1
->fog
- fog0
;
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
;
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
;
114 GLfixed a0
= ChanToFixed(vert0
->color
[3]);
115 GLfixed da
= ChanToFixed(vert1
->color
[3]) - a0
;
118 GLint i0
= vert0
->index
<< 8;
119 GLint di
= (GLint
) (vert1
->index
<< 8) - i0
;
122 const GLfloat invw0
= vert0
->win
[3];
123 const GLfloat invw1
= vert1
->win
[3];
126 GLfloat fragTexcoord
[4];
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];
136 PIXEL_TYPE
*pixelPtr
;
137 GLint pixelXstep
, pixelYstep
;
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];
151 #ifdef INTERP_MULTITEX
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];
169 /* Cull primitives with malformed coordinates.
172 float tmp
= vert0
->win
[0] + vert0
->win
[1] + vert1
->win
[0] + vert1
->win
[1];
173 if (IS_INF_OR_NAN(tmp
))
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]);
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
199 GLint w
= ctx
->DrawBuffer
->Width
;
200 GLint h
= ctx
->DrawBuffer
->Height
;
201 if ((x0
==w
) | (x1
==w
)) {
202 if ((x0
==w
) & (x1
==w
))
207 if ((y0
==h
) | (y1
==h
)) {
208 if ((y0
==h
) & (y1
==h
))
217 if (dx
==0 && dy
==0) {
230 zPtr
= (DEPTH_TYPE
*) _mesa_zbuffer_address(ctx
, x0
, y0
);
232 if (depthBits
<= 16) {
233 z0
= FloatToFixed(vert0
->win
[2]) + FIXED_HALF
;
234 z1
= FloatToFixed(vert1
->win
[2]) + FIXED_HALF
;
237 z0
= (int) vert0
->win
[2];
238 z1
= (int) vert1
->win
[2];
242 pixelPtr
= (PIXEL_TYPE
*) PIXEL_ADDRESS(x0
,y0
);
246 dx
= -dx
; /* make positive */
250 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
251 zPtrXstep
= -((GLint
)sizeof(DEPTH_TYPE
));
254 pixelXstep
= -((GLint
)sizeof(PIXEL_TYPE
));
261 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
262 zPtrXstep
= ((GLint
)sizeof(DEPTH_TYPE
));
265 pixelXstep
= ((GLint
)sizeof(PIXEL_TYPE
));
270 dy
= -dy
; /* make positive */
274 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
275 zPtrYstep
= -((GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
)));
278 pixelYstep
= BYTES_PER_ROW
;
285 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
286 zPtrYstep
= (GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
));
289 pixelYstep
= -(BYTES_PER_ROW
);
298 /*** X-major line ***/
300 GLint errorInc
= dy
+dy
;
301 GLint error
= errorInc
-dx
;
302 GLint errorDec
= error
-dx
;
313 dr
/= dx
; /* convert from whole line delta to per-pixel delta */
318 dsr
/= dx
; /* convert from whole line delta to per-pixel delta */
330 const GLfloat invDx
= 1.0F
/ (GLfloat
) dx
;
337 #ifdef INTERP_MULTITEX
339 const GLfloat invDx
= 1.0F
/ (GLfloat
) dx
;
341 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
342 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
354 GLdepth Z
= FixedToDepth(z0
);
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];
368 #ifdef INTERP_MULTITEX
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];
390 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
419 #ifdef INTERP_MULTITEX
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];
434 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
444 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
445 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
448 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
454 /*** Y-major line ***/
456 GLint errorInc
= dx
+dx
;
457 GLint error
= errorInc
-dy
;
458 GLint errorDec
= error
-dy
;
466 dr
/= dy
; /* convert from whole line delta to per-pixel delta */
471 dsr
/= dy
; /* convert from whole line delta to per-pixel delta */
483 const GLfloat invDy
= 1.0F
/ (GLfloat
) dy
;
490 #ifdef INTERP_MULTITEX
492 const GLfloat invDy
= 1.0F
/ (GLfloat
) dy
;
494 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
495 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
507 GLdepth Z
= FixedToDepth(z0
);
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];
521 #ifdef INTERP_MULTITEX
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];
543 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
572 #ifdef INTERP_MULTITEX
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];
586 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
596 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
597 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
600 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
616 #undef INTERP_MULTITEX