1 /* $Id: s_linetemp.h,v 1.5 2001/02/07 18:36:52 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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 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
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.
51 * Similarly, for direct depth buffer access, this type is used for depth
53 * DEPTH_TYPE - either GLushort or GLuint
55 * Optionally, one may provide one-time setup code
56 * SETUP_CODE - code which is to be executed once per line
58 * To enable line stippling define STIPPLE = 1
59 * To enable wide lines define WIDE = 1
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:
66 * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
68 * put_pixel( X, Y, color );
71 * This code was designed for the origin to be in the lower-left corner.
76 /*void line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )*/
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];
88 const GLint depthBits
= ctx
->Visual
.depthBits
;
89 const GLint fixedToDepthShift
= depthBits
<= 16 ? FIXED_SHIFT
: 0;
90 # define FixedToDepth(F) ((F) >> fixedToDepthShift)
92 GLint zPtrXstep
, zPtrYstep
;
95 GLfixed fog0
= FloatToFixed(vert0
->fog
);
96 GLfixed dfog
= FloatToFixed(vert1
->fog
) - fog0
;
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
;
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
;
115 GLfixed a0
= IntToFixed(vert0
->color
[3]);
116 GLfixed da
= IntToFixed(vert1
->color
[3]) - a0
;
119 GLint i0
= vert0
->index
<< 8;
120 GLint di
= (GLint
) (vert1
->index
<< 8) - i0
;
123 const GLfloat invw0
= vert0
->win
[3];
124 const GLfloat invw1
= vert1
->win
[3];
127 GLfloat fragTexcoord
[4];
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];
137 PIXEL_TYPE
*pixelPtr
;
138 GLint pixelXstep
, pixelYstep
;
141 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
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;
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];
162 #ifdef INTERP_MULTITEX
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];
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
190 GLint w
= ctx
->DrawBuffer
->Width
;
191 GLint h
= ctx
->DrawBuffer
->Height
;
192 if ((x0
==w
) | (x1
==w
)) {
193 if ((x0
==w
) & (x1
==w
))
198 if ((y0
==h
) | (y1
==h
)) {
199 if ((y0
==h
) & (y1
==h
))
208 if (dx
==0 && dy
==0) {
221 zPtr
= (DEPTH_TYPE
*) _mesa_zbuffer_address(ctx
, x0
, y0
);
223 if (depthBits
<= 16) {
224 z0
= FloatToFixed(vert0
->win
[2]);
225 z1
= FloatToFixed(vert1
->win
[2]);
228 z0
= (int) vert0
->win
[2];
229 z1
= (int) vert1
->win
[2];
233 pixelPtr
= (PIXEL_TYPE
*) PIXEL_ADDRESS(x0
,y0
);
237 dx
= -dx
; /* make positive */
241 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
242 zPtrXstep
= -((GLint
)sizeof(DEPTH_TYPE
));
245 pixelXstep
= -((GLint
)sizeof(PIXEL_TYPE
));
252 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
253 zPtrXstep
= ((GLint
)sizeof(DEPTH_TYPE
));
256 pixelXstep
= ((GLint
)sizeof(PIXEL_TYPE
));
261 dy
= -dy
; /* make positive */
265 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
266 zPtrYstep
= -ctx
->DrawBuffer
->Width
* ((GLint
)sizeof(DEPTH_TYPE
));
269 pixelYstep
= BYTES_PER_ROW
;
276 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
277 zPtrYstep
= ctx
->DrawBuffer
->Width
* ((GLint
)sizeof(DEPTH_TYPE
));
280 pixelYstep
= -(BYTES_PER_ROW
);
289 /*** X-major line ***/
291 GLint errorInc
= dy
+dy
;
292 GLint error
= errorInc
-dx
;
293 GLint errorDec
= error
-dx
;
299 dr
/= dx
; /* convert from whole line delta to per-pixel delta */
304 dsr
/= dx
; /* convert from whole line delta to per-pixel delta */
316 const GLfloat invDx
= 1.0F
/ (GLfloat
) dx
;
323 #ifdef INTERP_MULTITEX
325 const GLfloat invDx
= 1.0F
/ (GLfloat
) dx
;
327 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
328 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
341 m
= 1 << ((swrast
->StippleCounter
/ctx
->Line
.StippleFactor
) & 0xf);
342 if (ctx
->Line
.StipplePattern
& m
) {
345 GLdepth Z
= FixedToDepth(z0
);
352 const GLfloat invQ
= tex
[3] ? (1.0F
/ tex
[3]) : 1.0F
;
353 fragTexcoord
[0] = tex
[0] * invQ
;
354 fragTexcoord
[1] = tex
[1] * invQ
;
355 fragTexcoord
[2] = tex
[2] * invQ
;
356 fragTexcoord
[3] = tex
[3];
359 #ifdef INTERP_MULTITEX
362 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
363 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
364 const GLfloat invQ
= 1.0F
/ tex
[u
][3];
365 fragTexcoord
[u
][0] = tex
[u
][0] * invQ
;
366 fragTexcoord
[u
][1] = tex
[u
][1] * invQ
;
367 fragTexcoord
[u
][2] = tex
[u
][2] * invQ
;
368 fragTexcoord
[u
][3] = tex
[u
][3];
376 GLint ymin
= y0
+ min
;
377 GLint ymax
= y0
+ max
;
378 for (yy
=ymin
;yy
<=ymax
;yy
++) {
384 XMAJOR_PLOT( x0
, y0
);
391 swrast
->StippleCounter
++;
398 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
425 #ifdef INTERP_MULTITEX
428 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
429 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
430 tex
[u
][0] += dtex
[u
][0];
431 tex
[u
][1] += dtex
[u
][1];
432 tex
[u
][2] += dtex
[u
][2];
433 tex
[u
][3] += dtex
[u
][3];
440 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
450 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
451 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
454 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
460 /*** Y-major line ***/
462 GLint errorInc
= dx
+dx
;
463 GLint error
= errorInc
-dy
;
464 GLint errorDec
= error
-dy
;
470 dr
/= dy
; /* convert from whole line delta to per-pixel delta */
475 dsr
/= dy
; /* convert from whole line delta to per-pixel delta */
487 const GLfloat invDy
= 1.0F
/ (GLfloat
) dy
;
494 #ifdef INTERP_MULTITEX
496 const GLfloat invDy
= 1.0F
/ (GLfloat
) dy
;
498 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
499 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
512 m
= 1 << ((swrast
->StippleCounter
/ctx
->Line
.StippleFactor
) & 0xf);
513 if (ctx
->Line
.StipplePattern
& m
) {
516 GLdepth Z
= FixedToDepth(z0
);
523 const GLfloat invQ
= tex
[3] ? (1.0F
/ tex
[3]) : 1.0F
;
524 fragTexcoord
[0] = tex
[0] * invQ
;
525 fragTexcoord
[1] = tex
[1] * invQ
;
526 fragTexcoord
[2] = tex
[2] * invQ
;
527 fragTexcoord
[3] = tex
[3];
530 #ifdef INTERP_MULTITEX
533 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
534 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
535 const GLfloat invQ
= 1.0F
/ tex
[u
][3];
536 fragTexcoord
[u
][0] = tex
[u
][0] * invQ
;
537 fragTexcoord
[u
][1] = tex
[u
][1] * invQ
;
538 fragTexcoord
[u
][2] = tex
[u
][2] * invQ
;
539 fragTexcoord
[u
][3] = tex
[u
][3];
547 GLint xmin
= x0
+ min
;
548 GLint xmax
= x0
+ max
;
549 for (xx
=xmin
;xx
<=xmax
;xx
++) {
555 YMAJOR_PLOT( x0
, y0
);
562 swrast
->StippleCounter
++;
569 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
596 #ifdef INTERP_MULTITEX
599 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
600 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
601 tex
[u
][0] += dtex
[u
][0];
602 tex
[u
][1] += dtex
[u
][1];
603 tex
[u
][2] += dtex
[u
][2];
604 tex
[u
][3] += dtex
[u
][3];
610 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
620 #if defined(INTERP_Z) && defined(DEPTH_TYPE)
621 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
624 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
639 #undef INTERP_MULTITEX