2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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_FOG - if defined, interpolate FOG values
35 * INTERP_RGBA - if defined, interpolate RGBA values
36 * INTERP_SPEC - if defined, interpolate specular RGB values
37 * INTERP_INDEX - if defined, interpolate color index values
38 * INTERP_TEX - if defined, interpolate unit 0 texcoords
39 * INTERP_MULTITEX - if defined, interpolate multi-texcoords
40 * INTERP_VARYING - if defined, interpolate GLSL varyings
42 * When one can directly address pixels in the color buffer the following
43 * macros can be defined and used to directly compute pixel addresses during
44 * rasterization (see pixelPtr):
45 * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
46 * BYTES_PER_ROW - number of bytes per row in the color buffer
47 * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
48 * Y==0 at bottom of screen and increases upward.
50 * Similarly, for direct depth buffer access, this type is used for depth
52 * DEPTH_TYPE - either GLushort or GLuint
54 * Optionally, one may provide one-time setup code
55 * SETUP_CODE - code which is to be executed once per line
57 * To actually "plot" each pixel the PLOT macro must be defined...
58 * PLOT(X,Y) - code to plot a pixel. Example:
61 * color = pack_rgb( FixedToInt(r0), FixedToInt(g0),
63 * put_pixel( X, Y, color );
66 * This code was designed for the origin to be in the lower-left corner.
72 NAME( GLcontext
*ctx
, const SWvertex
*vert0
, const SWvertex
*vert1
)
75 GLuint interpFlags
= 0;
76 GLint x0
= (GLint
) vert0
->win
[0];
77 GLint x1
= (GLint
) vert1
->win
[0];
78 GLint y0
= (GLint
) vert0
->win
[1];
79 GLint y1
= (GLint
) vert1
->win
[1];
83 #if defined(DEPTH_TYPE)
84 const GLint depthBits
= ctx
->Visual
.depthBits
;
85 const GLint fixedToDepthShift
= depthBits
<= 16 ? FIXED_SHIFT
: 0;
86 struct gl_renderbuffer
*zrb
= ctx
->DrawBuffer
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
87 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
88 GLint zPtrXstep
, zPtrYstep
;
90 #elif defined(INTERP_Z)
91 const GLint depthBits
= ctx
->Visual
.depthBits
;
95 GLint pixelXstep
, pixelYstep
;
102 /* Cull primitives with malformed coordinates.
105 GLfloat tmp
= vert0
->win
[0] + vert0
->win
[1]
106 + vert1
->win
[0] + vert1
->win
[1];
107 if (IS_INF_OR_NAN(tmp
))
112 printf("%s():\n", __FUNCTION__);
113 printf(" (%f, %f, %f) -> (%f, %f, %f)\n",
114 vert0->win[0], vert0->win[1], vert0->win[2],
115 vert1->win[0], vert1->win[1], vert1->win[2]);
116 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
117 vert0->color[0], vert0->color[1], vert0->color[2],
118 vert1->color[0], vert1->color[1], vert1->color[2]);
119 printf(" (%d, %d, %d) -> (%d, %d, %d)\n",
120 vert0->specular[0], vert0->specular[1], vert0->specular[2],
121 vert1->specular[0], vert1->specular[1], vert1->specular[2]);
125 * Despite being clipped to the view volume, the line's window coordinates
126 * may just lie outside the window bounds. That is, if the legal window
127 * coordinates are [0,W-1][0,H-1], it's possible for x==W and/or y==H.
128 * This quick and dirty code nudges the endpoints inside the window if
133 GLint w
= ctx
->DrawBuffer
->Width
;
134 GLint h
= ctx
->DrawBuffer
->Height
;
135 if ((x0
==w
) | (x1
==w
)) {
136 if ((x0
==w
) & (x1
==w
))
141 if ((y0
==h
) | (y1
==h
)) {
142 if ((y0
==h
) & (y1
==h
))
152 if (dx
== 0 && dy
== 0)
156 zPtr
= (DEPTH_TYPE
*) zrb
->GetPointer(ctx
, zrb
, x0
, y0
);
159 pixelPtr
= (PIXEL_TYPE
*) PIXEL_ADDRESS(x0
,y0
);
163 dx
= -dx
; /* make positive */
166 zPtrXstep
= -((GLint
)sizeof(DEPTH_TYPE
));
169 pixelXstep
= -((GLint
)sizeof(PIXEL_TYPE
));
175 zPtrXstep
= ((GLint
)sizeof(DEPTH_TYPE
));
178 pixelXstep
= ((GLint
)sizeof(PIXEL_TYPE
));
183 dy
= -dy
; /* make positive */
186 zPtrYstep
= -((GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
)));
189 pixelYstep
= BYTES_PER_ROW
;
195 zPtrYstep
= (GLint
) (ctx
->DrawBuffer
->Width
* sizeof(DEPTH_TYPE
));
198 pixelYstep
= -(BYTES_PER_ROW
);
205 numPixels
= MAX2(dx
, dy
);
208 * Span setup: compute start and step values for all interpolated values.
211 interpFlags
|= SPAN_RGBA
;
212 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
213 span
.red
= ChanToFixed(vert0
->color
[0]);
214 span
.green
= ChanToFixed(vert0
->color
[1]);
215 span
.blue
= ChanToFixed(vert0
->color
[2]);
216 span
.alpha
= ChanToFixed(vert0
->color
[3]);
217 span
.redStep
= (ChanToFixed(vert1
->color
[0]) - span
.red
) / numPixels
;
218 span
.greenStep
= (ChanToFixed(vert1
->color
[1]) - span
.green
) / numPixels
;
219 span
.blueStep
= (ChanToFixed(vert1
->color
[2]) - span
.blue
) / numPixels
;
220 span
.alphaStep
= (ChanToFixed(vert1
->color
[3]) - span
.alpha
) / numPixels
;
223 span
.red
= ChanToFixed(vert1
->color
[0]);
224 span
.green
= ChanToFixed(vert1
->color
[1]);
225 span
.blue
= ChanToFixed(vert1
->color
[2]);
226 span
.alpha
= ChanToFixed(vert1
->color
[3]);
234 interpFlags
|= SPAN_SPEC
;
235 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
236 span
.specRed
= ChanToFixed(vert0
->specular
[0]);
237 span
.specGreen
= ChanToFixed(vert0
->specular
[1]);
238 span
.specBlue
= ChanToFixed(vert0
->specular
[2]);
239 span
.specRedStep
= (ChanToFixed(vert1
->specular
[0]) - span
.specRed
) / numPixels
;
240 span
.specGreenStep
= (ChanToFixed(vert1
->specular
[1]) - span
.specBlue
) / numPixels
;
241 span
.specBlueStep
= (ChanToFixed(vert1
->specular
[2]) - span
.specGreen
) / numPixels
;
244 span
.specRed
= ChanToFixed(vert1
->specular
[0]);
245 span
.specGreen
= ChanToFixed(vert1
->specular
[1]);
246 span
.specBlue
= ChanToFixed(vert1
->specular
[2]);
247 span
.specRedStep
= 0;
248 span
.specGreenStep
= 0;
249 span
.specBlueStep
= 0;
253 interpFlags
|= SPAN_INDEX
;
254 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
255 span
.index
= FloatToFixed(vert0
->index
);
256 span
.indexStep
= FloatToFixed(vert1
->index
- vert0
->index
) / numPixels
;
259 span
.index
= FloatToFixed(vert1
->index
);
263 #if defined(INTERP_Z) || defined(DEPTH_TYPE)
264 interpFlags
|= SPAN_Z
;
266 if (depthBits
<= 16) {
267 span
.z
= FloatToFixed(vert0
->win
[2]) + FIXED_HALF
;
268 span
.zStep
= FloatToFixed(vert1
->win
[2] - vert0
->win
[2]) / numPixels
;
271 /* don't use fixed point */
272 span
.z
= (GLint
) vert0
->win
[2];
273 span
.zStep
= (GLint
) ((vert1
->win
[2] - vert0
->win
[2]) / numPixels
);
278 interpFlags
|= SPAN_FOG
;
279 span
.attrStart
[FRAG_ATTRIB_FOGC
][0] = vert0
->fog
;
280 span
.attrStepX
[FRAG_ATTRIB_FOGC
][0] = (vert1
->fog
- vert0
->fog
) / numPixels
;
283 interpFlags
|= SPAN_TEXTURE
;
285 const GLfloat invw0
= vert0
->win
[3];
286 const GLfloat invw1
= vert1
->win
[3];
287 const GLfloat invLen
= 1.0F
/ numPixels
;
288 GLfloat ds
, dt
, dr
, dq
;
289 span
.attrStart
[FRAG_ATTRIB_TEX0
][0] = invw0
* vert0
->texcoord
[0][0];
290 span
.attrStart
[FRAG_ATTRIB_TEX0
][1] = invw0
* vert0
->texcoord
[0][1];
291 span
.attrStart
[FRAG_ATTRIB_TEX0
][2] = invw0
* vert0
->texcoord
[0][2];
292 span
.attrStart
[FRAG_ATTRIB_TEX0
][3] = invw0
* vert0
->texcoord
[0][3];
293 ds
= (invw1
* vert1
->texcoord
[0][0]) - span
.attrStart
[FRAG_ATTRIB_TEX0
][0];
294 dt
= (invw1
* vert1
->texcoord
[0][1]) - span
.attrStart
[FRAG_ATTRIB_TEX0
][1];
295 dr
= (invw1
* vert1
->texcoord
[0][2]) - span
.attrStart
[FRAG_ATTRIB_TEX0
][2];
296 dq
= (invw1
* vert1
->texcoord
[0][3]) - span
.attrStart
[FRAG_ATTRIB_TEX0
][3];
297 span
.attrStepX
[FRAG_ATTRIB_TEX0
][0] = ds
* invLen
;
298 span
.attrStepX
[FRAG_ATTRIB_TEX0
][1] = dt
* invLen
;
299 span
.attrStepX
[FRAG_ATTRIB_TEX0
][2] = dr
* invLen
;
300 span
.attrStepX
[FRAG_ATTRIB_TEX0
][3] = dq
* invLen
;
301 span
.attrStepY
[FRAG_ATTRIB_TEX0
][0] = 0.0F
;
302 span
.attrStepY
[FRAG_ATTRIB_TEX0
][1] = 0.0F
;
303 span
.attrStepY
[FRAG_ATTRIB_TEX0
][2] = 0.0F
;
304 span
.attrStepY
[FRAG_ATTRIB_TEX0
][3] = 0.0F
;
307 #ifdef INTERP_MULTITEX
308 interpFlags
|= SPAN_TEXTURE
;
310 const GLfloat invLen
= 1.0F
/ numPixels
;
312 for (u
= 0; u
< ctx
->Const
.MaxTextureUnits
; u
++) {
313 if (ctx
->Texture
.Unit
[u
]._ReallyEnabled
) {
314 const GLuint attr
= FRAG_ATTRIB_TEX0
+ u
;
315 const GLfloat invw0
= vert0
->win
[3];
316 const GLfloat invw1
= vert1
->win
[3];
317 GLfloat ds
, dt
, dr
, dq
;
318 span
.attrStart
[attr
][0] = invw0
* vert0
->texcoord
[u
][0];
319 span
.attrStart
[attr
][1] = invw0
* vert0
->texcoord
[u
][1];
320 span
.attrStart
[attr
][2] = invw0
* vert0
->texcoord
[u
][2];
321 span
.attrStart
[attr
][3] = invw0
* vert0
->texcoord
[u
][3];
322 ds
= (invw1
* vert1
->texcoord
[u
][0]) - span
.attrStart
[attr
][0];
323 dt
= (invw1
* vert1
->texcoord
[u
][1]) - span
.attrStart
[attr
][1];
324 dr
= (invw1
* vert1
->texcoord
[u
][2]) - span
.attrStart
[attr
][2];
325 dq
= (invw1
* vert1
->texcoord
[u
][3]) - span
.attrStart
[attr
][3];
326 span
.attrStepX
[attr
][0] = ds
* invLen
;
327 span
.attrStepX
[attr
][1] = dt
* invLen
;
328 span
.attrStepX
[attr
][2] = dr
* invLen
;
329 span
.attrStepX
[attr
][3] = dq
* invLen
;
330 span
.attrStepY
[attr
][0] = 0.0F
;
331 span
.attrStepY
[attr
][1] = 0.0F
;
332 span
.attrStepY
[attr
][2] = 0.0F
;
333 span
.attrStepY
[attr
][3] = 0.0F
;
338 #ifdef INTERP_VARYING
339 interpFlags
|= SPAN_VARYING
;
341 const GLfloat invLen
= 1.0F
/ numPixels
;
342 const GLbitfield inputsUsed
= ctx
->FragmentProgram
._Current
?
343 ctx
->FragmentProgram
._Current
->Base
.InputsRead
: 0x0;
344 const GLfloat invw0
= vert0
->win
[3];
345 const GLfloat invw1
= vert1
->win
[3];
347 for (v
= 0; v
< MAX_VARYING
; v
++) {
348 if (inputsUsed
& FRAG_BIT_VAR(v
)) {
349 GLuint attr
= FRAG_ATTRIB_VAR0
+ v
;
350 GLfloat ds
, dt
, dr
, dq
;
351 span
.attrStart
[attr
][0] = invw0
* vert0
->varying
[v
][0];
352 span
.attrStart
[attr
][1] = invw0
* vert0
->varying
[v
][1];
353 span
.attrStart
[attr
][2] = invw0
* vert0
->varying
[v
][2];
354 span
.attrStart
[attr
][3] = invw0
* vert0
->varying
[v
][3];
355 ds
= (invw1
* vert1
->varying
[v
][0]) - span
.attrStart
[attr
][0];
356 dt
= (invw1
* vert1
->varying
[v
][1]) - span
.attrStart
[attr
][1];
357 dr
= (invw1
* vert1
->varying
[v
][2]) - span
.attrStart
[attr
][2];
358 dq
= (invw1
* vert1
->varying
[v
][3]) - span
.attrStart
[attr
][3];
359 span
.attrStepX
[attr
][0] = ds
* invLen
;
360 span
.attrStepX
[attr
][1] = dt
* invLen
;
361 span
.attrStepX
[attr
][2] = dr
* invLen
;
362 span
.attrStepX
[attr
][3] = dq
* invLen
;
363 span
.attrStepY
[attr
][0] = 0.0F
;
364 span
.attrStepY
[attr
][1] = 0.0F
;
365 span
.attrStepY
[attr
][2] = 0.0F
;
366 span
.attrStepY
[attr
][3] = 0.0F
;
372 INIT_SPAN(span
, GL_LINE
, numPixels
, interpFlags
, SPAN_XY
);
374 /* Need these for fragment prog texcoord interpolation */
375 span
.attrStart
[FRAG_ATTRIB_WPOS
][3] = 1.0F
;
376 span
.attrStepX
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
377 span
.attrStepY
[FRAG_ATTRIB_WPOS
][3] = 0.0F
;
384 /*** X-major line ***/
386 GLint errorInc
= dy
+dy
;
387 GLint error
= errorInc
-dx
;
388 GLint errorDec
= error
-dx
;
390 for (i
= 0; i
< dx
; i
++) {
392 GLuint Z
= FixedToDepth(span
.z
);
397 span
.array
->x
[i
] = x0
;
398 span
.array
->y
[i
] = y0
;
402 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
403 span
.z
+= span
.zStep
;
406 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
415 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
418 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
424 /*** Y-major line ***/
426 GLint errorInc
= dx
+dx
;
427 GLint error
= errorInc
-dy
;
428 GLint errorDec
= error
-dy
;
432 GLuint Z
= FixedToDepth(span
.z
);
437 span
.array
->x
[i
] = x0
;
438 span
.array
->y
[i
] = y0
;
442 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrYstep
);
443 span
.z
+= span
.zStep
;
446 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelYstep
);
455 zPtr
= (DEPTH_TYPE
*) ((GLubyte
*) zPtr
+ zPtrXstep
);
458 pixelPtr
= (PIXEL_TYPE
*) ((GLubyte
*) pixelPtr
+ pixelXstep
);
479 #undef INTERP_MULTITEX