2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
27 * Line Rasterizer Template
29 * This file is #include'd to generate custom line rasterizers.
31 * The following macros may be defined to indicate what auxillary information
32 * must be interplated along the line:
33 * INTERP_Z - if defined, interpolate Z values
34 * INTERP_ATTRIBS - if defined, interpolate attribs (texcoords, varying, etc)
36 * When one can directly address pixels in the color buffer the following
37 * macros can be defined and used to directly compute pixel addresses during
38 * rasterization (see pixelPtr):
39 * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
40 * BYTES_PER_ROW - number of bytes per row in the color buffer
41 * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
42 * Y==0 at bottom of screen and increases upward.
44 * Similarly, for direct depth buffer access, this type is used for depth
46 * DEPTH_TYPE - either GLushort or GLuint
48 * Optionally, one may provide one-time setup code
49 * SETUP_CODE - code which is to be executed once per line
51 * To actually "plot" each pixel the PLOT macro must be defined...
52 * PLOT(X,Y) - code to plot a pixel. Example:
55 * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
57 * put_pixel( X, Y, color );
60 * This code was designed for the origin to be in the lower-left corner.
66 NAME( struct gl_context
*ctx
, const SWvertex
*vert0
, const SWvertex
*vert1
)
68 const SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
70 GLuint interpFlags
= 0;
71 GLint x0
= (GLint
) vert0
->attrib
[VARYING_SLOT_POS
][0];
72 GLint x1
= (GLint
) vert1
->attrib
[VARYING_SLOT_POS
][0];
73 GLint y0
= (GLint
) vert0
->attrib
[VARYING_SLOT_POS
][1];
74 GLint y1
= (GLint
) vert1
->attrib
[VARYING_SLOT_POS
][1];
78 #if defined(DEPTH_TYPE)
79 const GLint depthBits
= ctx
->DrawBuffer
->Visual
.depthBits
;
80 const GLint fixedToDepthShift
= depthBits
<= 16 ? FIXED_SHIFT
: 0;
81 struct gl_renderbuffer
*zrb
= ctx
->DrawBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
82 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
83 GLint zPtrXstep
, zPtrYstep
;
85 #elif defined(INTERP_Z)
86 const GLint depthBits
= ctx
->DrawBuffer
->Visual
.depthBits
;
90 GLint pixelXstep
, pixelYstep
;
99 /* Cull primitives with malformed coordinates.
102 GLfloat tmp
= vert0
->attrib
[VARYING_SLOT_POS
][0] + vert0
->attrib
[VARYING_SLOT_POS
][1]
103 + vert1
->attrib
[VARYING_SLOT_POS
][0] + vert1
->attrib
[VARYING_SLOT_POS
][1];
104 if (IS_INF_OR_NAN(tmp
))
109 printf("%s():\n", __func__);
110 printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
111 vert0->attrib[VARYING_SLOT_POS][0],
112 vert0->attrib[VARYING_SLOT_POS][1],
113 vert0->attrib[VARYING_SLOT_POS][2],
114 vert1->attrib[VARYING_SLOT_POS][0],
115 vert1->attrib[VARYING_SLOT_POS][1],
116 vert1->attrib[VARYING_SLOT_POS][2]);
117 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
118 vert0->color[0], vert0->color[1], vert0->color[2],
119 vert1->color[0], vert1->color[1], vert1->color[2]);
120 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
121 vert0->specular[0], vert0->specular[1], vert0->specular[2],
122 vert1->specular[0], vert1->specular[1], vert1->specular[2]);
126 * Despite being clipped to the view volume, the line's window coordinates
127 * may just lie outside the window bounds. That is, if the legal window
128 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
129 * This quick and dirty code nudges the endpoints inside the window if
134 GLint w
= ctx
->DrawBuffer
->Width
;
135 GLint h
= ctx
->DrawBuffer
->Height
;
136 if ((x0
==w
) | (x1
==w
)) {
137 if ((x0
==w
) & (x1
==w
))
142 if ((y0
==h
) | (y1
==h
)) {
143 if ((y0
==h
) & (y1
==h
))
153 if (dx
== 0 && dy
== 0)
157 printf("%s %d,%d %g %g %g %g %g %g %g %g\n", __func__, dx, dy,
158 vert0->attrib[VARYING_SLOT_COL1][0],
159 vert0->attrib[VARYING_SLOT_COL1][1],
160 vert0->attrib[VARYING_SLOT_COL1][2],
161 vert0->attrib[VARYING_SLOT_COL1][3],
162 vert1->attrib[VARYING_SLOT_COL1][0],
163 vert1->attrib[VARYING_SLOT_COL1][1],
164 vert1->attrib[VARYING_SLOT_COL1][2],
165 vert1->attrib[VARYING_SLOT_COL1][3]);
169 zPtr
= (DEPTH_TYPE
*) _swrast_pixel_address(zrb
, x0
, y0
);
172 pixelPtr
= (PIXEL_TYPE
*) PIXEL_ADDRESS(x0
,y0
);
176 dx
= -dx
; /* make positive */
179 zPtrXstep
= -((GLint
)sizeof(DEPTH_TYPE
));
182 pixelXstep
= -((GLint
)sizeof(PIXEL_TYPE
));
188 zPtrXstep
= ((GLint
)sizeof(DEPTH_TYPE
));
191 pixelXstep
= ((GLint
)sizeof(PIXEL_TYPE
));
196 dy
= -dy
; /* make positive */
199 zPtrYstep
= -((GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
)));
202 pixelYstep
= BYTES_PER_ROW
;
208 zPtrYstep
= (GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
));
211 pixelYstep
= -(BYTES_PER_ROW
);
218 numPixels
= MAX2(dx
, dy
);
221 * Span setup: compute start and step values for all interpolated values.
223 interpFlags
|= SPAN_RGBA
;
224 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
225 span
.red
= ChanToFixed(vert0
->color
[0]);
226 span
.green
= ChanToFixed(vert0
->color
[1]);
227 span
.blue
= ChanToFixed(vert0
->color
[2]);
228 span
.alpha
= ChanToFixed(vert0
->color
[3]);
229 span
.redStep
= (ChanToFixed(vert1
->color
[0]) - span
.red
) / numPixels
;
230 span
.greenStep
= (ChanToFixed(vert1
->color
[1]) - span
.green
) / numPixels
;
231 span
.blueStep
= (ChanToFixed(vert1
->color
[2]) - span
.blue
) / numPixels
;
232 span
.alphaStep
= (ChanToFixed(vert1
->color
[3]) - span
.alpha
) / numPixels
;
235 span
.red
= ChanToFixed(vert1
->color
[0]);
236 span
.green
= ChanToFixed(vert1
->color
[1]);
237 span
.blue
= ChanToFixed(vert1
->color
[2]);
238 span
.alpha
= ChanToFixed(vert1
->color
[3]);
244 #if defined(INTERP_Z) || defined(DEPTH_TYPE)
245 interpFlags
|= SPAN_Z
;
247 if (depthBits
<= 16) {
248 span
.z
= FloatToFixed(vert0
->attrib
[VARYING_SLOT_POS
][2]) + FIXED_HALF
;
249 span
.zStep
= FloatToFixed( vert1
->attrib
[VARYING_SLOT_POS
][2]
250 - vert0
->attrib
[VARYING_SLOT_POS
][2]) / numPixels
;
253 /* don't use fixed point */
254 span
.z
= (GLuint
) vert0
->attrib
[VARYING_SLOT_POS
][2];
255 span
.zStep
= (GLint
) (( vert1
->attrib
[VARYING_SLOT_POS
][2]
256 - vert0
->attrib
[VARYING_SLOT_POS
][2]) / numPixels
);
260 #if defined(INTERP_ATTRIBS)
262 const GLfloat invLen
= 1.0F
/ numPixels
;
263 const GLfloat invw0
= vert0
->attrib
[VARYING_SLOT_POS
][3];
264 const GLfloat invw1
= vert1
->attrib
[VARYING_SLOT_POS
][3];
266 span
.attrStart
[VARYING_SLOT_POS
][3] = invw0
;
267 span
.attrStepX
[VARYING_SLOT_POS
][3] = (invw1
- invw0
) * invLen
;
268 span
.attrStepY
[VARYING_SLOT_POS
][3] = 0.0;
271 if (swrast
->_InterpMode
[attr
] == GL_FLAT
) {
272 COPY_4V(span
.attrStart
[attr
], vert1
->attrib
[attr
]);
273 ASSIGN_4V(span
.attrStepX
[attr
], 0.0, 0.0, 0.0, 0.0);
277 for (c
= 0; c
< 4; c
++) {
279 span
.attrStart
[attr
][c
] = invw0
* vert0
->attrib
[attr
][c
];
280 da
= (invw1
* vert1
->attrib
[attr
][c
]) - span
.attrStart
[attr
][c
];
281 span
.attrStepX
[attr
][c
] = da
* invLen
;
284 ASSIGN_4V(span
.attrStepY
[attr
], 0.0, 0.0, 0.0, 0.0);
289 INIT_SPAN(span
, GL_LINE
);
290 span
.end
= numPixels
;
291 span
.interpMask
= interpFlags
;
292 span
.arrayMask
= SPAN_XY
;
294 span
.facing
= swrast
->PointLineFacing
;
302 /*** X-major line ***/
304 GLint errorInc
= dy
+dy
;
305 GLint error
= errorInc
-dx
;
306 GLint errorDec
= error
-dx
;
308 for (i
= 0; i
< dx
; i
++) {
310 GLuint Z
= FixedToDepth(span
.z
);
315 span
.array
->x
[i
] = x0
;
316 span
.array
->y
[i
] = y0
;
320 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
321 span
.z
+= span
.zStep
;
324 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
333 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
336 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
342 /*** Y-major line ***/
344 GLint errorInc
= dx
+dx
;
345 GLint error
= errorInc
-dy
;
346 GLint errorDec
= error
-dy
;
350 GLuint Z
= FixedToDepth(span
.z
);
355 span
.array
->x
[i
] = x0
;
356 span
.array
->y
[i
] = y0
;
360 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
361 span
.z
+= span
.zStep
;
364 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
373 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
376 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
393 #undef INTERP_ATTRIBS