Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
||
5 | * |
||
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: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
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. |
||
23 | */ |
||
24 | |||
25 | |||
26 | /* |
||
27 | * Line Rasterizer Template |
||
28 | * |
||
29 | * This file is #include'd to generate custom line rasterizers. |
||
30 | * |
||
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) |
||
35 | * |
||
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. |
||
43 | * |
||
44 | * Similarly, for direct depth buffer access, this type is used for depth |
||
45 | * buffer addressing: |
||
46 | * DEPTH_TYPE - either GLushort or GLuint |
||
47 | * |
||
48 | * Optionally, one may provide one-time setup code |
||
49 | * SETUP_CODE - code which is to be executed once per line |
||
50 | * |
||
51 | * To actually "plot" each pixel the PLOT macro must be defined... |
||
52 | * PLOT(X,Y) - code to plot a pixel. Example: |
||
53 | * if (Z < *zPtr) { |
||
54 | * *zPtr = Z; |
||
55 | * color = pack_rgb( FixedToInt(r0), FixedToInt(g0), |
||
56 | * FixedToInt(b0) ); |
||
57 | * put_pixel( X, Y, color ); |
||
58 | * } |
||
59 | * |
||
60 | * This code was designed for the origin to be in the lower-left corner. |
||
61 | * |
||
62 | */ |
||
63 | |||
64 | |||
65 | static void |
||
66 | NAME( struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1 ) |
||
67 | { |
||
68 | const SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
69 | SWspan span; |
||
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]; |
||
75 | GLint dx, dy; |
||
76 | GLint numPixels; |
||
77 | GLint xstep, ystep; |
||
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; |
||
84 | DEPTH_TYPE *zPtr; |
||
85 | #elif defined(INTERP_Z) |
||
86 | const GLint depthBits = ctx->DrawBuffer->Visual.depthBits; |
||
87 | #endif |
||
88 | #ifdef PIXEL_ADDRESS |
||
89 | PIXEL_TYPE *pixelPtr; |
||
90 | GLint pixelXstep, pixelYstep; |
||
91 | #endif |
||
92 | |||
93 | #ifdef SETUP_CODE |
||
94 | SETUP_CODE |
||
95 | #endif |
||
96 | |||
97 | (void) swrast; |
||
98 | |||
99 | /* Cull primitives with malformed coordinates. |
||
100 | */ |
||
101 | { |
||
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)) |
||
105 | return; |
||
106 | } |
||
107 | |||
108 | /* |
||
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]); |
||
123 | */ |
||
124 | |||
125 | /* |
||
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 |
||
130 | * necessary. |
||
131 | */ |
||
132 | #ifdef CLIP_HACK |
||
133 | { |
||
134 | GLint w = ctx->DrawBuffer->Width; |
||
135 | GLint h = ctx->DrawBuffer->Height; |
||
136 | if ((x0==w) | (x1==w)) { |
||
137 | if ((x0==w) & (x1==w)) |
||
138 | return; |
||
139 | x0 -= x0==w; |
||
140 | x1 -= x1==w; |
||
141 | } |
||
142 | if ((y0==h) | (y1==h)) { |
||
143 | if ((y0==h) & (y1==h)) |
||
144 | return; |
||
145 | y0 -= y0==h; |
||
146 | y1 -= y1==h; |
||
147 | } |
||
148 | } |
||
149 | #endif |
||
150 | |||
151 | dx = x1 - x0; |
||
152 | dy = y1 - y0; |
||
153 | if (dx == 0 && dy == 0) |
||
154 | return; |
||
155 | |||
156 | /* |
||
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]); |
||
166 | */ |
||
167 | |||
168 | #ifdef DEPTH_TYPE |
||
169 | zPtr = (DEPTH_TYPE *) _swrast_pixel_address(zrb, x0, y0); |
||
170 | #endif |
||
171 | #ifdef PIXEL_ADDRESS |
||
172 | pixelPtr = (PIXEL_TYPE *) PIXEL_ADDRESS(x0,y0); |
||
173 | #endif |
||
174 | |||
175 | if (dx<0) { |
||
176 | dx = -dx; /* make positive */ |
||
177 | xstep = -1; |
||
178 | #ifdef DEPTH_TYPE |
||
179 | zPtrXstep = -((GLint)sizeof(DEPTH_TYPE)); |
||
180 | #endif |
||
181 | #ifdef PIXEL_ADDRESS |
||
182 | pixelXstep = -((GLint)sizeof(PIXEL_TYPE)); |
||
183 | #endif |
||
184 | } |
||
185 | else { |
||
186 | xstep = 1; |
||
187 | #ifdef DEPTH_TYPE |
||
188 | zPtrXstep = ((GLint)sizeof(DEPTH_TYPE)); |
||
189 | #endif |
||
190 | #ifdef PIXEL_ADDRESS |
||
191 | pixelXstep = ((GLint)sizeof(PIXEL_TYPE)); |
||
192 | #endif |
||
193 | } |
||
194 | |||
195 | if (dy<0) { |
||
196 | dy = -dy; /* make positive */ |
||
197 | ystep = -1; |
||
198 | #ifdef DEPTH_TYPE |
||
199 | zPtrYstep = -((GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE))); |
||
200 | #endif |
||
201 | #ifdef PIXEL_ADDRESS |
||
202 | pixelYstep = BYTES_PER_ROW; |
||
203 | #endif |
||
204 | } |
||
205 | else { |
||
206 | ystep = 1; |
||
207 | #ifdef DEPTH_TYPE |
||
208 | zPtrYstep = (GLint) (ctx->DrawBuffer->Width * sizeof(DEPTH_TYPE)); |
||
209 | #endif |
||
210 | #ifdef PIXEL_ADDRESS |
||
211 | pixelYstep = -(BYTES_PER_ROW); |
||
212 | #endif |
||
213 | } |
||
214 | |||
215 | assert(dx >= 0); |
||
216 | assert(dy >= 0); |
||
217 | |||
218 | numPixels = MAX2(dx, dy); |
||
219 | |||
220 | /* |
||
221 | * Span setup: compute start and step values for all interpolated values. |
||
222 | */ |
||
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; |
||
233 | } |
||
234 | else { |
||
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]); |
||
239 | span.redStep = 0; |
||
240 | span.greenStep = 0; |
||
241 | span.blueStep = 0; |
||
242 | span.alphaStep = 0; |
||
243 | } |
||
244 | #if defined(INTERP_Z) || defined(DEPTH_TYPE) |
||
245 | interpFlags |= SPAN_Z; |
||
246 | { |
||
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; |
||
251 | } |
||
252 | else { |
||
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); |
||
257 | } |
||
258 | } |
||
259 | #endif |
||
260 | #if defined(INTERP_ATTRIBS) |
||
261 | { |
||
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]; |
||
265 | |||
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; |
||
269 | |||
270 | ATTRIB_LOOP_BEGIN |
||
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); |
||
274 | } |
||
275 | else { |
||
276 | GLuint c; |
||
277 | for (c = 0; c < 4; c++) { |
||
278 | float da; |
||
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; |
||
282 | } |
||
283 | } |
||
284 | ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0); |
||
285 | ATTRIB_LOOP_END |
||
286 | } |
||
287 | #endif |
||
288 | |||
289 | INIT_SPAN(span, GL_LINE); |
||
290 | span.end = numPixels; |
||
291 | span.interpMask = interpFlags; |
||
292 | span.arrayMask = SPAN_XY; |
||
293 | |||
294 | span.facing = swrast->PointLineFacing; |
||
295 | |||
296 | |||
297 | /* |
||
298 | * Draw |
||
299 | */ |
||
300 | |||
301 | if (dx > dy) { |
||
302 | /*** X-major line ***/ |
||
303 | GLint i; |
||
304 | GLint errorInc = dy+dy; |
||
305 | GLint error = errorInc-dx; |
||
306 | GLint errorDec = error-dx; |
||
307 | |||
308 | for (i = 0; i < dx; i++) { |
||
309 | #ifdef DEPTH_TYPE |
||
310 | GLuint Z = FixedToDepth(span.z); |
||
311 | #endif |
||
312 | #ifdef PLOT |
||
313 | PLOT( x0, y0 ); |
||
314 | #else |
||
315 | span.array->x[i] = x0; |
||
316 | span.array->y[i] = y0; |
||
317 | #endif |
||
318 | x0 += xstep; |
||
319 | #ifdef DEPTH_TYPE |
||
320 | zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); |
||
321 | span.z += span.zStep; |
||
322 | #endif |
||
323 | #ifdef PIXEL_ADDRESS |
||
324 | pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); |
||
325 | #endif |
||
326 | if (error < 0) { |
||
327 | error += errorInc; |
||
328 | } |
||
329 | else { |
||
330 | error += errorDec; |
||
331 | y0 += ystep; |
||
332 | #ifdef DEPTH_TYPE |
||
333 | zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); |
||
334 | #endif |
||
335 | #ifdef PIXEL_ADDRESS |
||
336 | pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); |
||
337 | #endif |
||
338 | } |
||
339 | } |
||
340 | } |
||
341 | else { |
||
342 | /*** Y-major line ***/ |
||
343 | GLint i; |
||
344 | GLint errorInc = dx+dx; |
||
345 | GLint error = errorInc-dy; |
||
346 | GLint errorDec = error-dy; |
||
347 | |||
348 | for (i=0;i |
||
349 | #ifdef DEPTH_TYPE |
||
350 | GLuint Z = FixedToDepth(span.z); |
||
351 | #endif |
||
352 | #ifdef PLOT |
||
353 | PLOT( x0, y0 ); |
||
354 | #else |
||
355 | span.array->x[i] = x0; |
||
356 | span.array->y[i] = y0; |
||
357 | #endif |
||
358 | y0 += ystep; |
||
359 | #ifdef DEPTH_TYPE |
||
360 | zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrYstep); |
||
361 | span.z += span.zStep; |
||
362 | #endif |
||
363 | #ifdef PIXEL_ADDRESS |
||
364 | pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelYstep); |
||
365 | #endif |
||
366 | if (error<0) { |
||
367 | error += errorInc; |
||
368 | } |
||
369 | else { |
||
370 | error += errorDec; |
||
371 | x0 += xstep; |
||
372 | #ifdef DEPTH_TYPE |
||
373 | zPtr = (DEPTH_TYPE *) ((GLubyte*) zPtr + zPtrXstep); |
||
374 | #endif |
||
375 | #ifdef PIXEL_ADDRESS |
||
376 | pixelPtr = (PIXEL_TYPE*) ((GLubyte*) pixelPtr + pixelXstep); |
||
377 | #endif |
||
378 | } |
||
379 | } |
||
380 | } |
||
381 | |||
382 | #ifdef RENDER_SPAN |
||
383 | RENDER_SPAN( span ); |
||
384 | #endif |
||
385 | |||
386 | (void)span; |
||
387 | |||
388 | } |
||
389 | |||
390 | |||
391 | #undef NAME |
||
392 | #undef INTERP_Z |
||
393 | #undef INTERP_ATTRIBS |
||
394 | #undef PIXEL_ADDRESS |
||
395 | #undef PIXEL_TYPE |
||
396 | #undef DEPTH_TYPE |
||
397 | #undef BYTES_PER_ROW |
||
398 | #undef SETUP_CODE |
||
399 | #undef PLOT |
||
400 | #undef CLIP_HACK |
||
401 | #undef FixedToDepth |
||
402 | #undef RENDER_SPAN0)>>>>=>0)>0)>=>> |