1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2006  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  * This file contains "accelerated" point, line, and triangle functions.
28  * It should be fairly easy to write new special-purpose point, line or
29  * triangle functions and hook them into this module.
30  */
31 
32 
33 #include "glxheader.h"
34 #include "main/macros.h"
35 #include "main/mtypes.h"
36 #include "xmesaP.h"
37 
38 /* Internal swrast includes:
39  */
40 #include "swrast/s_depth.h"
41 #include "swrast/s_points.h"
42 #include "swrast/s_lines.h"
43 #include "swrast/s_context.h"
44 
45 
46 /**********************************************************************/
47 /***                    Point rendering                             ***/
48 /**********************************************************************/
49 
50 
51 /*
52  * Render an array of points into a pixmap, any pixel format.
53  */
54 #if 000
55 /* XXX don't use this, it doesn't dither correctly */
56 static void draw_points_ANY_pixmap( struct gl_context *ctx, const SWvertex *vert )
57 {
58    XMesaContext xmesa = XMESA_CONTEXT(ctx);
59    XMesaDisplay *dpy = xmesa->xm_visual->display;
60    XMesaDrawable buffer = xmesa->xm_buffer->buffer;
61    XMesaGC gc = xmesa->xm_buffer->gc;
62 
63    if (xmesa->xm_visual->mesa_visual.RGBAflag) {
64       register int x, y;
65       const GLubyte *color = vert->color;
66       unsigned long pixel = xmesa_color_to_pixel( xmesa,
67 						  color[0], color[1],
68 						  color[2], color[3],
69 						  xmesa->pixelformat);
70       XMesaSetForeground( dpy, gc, pixel );
71       x = (GLint) vert->win[0];
72       y = YFLIP( xrb, (GLint) vert->win[1] );
73       XMesaDrawPoint( dpy, buffer, gc, x, y);
74    }
75    else {
76       /* Color index mode */
77       register int x, y;
78       XMesaSetForeground( dpy, gc, vert->index );
79       x =                         (GLint) vert->win[0];
80       y = YFLIP( xrb, (GLint) vert->win[1] );
81       XMesaDrawPoint( dpy, buffer, gc, x, y);
82    }
83 }
84 #endif
85 
86 
87 /* Override the swrast point-selection function.  Try to use one of
88  * our internal point functions, otherwise fall back to the standard
89  * swrast functions.
90  */
xmesa_choose_point(struct gl_context * ctx)91 void xmesa_choose_point( struct gl_context *ctx )
92 {
93 #if 0
94    XMesaContext xmesa = XMESA_CONTEXT(ctx);
95    SWcontext *swrast = SWRAST_CONTEXT(ctx);
96 
97    if (ctx->RenderMode == GL_RENDER
98        && ctx->Point.Size == 1.0F && !ctx->Point.SmoothFlag
99        && swrast->_RasterMask == 0
100        && ctx->Texture._MaxEnabledTexImageUnit == -1
101        && xmesa->xm_buffer->buffer != XIMAGE) {
102       swrast->Point = draw_points_ANY_pixmap;
103    }
104    else {
105       _swrast_choose_point( ctx );
106    }
107 #else
108    _swrast_choose_point( ctx );
109 #endif
110 }
111 
112 
113 
114 /**********************************************************************/
115 /***                      Line rendering                            ***/
116 /**********************************************************************/
117 
118 
119 #if CHAN_BITS == 8
120 
121 
122 #define GET_XRB(XRB)  struct xmesa_renderbuffer *XRB = \
123    xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0])
124 
125 
126 /*
127  * Draw a flat-shaded, PF_TRUECOLOR line into an XImage.
128  */
129 #define NAME flat_TRUECOLOR_line
130 #define SETUP_CODE					\
131    XMesaContext xmesa = XMESA_CONTEXT(ctx);		\
132    GET_XRB(xrb);					\
133    const GLubyte *color = vert1->color;			\
134    unsigned long pixel;					\
135    PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
136 #define CLIP_HACK 1
137 #define PLOT(X,Y) XMesaPutPixel(xrb->ximage, X, YFLIP(xrb, Y), pixel );
138 #include "swrast/s_linetemp.h"
139 
140 
141 
142 /*
143  * Draw a flat-shaded, PF_8A8B8G8R line into an XImage.
144  */
145 #define NAME flat_8A8B8G8R_line
146 #define SETUP_CODE						\
147    GET_XRB(xrb);						\
148    const GLubyte *color = vert1->color;				\
149    GLuint pixel = PACK_8A8B8G8R(color[0], color[1], color[2], color[3]);
150 #define PIXEL_TYPE GLuint
151 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
152 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
153 #define CLIP_HACK 1
154 #define PLOT(X,Y) *pixelPtr = pixel;
155 #include "swrast/s_linetemp.h"
156 
157 
158 
159 /*
160  * Draw a flat-shaded, PF_8A8R8G8B line into an XImage.
161  */
162 #define NAME flat_8A8R8G8B_line
163 #define SETUP_CODE						\
164    GET_XRB(xrb);						\
165    const GLubyte *color = vert1->color;				\
166    GLuint pixel = PACK_8A8R8G8B(color[0], color[1], color[2], color[3]);
167 #define PIXEL_TYPE GLuint
168 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
169 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
170 #define CLIP_HACK 1
171 #define PLOT(X,Y) *pixelPtr = pixel;
172 #include "swrast/s_linetemp.h"
173 
174 
175 
176 /*
177  * Draw a flat-shaded, PF_8R8G8B line into an XImage.
178  */
179 #define NAME flat_8R8G8B_line
180 #define SETUP_CODE						\
181    GET_XRB(xrb);						\
182    const GLubyte *color = vert1->color;				\
183    GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
184 #define PIXEL_TYPE GLuint
185 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
186 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X, Y)
187 #define CLIP_HACK 1
188 #define PLOT(X,Y) *pixelPtr = pixel;
189 #include "swrast/s_linetemp.h"
190 
191 
192 
193 /*
194  * Draw a flat-shaded, PF_8R8G8B24 line into an XImage.
195  */
196 #define NAME flat_8R8G8B24_line
197 #define SETUP_CODE						\
198    GET_XRB(xrb);						\
199    const GLubyte *color = vert1->color;
200 #define PIXEL_TYPE bgr_t
201 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
202 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X, Y)
203 #define CLIP_HACK 1
204 #define PLOT(X,Y) {			\
205       pixelPtr->r = color[RCOMP];	\
206       pixelPtr->g = color[GCOMP];	\
207       pixelPtr->b = color[BCOMP];	\
208 }
209 #include "swrast/s_linetemp.h"
210 
211 
212 
213 /*
214  * Draw a flat-shaded, PF_5R6G5B line into an XImage.
215  */
216 #define NAME flat_5R6G5B_line
217 #define SETUP_CODE						\
218    GET_XRB(xrb);						\
219    const GLubyte *color = vert1->color;				\
220    GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
221 #define PIXEL_TYPE GLushort
222 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
223 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
224 #define CLIP_HACK 1
225 #define PLOT(X,Y) *pixelPtr = pixel;
226 #include "swrast/s_linetemp.h"
227 
228 
229 
230 /*
231  * Draw a flat-shaded, PF_DITHER_5R6G5B line into an XImage.
232  */
233 #define NAME flat_DITHER_5R6G5B_line
234 #define SETUP_CODE						\
235    GET_XRB(xrb);						\
236    XMesaContext xmesa = XMESA_CONTEXT(ctx);			\
237    const GLubyte *color = vert1->color;
238 #define PIXEL_TYPE GLushort
239 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
240 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X, Y)
241 #define CLIP_HACK 1
242 #define PLOT(X,Y) PACK_TRUEDITHER( *pixelPtr, X, Y, color[0], color[1], color[2] );
243 #include "swrast/s_linetemp.h"
244 
245 
246 
247 /*
248  * Draw a flat-shaded, Z-less, PF_TRUECOLOR line into an XImage.
249  */
250 #define NAME flat_TRUECOLOR_z_line
251 #define SETUP_CODE						\
252    GET_XRB(xrb);						\
253    XMesaContext xmesa = XMESA_CONTEXT(ctx);			\
254    const GLubyte *color = vert1->color;				\
255    unsigned long pixel;						\
256    PACK_TRUECOLOR( pixel, color[0], color[1], color[2] );
257 #define INTERP_Z 1
258 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
259 #define CLIP_HACK 1
260 #define PLOT(X,Y)							\
261 	if (Z < *zPtr) {						\
262 	   *zPtr = Z;							\
263            XMesaPutPixel(xrb->ximage, X, YFLIP(xrb, Y), pixel);		\
264 	}
265 #include "swrast/s_linetemp.h"
266 
267 
268 
269 /*
270  * Draw a flat-shaded, Z-less, PF_8A8B8G8R line into an XImage.
271  */
272 #define NAME flat_8A8B8G8R_z_line
273 #define SETUP_CODE						\
274    GET_XRB(xrb);						\
275    const GLubyte *color = vert1->color;				\
276    GLuint pixel = PACK_8A8B8G8R(color[0], color[1], color[2], color[3]);
277 #define INTERP_Z 1
278 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
279 #define PIXEL_TYPE GLuint
280 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
281 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
282 #define CLIP_HACK 1
283 #define PLOT(X,Y)		\
284 	if (Z < *zPtr) {	\
285 	   *zPtr = Z;		\
286 	   *pixelPtr = pixel;	\
287 	}
288 #include "swrast/s_linetemp.h"
289 
290 
291 
292 /*
293  * Draw a flat-shaded, Z-less, PF_8A8R8G8B line into an XImage.
294  */
295 #define NAME flat_8A8R8G8B_z_line
296 #define SETUP_CODE						\
297    GET_XRB(xrb);						\
298    const GLubyte *color = vert1->color;				\
299    GLuint pixel = PACK_8A8R8G8B(color[0], color[1], color[2], color[3]);
300 #define INTERP_Z 1
301 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
302 #define PIXEL_TYPE GLuint
303 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
304 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
305 #define CLIP_HACK 1
306 #define PLOT(X,Y)		\
307 	if (Z < *zPtr) {	\
308 	   *zPtr = Z;		\
309 	   *pixelPtr = pixel;	\
310 	}
311 #include "swrast/s_linetemp.h"
312 
313 
314 
315 /*
316  * Draw a flat-shaded, Z-less, PF_8R8G8B line into an XImage.
317  */
318 #define NAME flat_8R8G8B_z_line
319 #define SETUP_CODE						\
320    GET_XRB(xrb);						\
321    const GLubyte *color = vert1->color;				\
322    GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] );
323 #define INTERP_Z 1
324 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
325 #define PIXEL_TYPE GLuint
326 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
327 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR4(xrb, X,Y)
328 #define CLIP_HACK 1
329 #define PLOT(X,Y)		\
330 	if (Z < *zPtr) {	\
331 	   *zPtr = Z;		\
332 	   *pixelPtr = pixel;	\
333 	}
334 #include "swrast/s_linetemp.h"
335 
336 
337 
338 /*
339  * Draw a flat-shaded, Z-less, PF_8R8G8B24 line into an XImage.
340  */
341 #define NAME flat_8R8G8B24_z_line
342 #define SETUP_CODE						\
343    GET_XRB(xrb);						\
344    const GLubyte *color = vert1->color;
345 #define INTERP_Z 1
346 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
347 #define PIXEL_TYPE bgr_t
348 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
349 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR3(xrb, X,Y)
350 #define CLIP_HACK 1
351 #define PLOT(X,Y)			\
352 	if (Z < *zPtr) {		\
353 	   *zPtr = Z;			\
354            pixelPtr->r = color[RCOMP];	\
355            pixelPtr->g = color[GCOMP];	\
356            pixelPtr->b = color[BCOMP];	\
357 	}
358 #include "swrast/s_linetemp.h"
359 
360 
361 
362 /*
363  * Draw a flat-shaded, Z-less, PF_5R6G5B line into an XImage.
364  */
365 #define NAME flat_5R6G5B_z_line
366 #define SETUP_CODE						\
367    GET_XRB(xrb);						\
368    const GLubyte *color = vert1->color;				\
369    GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] );
370 #define INTERP_Z 1
371 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
372 #define PIXEL_TYPE GLushort
373 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
374 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X,Y)
375 #define CLIP_HACK 1
376 #define PLOT(X,Y)		\
377 	if (Z < *zPtr) {	\
378 	   *zPtr = Z;		\
379 	   *pixelPtr = pixel;	\
380 	}
381 #include "swrast/s_linetemp.h"
382 
383 
384 
385 /*
386  * Draw a flat-shaded, Z-less, PF_DITHER_5R6G5B line into an XImage.
387  */
388 #define NAME flat_DITHER_5R6G5B_z_line
389 #define SETUP_CODE					\
390    GET_XRB(xrb);						\
391    XMesaContext xmesa = XMESA_CONTEXT(ctx);		\
392    const GLubyte *color = vert1->color;
393 #define INTERP_Z 1
394 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
395 #define PIXEL_TYPE GLushort
396 #define BYTES_PER_ROW (xrb->ximage->bytes_per_line)
397 #define PIXEL_ADDRESS(X,Y) PIXEL_ADDR2(xrb, X,Y)
398 #define CLIP_HACK 1
399 #define PLOT(X,Y)		\
400 	if (Z < *zPtr) {	\
401 	   *zPtr = Z;		\
402 	   PACK_TRUEDITHER(*pixelPtr, X, Y, color[0], color[1], color[2]); \
403 	}
404 #include "swrast/s_linetemp.h"
405 
406 
407 
408 /**
409  * Draw fast, XOR line with XDrawLine in front color buffer.
410  * WARNING: this isn't fully OpenGL conformant because different pixels
411  * will be hit versus using the other line functions.
412  * Don't use the code in X server GLcore module since we need a wrapper
413  * for the XSetLineAttributes() function call.
414  */
415 static void
xor_line(struct gl_context * ctx,const SWvertex * vert0,const SWvertex * vert1)416 xor_line(struct gl_context *ctx, const SWvertex *vert0, const SWvertex *vert1)
417 {
418    XMesaContext xmesa = XMESA_CONTEXT(ctx);
419    XMesaDisplay *dpy = xmesa->xm_visual->display;
420    XMesaGC gc = xmesa->xm_buffer->gc;
421    GET_XRB(xrb);
422    unsigned long pixel = xmesa_color_to_pixel(ctx,
423                                               vert1->color[0], vert1->color[1],
424                                               vert1->color[2], vert1->color[3],
425                                               xmesa->pixelformat);
426    int x0 =            (GLint) vert0->attrib[VARYING_SLOT_POS][0];
427    int y0 = YFLIP(xrb, (GLint) vert0->attrib[VARYING_SLOT_POS][1]);
428    int x1 =            (GLint) vert1->attrib[VARYING_SLOT_POS][0];
429    int y1 = YFLIP(xrb, (GLint) vert1->attrib[VARYING_SLOT_POS][1]);
430    XMesaSetForeground(dpy, gc, pixel);
431    XMesaSetFunction(dpy, gc, GXxor);
432    XSetLineAttributes(dpy, gc, (int) ctx->Line.Width,
433                       LineSolid, CapButt, JoinMiter);
434    XDrawLine(dpy, xrb->pixmap, gc, x0, y0, x1, y1);
435    XMesaSetFunction(dpy, gc, GXcopy);  /* this gc is used elsewhere */
436 }
437 
438 
439 #endif /* CHAN_BITS == 8 */
440 
441 
442 /**
443  * Return pointer to line drawing function, or NULL if we should use a
444  * swrast fallback.
445  */
446 static swrast_line_func
get_line_func(struct gl_context * ctx)447 get_line_func(struct gl_context *ctx)
448 {
449 #if CHAN_BITS == 8
450    SWcontext *swrast = SWRAST_CONTEXT(ctx);
451    XMesaContext xmesa = XMESA_CONTEXT(ctx);
452    const struct xmesa_renderbuffer *xrb;
453 
454    if ((ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_FRONT_LEFT) &&
455        (ctx->DrawBuffer->_ColorDrawBufferIndexes[0] != BUFFER_BIT_BACK_LEFT))
456       return (swrast_line_func) NULL;
457    if (ctx->RenderMode != GL_RENDER)      return (swrast_line_func) NULL;
458    if (ctx->Line.SmoothFlag)              return (swrast_line_func) NULL;
459    if (ctx->Texture._MaxEnabledTexImageUnit != -1)        return (swrast_line_func) NULL;
460    if (ctx->Light.ShadeModel != GL_FLAT)  return (swrast_line_func) NULL;
461    if (ctx->Line.StippleFlag)             return (swrast_line_func) NULL;
462    if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL;
463 
464    xrb = xmesa_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0]);
465 
466    if (xrb->ximage
467        && swrast->_RasterMask==DEPTH_BIT
468        && ctx->Depth.Func==GL_LESS
469        && ctx->Depth.Mask==GL_TRUE
470        && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
471        && ctx->Line.Width==1.0F) {
472       switch (xmesa->pixelformat) {
473          case PF_Truecolor:
474             return flat_TRUECOLOR_z_line;
475          case PF_8A8B8G8R:
476             return flat_8A8B8G8R_z_line;
477          case PF_8A8R8G8B:
478             return flat_8A8R8G8B_z_line;
479          case PF_8R8G8B:
480             return flat_8R8G8B_z_line;
481          case PF_8R8G8B24:
482             return flat_8R8G8B24_z_line;
483          case PF_5R6G5B:
484             return flat_5R6G5B_z_line;
485          case PF_Dither_5R6G5B:
486             return flat_DITHER_5R6G5B_z_line;
487          default:
488             return (swrast_line_func)NULL;
489       }
490    }
491    if (xrb->ximage
492        && swrast->_RasterMask==0
493        && ctx->Line.Width==1.0F) {
494       switch (xmesa->pixelformat) {
495          case PF_Truecolor:
496             return flat_TRUECOLOR_line;
497          case PF_8A8B8G8R:
498             return flat_8A8B8G8R_line;
499          case PF_8A8R8G8B:
500             return flat_8A8R8G8B_line;
501          case PF_8R8G8B:
502             return flat_8R8G8B_line;
503          case PF_8R8G8B24:
504             return flat_8R8G8B24_line;
505          case PF_5R6G5B:
506             return flat_5R6G5B_line;
507          case PF_Dither_5R6G5B:
508             return flat_DITHER_5R6G5B_line;
509 	 default:
510 	    return (swrast_line_func)NULL;
511       }
512    }
513 
514    if (ctx->DrawBuffer->_NumColorDrawBuffers == 1
515        && ctx->DrawBuffer->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT
516        && swrast->_RasterMask == LOGIC_OP_BIT
517        && ctx->Color.LogicOp == GL_XOR
518        && !ctx->Line.StippleFlag
519        && !ctx->Line.SmoothFlag) {
520       return xor_line;
521    }
522 
523 #endif /* CHAN_BITS == 8 */
524    return (swrast_line_func) NULL;
525 }
526 
527 
528 /**
529  * Override for the swrast line-selection function.  Try to use one
530  * of our internal line functions, otherwise fall back to the
531  * standard swrast functions.
532  */
533 void
xmesa_choose_line(struct gl_context * ctx)534 xmesa_choose_line(struct gl_context *ctx)
535 {
536    SWcontext *swrast = SWRAST_CONTEXT(ctx);
537 
538    if (!(swrast->Line = get_line_func( ctx )))
539       _swrast_choose_line( ctx );
540 }
541