1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
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 */
56static 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 */
91void 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._EnabledUnits
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 */
415static void
416xor_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[FRAG_ATTRIB_WPOS][0];
427   int y0 = YFLIP(xrb, (GLint) vert0->attrib[FRAG_ATTRIB_WPOS][1]);
428   int x1 =            (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][0];
429   int y1 = YFLIP(xrb, (GLint) vert1->attrib[FRAG_ATTRIB_WPOS][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 */
446static swrast_line_func
447get_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._EnabledUnits)        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 */
533void
534xmesa_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