xm_dd.c revision 1832f1cc86758fdcbd122edd5bf9e7a29ccade20
1/* $Id: xm_dd.c,v 1.23 2001/04/27 21:18:25 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#include "glxheader.h"
29#include "context.h"
30#include "depth.h"
31#include "drawpix.h"
32#include "extensions.h"
33#include "macros.h"
34#include "mem.h"
35#include "mtypes.h"
36#include "state.h"
37#include "texstore.h"
38#include "texformat.h"
39#include "xmesaP.h"
40#include "array_cache/acache.h"
41#include "swrast/swrast.h"
42#include "swrast/s_alphabuf.h"
43#include "swrast_setup/swrast_setup.h"
44#include "tnl/tnl.h"
45#include "tnl/t_context.h"
46
47
48/*
49 * Return the size (width,height of the current color buffer.
50 * This function should be called by the glViewport function because
51 * glViewport is often called when the window gets resized.  We need to
52 * update some X/Mesa stuff when that happens.
53 * Output:  width - width of buffer in pixels.
54 *          height - height of buffer in pixels.
55 */
56static void
57get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
58{
59   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
60   unsigned int winwidth, winheight;
61#ifndef XFree86Server
62   Window root;
63   int winx, winy;
64   unsigned int bw, d;
65
66   _glthread_LOCK_MUTEX(_xmesa_lock);
67   XGetGeometry( xmesa->display, xmesa->xm_buffer->frontbuffer, &root,
68		 &winx, &winy, &winwidth, &winheight, &bw, &d );
69   _glthread_UNLOCK_MUTEX(_xmesa_lock);
70#else
71
72   winwidth = xmesa->xm_buffer->frontbuffer->width;
73   winheight = xmesa->xm_buffer->frontbuffer->height;
74#endif
75
76   *width = winwidth;
77   *height = winheight;
78
79   if (   winwidth!=xmesa->xm_buffer->width
80       || winheight!=xmesa->xm_buffer->height) {
81      xmesa->xm_buffer->width = winwidth;
82      xmesa->xm_buffer->height = winheight;
83      xmesa_alloc_back_buffer( xmesa->xm_buffer );
84   }
85
86   /* Needed by FLIP macro */
87   xmesa->xm_buffer->bottom = (int) winheight - 1;
88
89   if (xmesa->xm_buffer->backimage) {
90      /* Needed by PIXELADDR1 macro */
91      xmesa->xm_buffer->ximage_width1
92                  = xmesa->xm_buffer->backimage->bytes_per_line;
93      xmesa->xm_buffer->ximage_origin1
94                  = (GLubyte *) xmesa->xm_buffer->backimage->data
95                    + xmesa->xm_buffer->ximage_width1 * (winheight-1);
96
97      /* Needed by PIXELADDR2 macro */
98      xmesa->xm_buffer->ximage_width2
99                  = xmesa->xm_buffer->backimage->bytes_per_line / 2;
100      xmesa->xm_buffer->ximage_origin2
101                  = (GLushort *) xmesa->xm_buffer->backimage->data
102                    + xmesa->xm_buffer->ximage_width2 * (winheight-1);
103
104      /* Needed by PIXELADDR3 macro */
105      xmesa->xm_buffer->ximage_width3
106                  = xmesa->xm_buffer->backimage->bytes_per_line;
107      xmesa->xm_buffer->ximage_origin3
108                  = (GLubyte *) xmesa->xm_buffer->backimage->data
109                    + xmesa->xm_buffer->ximage_width3 * (winheight-1);
110
111      /* Needed by PIXELADDR4 macro */
112      xmesa->xm_buffer->ximage_width4 = xmesa->xm_buffer->backimage->width;
113      xmesa->xm_buffer->ximage_origin4
114                  = (GLuint *) xmesa->xm_buffer->backimage->data
115                    + xmesa->xm_buffer->ximage_width4 * (winheight-1);
116   }
117}
118
119
120static void
121finish( GLcontext *ctx )
122{
123#ifdef XFree86Server
124      /* NOT_NEEDED */
125#else
126   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
127   if (xmesa) {
128      _glthread_LOCK_MUTEX(_xmesa_lock);
129      XSync( xmesa->display, False );
130      _glthread_UNLOCK_MUTEX(_xmesa_lock);
131   }
132#endif
133}
134
135
136static void
137flush( GLcontext *ctx )
138{
139#ifdef XFree86Server
140      /* NOT_NEEDED */
141#else
142   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
143   if (xmesa) {
144      _glthread_LOCK_MUTEX(_xmesa_lock);
145      XFlush( xmesa->display );
146      _glthread_UNLOCK_MUTEX(_xmesa_lock);
147   }
148#endif
149}
150
151
152
153
154static GLboolean
155set_draw_buffer( GLcontext *ctx, GLenum mode )
156{
157   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
158   if (mode == GL_FRONT_LEFT) {
159      /* write to front buffer */
160      xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
161      xmesa_update_span_funcs(ctx);
162      return GL_TRUE;
163   }
164   else if (mode==GL_BACK_LEFT && xmesa->xm_buffer->db_state) {
165      /* write to back buffer */
166      if (xmesa->xm_buffer->backpixmap) {
167         xmesa->xm_buffer->buffer =
168	     (XMesaDrawable)xmesa->xm_buffer->backpixmap;
169      }
170      else if (xmesa->xm_buffer->backimage) {
171         xmesa->xm_buffer->buffer = None;
172      }
173      else {
174         /* just in case there wasn't enough memory for back buffer */
175         xmesa->xm_buffer->buffer = xmesa->xm_buffer->frontbuffer;
176      }
177      xmesa_update_span_funcs(ctx);
178      return GL_TRUE;
179   }
180   else {
181      return GL_FALSE;
182   }
183}
184
185
186void
187xmesa_set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
188{
189   XMesaBuffer target;
190   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
191
192   if (buffer == ctx->DrawBuffer) {
193      target = xmesa->xm_buffer;
194      xmesa->use_read_buffer = GL_FALSE;
195   }
196   else {
197      ASSERT(buffer == ctx->ReadBuffer);
198      target = xmesa->xm_read_buffer;
199      xmesa->use_read_buffer = GL_TRUE;
200   }
201
202   if (mode == GL_FRONT_LEFT) {
203      target->buffer = target->frontbuffer;
204      xmesa_update_span_funcs(ctx);
205   }
206   else if (mode==GL_BACK_LEFT && xmesa->xm_read_buffer->db_state) {
207      if (target->backpixmap) {
208         target->buffer = (XMesaDrawable)xmesa->xm_buffer->backpixmap;
209      }
210      else if (target->backimage) {
211         target->buffer = None;
212      }
213      else {
214         /* just in case there wasn't enough memory for back buffer */
215         target->buffer = target->frontbuffer;
216      }
217      xmesa_update_span_funcs(ctx);
218   }
219   else {
220      _mesa_problem(ctx, "invalid buffer in set_read_buffer() in xmesa2.c");
221   }
222}
223
224
225
226static void
227clear_index( GLcontext *ctx, GLuint index )
228{
229   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
230   xmesa->clearpixel = (unsigned long) index;
231   XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
232                       (unsigned long) index );
233}
234
235
236static void
237clear_color( GLcontext *ctx, const GLchan color[4] )
238{
239   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
240   xmesa->clearcolor[0] = color[0];
241   xmesa->clearcolor[1] = color[1];
242   xmesa->clearcolor[2] = color[2];
243   xmesa->clearcolor[3] = color[3];
244   xmesa->clearpixel = xmesa_color_to_pixel( xmesa, color[0], color[1],
245                                             color[2], color[3],
246                                             xmesa->xm_visual->undithered_pf );
247   _glthread_LOCK_MUTEX(_xmesa_lock);
248   XMesaSetForeground( xmesa->display, xmesa->xm_buffer->cleargc,
249                       xmesa->clearpixel );
250   _glthread_UNLOCK_MUTEX(_xmesa_lock);
251}
252
253
254
255/* Set index mask ala glIndexMask */
256static void
257index_mask( GLcontext *ctx, GLuint mask )
258{
259   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
260   if (xmesa->xm_buffer->buffer != XIMAGE) {
261      unsigned long m;
262      if (mask==0xffffffff) {
263	 m = ((unsigned long)~0L);
264      }
265      else {
266         m = (unsigned long) mask;
267      }
268      XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
269   }
270}
271
272
273/* Implements glColorMask() */
274static void
275color_mask(GLcontext *ctx,
276           GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask)
277{
278   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
279   int xclass = GET_VISUAL_CLASS(xmesa->xm_visual);
280   (void) amask;
281
282   if (xmesa->xm_buffer->buffer != XIMAGE
283       && (xclass == TrueColor || xclass == DirectColor)) {
284      unsigned long m;
285      if (rmask && gmask && bmask) {
286         m = ((unsigned long)~0L);
287      }
288      else {
289         m = 0;
290         if (rmask)   m |= GET_REDMASK(xmesa->xm_visual);
291         if (gmask)   m |= GET_GREENMASK(xmesa->xm_visual);
292         if (bmask)   m |= GET_BLUEMASK(xmesa->xm_visual);
293      }
294      XMesaSetPlaneMask( xmesa->display, xmesa->xm_buffer->cleargc, m );
295   }
296}
297
298
299
300/**********************************************************************/
301/*** glClear implementations                                        ***/
302/**********************************************************************/
303
304
305static void
306clear_front_pixmap( GLcontext *ctx, GLboolean all,
307                    GLint x, GLint y, GLint width, GLint height )
308{
309   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
310   if (all) {
311      XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
312                          xmesa->xm_buffer->cleargc,
313                          0, 0,
314                          xmesa->xm_buffer->width+1,
315                          xmesa->xm_buffer->height+1 );
316   }
317   else {
318      XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->frontbuffer,
319                          xmesa->xm_buffer->cleargc,
320                          x, xmesa->xm_buffer->height - y - height,
321                          width, height );
322   }
323}
324
325
326static void
327clear_back_pixmap( GLcontext *ctx, GLboolean all,
328                   GLint x, GLint y, GLint width, GLint height )
329{
330   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
331   if (all) {
332      XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
333                          xmesa->xm_buffer->cleargc,
334                          0, 0,
335                          xmesa->xm_buffer->width+1,
336                          xmesa->xm_buffer->height+1 );
337   }
338   else {
339      XMesaFillRectangle( xmesa->display, xmesa->xm_buffer->backpixmap,
340                          xmesa->xm_buffer->cleargc,
341                          x, xmesa->xm_buffer->height - y - height,
342                          width, height );
343   }
344}
345
346
347static void
348clear_8bit_ximage( GLcontext *ctx, GLboolean all,
349                   GLint x, GLint y, GLint width, GLint height )
350{
351   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
352   if (all) {
353      size_t n = xmesa->xm_buffer->backimage->bytes_per_line
354         * xmesa->xm_buffer->backimage->height;
355      MEMSET( xmesa->xm_buffer->backimage->data, xmesa->clearpixel, n );
356   }
357   else {
358      GLint i;
359      for (i=0;i<height;i++) {
360         GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, y+i );
361         MEMSET( ptr, xmesa->clearpixel, width );
362      }
363   }
364}
365
366
367static void
368clear_HPCR_ximage( GLcontext *ctx, GLboolean all,
369                   GLint x, GLint y, GLint width, GLint height )
370{
371   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
372   if (all) {
373      GLint i, c16 = (xmesa->xm_buffer->backimage->bytes_per_line>>4)<<4;
374      GLubyte *ptr  = (GLubyte *)xmesa->xm_buffer->backimage->data;
375      for (i=0; i<xmesa->xm_buffer->backimage->height; i++) {
376         GLint j;
377         GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
378         if (i&1) {
379            sptr += 16;
380         }
381         for (j=0; j<c16; j+=16) {
382            ptr[0] = sptr[0];
383            ptr[1] = sptr[1];
384            ptr[2] = sptr[2];
385            ptr[3] = sptr[3];
386            ptr[4] = sptr[4];
387            ptr[5] = sptr[5];
388            ptr[6] = sptr[6];
389            ptr[7] = sptr[7];
390            ptr[8] = sptr[8];
391            ptr[9] = sptr[9];
392            ptr[10] = sptr[10];
393            ptr[11] = sptr[11];
394            ptr[12] = sptr[12];
395            ptr[13] = sptr[13];
396            ptr[14] = sptr[14];
397            ptr[15] = sptr[15];
398            ptr += 16;
399         }
400         for (; j<xmesa->xm_buffer->backimage->bytes_per_line; j++) {
401            *ptr = sptr[j&15];
402            ptr++;
403         }
404      }
405   }
406   else {
407      GLint i;
408      for (i=y; i<y+height; i++) {
409         GLubyte *ptr = PIXELADDR1( xmesa->xm_buffer, x, i );
410         int j;
411         GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0];
412         if (i&1) {
413            sptr += 16;
414         }
415         for (j=x; j<x+width; j++) {
416            *ptr = sptr[j&15];
417            ptr++;
418         }
419      }
420   }
421}
422
423
424static void
425clear_16bit_ximage( GLcontext *ctx, GLboolean all,
426                    GLint x, GLint y, GLint width, GLint height )
427{
428   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
429   register GLuint pixel = (GLuint) xmesa->clearpixel;
430   if (xmesa->swapbytes) {
431      pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00);
432   }
433   if (all) {
434      register GLuint n;
435      register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
436      if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) {
437         /* low and high bytes are equal so use memset() */
438         n = xmesa->xm_buffer->backimage->bytes_per_line
439            * xmesa->xm_buffer->height;
440         MEMSET( ptr4, pixel & 0xff, n );
441      }
442      else {
443         pixel = pixel | (pixel<<16);
444         n = xmesa->xm_buffer->backimage->bytes_per_line
445            * xmesa->xm_buffer->height / 4;
446         do {
447            *ptr4++ = pixel;
448               n--;
449         } while (n!=0);
450
451         if ((xmesa->xm_buffer->backimage->bytes_per_line *
452              xmesa->xm_buffer->height) & 0x2)
453            *(GLushort *)ptr4 = pixel & 0xffff;
454      }
455   }
456   else {
457      register int i, j;
458      for (j=0;j<height;j++) {
459         register GLushort *ptr2 = PIXELADDR2( xmesa->xm_buffer, x, y+j );
460         for (i=0;i<width;i++) {
461            *ptr2++ = pixel;
462         }
463      }
464   }
465}
466
467
468/* Optimized code provided by Nozomi Ytow <noz@xfree86.org> */
469static void
470clear_24bit_ximage( GLcontext *ctx, GLboolean all,
471                    GLint x, GLint y, GLint width, GLint height )
472{
473   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
474   const GLubyte r = xmesa->clearcolor[0];
475   const GLubyte g = xmesa->clearcolor[1];
476   const GLubyte b = xmesa->clearcolor[2];
477   register GLuint clearPixel;
478   if (xmesa->swapbytes) {
479      clearPixel = (b << 16) | (g << 8) | r;
480   }
481   else {
482      clearPixel = (r << 16) | (g << 8) | b;
483   }
484
485   if (all) {
486      if (r==g && g==b) {
487         /* same value for all three components (gray) */
488         const GLint w3 = xmesa->xm_buffer->width * 3;
489         const GLint h = xmesa->xm_buffer->height;
490         GLint i;
491         for (i = 0; i < h; i++) {
492            bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
493            MEMSET(ptr3, r, w3);
494         }
495      }
496      else {
497         /* the usual case */
498         const GLint w = xmesa->xm_buffer->width;
499         const GLint h = xmesa->xm_buffer->height;
500         GLint i, j;
501         for (i = 0; i < h; i++) {
502            bgr_t *ptr3 = PIXELADDR3(xmesa->xm_buffer, 0, i);
503            for (j = 0; j < w; j++) {
504               ptr3->r = r;
505               ptr3->g = g;
506               ptr3->b = b;
507               ptr3++;
508            }
509         }
510#if 0 /* this code doesn't work for all window widths */
511         register GLuint *ptr4 = (GLuint *) ptr3;
512         register GLuint px;
513         GLuint pixel4[3];
514         register GLuint *p = pixel4;
515         pixel4[0] = clearPixel | (clearPixel << 24);
516         pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
517         pixel4[2] = (clearPixel << 8) | (clearPixel >>  16);
518         switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
519            case 0:
520               break;
521            case 1:
522               px = *ptr4 & 0x00ffffff;
523               px |= pixel4[0] & 0xff000000;
524               *ptr4++ = px;
525               px = *ptr4 & 0xffff0000;
526               px |= pixel4[2] & 0x0000ffff;
527               *ptr4 = px;
528               if (0 == --n)
529                  break;
530            case 2:
531               px = *ptr4 & 0x0000fffff;
532               px |= pixel4[1] & 0xffff0000;
533               *ptr4++ = px;
534               px = *ptr4 & 0xffffff00;
535               px |= pixel4[2] & 0x000000ff;
536               *ptr4 = px;
537               if (0 == --n)
538                  break;
539            case 3:
540               px = *ptr4 & 0x000000ff;
541               px |= pixel4[2] & 0xffffff00;
542               *ptr4++ = px;
543               --n;
544               break;
545         }
546         while (n > 3) {
547            p = pixel4;
548            *ptr4++ = *p++;
549            *ptr4++ = *p++;
550            *ptr4++ = *p++;
551            n -= 4;
552         }
553         switch (n) {
554            case 3:
555               p = pixel4;
556               *ptr4++ = *p++;
557               *ptr4++ = *p++;
558               px = *ptr4 & 0xffffff00;
559               px |= clearPixel & 0xff;
560               *ptr4 = px;
561               break;
562            case 2:
563               p = pixel4;
564               *ptr4++ = *p++;
565               px = *ptr4 & 0xffff0000;
566               px |= *p & 0xffff;
567               *ptr4 = px;
568               break;
569            case 1:
570               px = *ptr4 & 0xff000000;
571               px |= *p & 0xffffff;
572               *ptr4 = px;
573               break;
574            case 0:
575               break;
576         }
577#endif
578      }
579   }
580   else {
581      /* only clear subrect of color buffer */
582      if (r==g && g==b) {
583         /* same value for all three components (gray) */
584         GLint j;
585         for (j=0;j<height;j++) {
586            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
587            MEMSET(ptr3, r, 3 * width);
588         }
589      }
590      else {
591         /* non-gray clear color */
592         GLint i, j;
593         for (j = 0; j < height; j++) {
594            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
595            for (i = 0; i < width; i++) {
596               ptr3->r = r;
597               ptr3->g = g;
598               ptr3->b = b;
599               ptr3++;
600            }
601         }
602#if 0 /* this code might not always (seems ptr3 always == ptr4) */
603         GLint j;
604         GLuint pixel4[3];
605         pixel4[0] = clearPixel | (clearPixel << 24);
606         pixel4[1] = (clearPixel << 16) | (clearPixel >> 8);
607         pixel4[2] = (clearPixel << 8) | (clearPixel >>  16);
608         for (j=0;j<height;j++) {
609            bgr_t *ptr3 = PIXELADDR3( xmesa->xm_buffer, x, y+j );
610            register GLuint *ptr4 = (GLuint *)ptr3;
611            register GLuint *p, px;
612            GLuint w = width;
613            switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){
614               case 0:
615                  break;
616               case 1:
617                  px = *ptr4 & 0x00ffffff;
618                  px |= pixel4[0] & 0xff000000;
619                  *ptr4++ = px;
620                  px = *ptr4 & 0xffff0000;
621                  px |= pixel4[2] & 0x0000ffff;
622                  *ptr4 = px;
623                  if (0 == --w)
624                     break;
625               case 2:
626                  px = *ptr4 & 0x0000fffff;
627                  px |= pixel4[1] & 0xffff0000;
628                  *ptr4++ = px;
629                  px = *ptr4 & 0xffffff00;
630                  px |= pixel4[2] & 0x000000ff;
631                  *ptr4 = px;
632                  if (0 == --w)
633                     break;
634               case 3:
635                  px = *ptr4 & 0x000000ff;
636                  px |= pixel4[2] & 0xffffff00;
637                  *ptr4++ = px;
638                  --w;
639                  break;
640            }
641            while (w > 3){
642               p = pixel4;
643               *ptr4++ = *p++;
644               *ptr4++ = *p++;
645               *ptr4++ = *p++;
646               w -= 4;
647            }
648            switch (w) {
649               case 3:
650                  p = pixel4;
651                  *ptr4++ = *p++;
652                  *ptr4++ = *p++;
653                  px = *ptr4 & 0xffffff00;
654                  px |= *p & 0xff;
655                  *ptr4 = px;
656                  break;
657               case 2:
658                  p = pixel4;
659                  *ptr4++ = *p++;
660                  px = *ptr4 & 0xffff0000;
661                  px |= *p & 0xffff;
662                  *ptr4 = px;
663                  break;
664               case 1:
665                  px = *ptr4 & 0xff000000;
666                  px |= pixel4[0] & 0xffffff;
667                  *ptr4 = px;
668                  break;
669               case 0:
670                  break;
671            }
672         }
673#endif
674      }
675   }
676}
677
678
679static void
680clear_32bit_ximage( GLcontext *ctx, GLboolean all,
681                    GLint x, GLint y, GLint width, GLint height )
682{
683   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
684   register GLuint pixel = (GLuint) xmesa->clearpixel;
685   if (xmesa->swapbytes) {
686      pixel = ((pixel >> 24) & 0x000000ff)
687            | ((pixel >> 8)  & 0x0000ff00)
688            | ((pixel << 8)  & 0x00ff0000)
689            | ((pixel << 24) & 0xff000000);
690   }
691   if (all) {
692      register GLint n = xmesa->xm_buffer->width * xmesa->xm_buffer->height;
693      register GLuint *ptr4 = (GLuint *) xmesa->xm_buffer->backimage->data;
694      if (pixel==0) {
695         MEMSET( ptr4, pixel, 4*n );
696      }
697      else {
698         do {
699            *ptr4++ = pixel;
700            n--;
701         } while (n!=0);
702      }
703   }
704   else {
705      register int i, j;
706      for (j=0;j<height;j++) {
707         register GLuint *ptr4 = PIXELADDR4( xmesa->xm_buffer, x, y+j );
708         for (i=0;i<width;i++) {
709            *ptr4++ = pixel;
710         }
711      }
712   }
713}
714
715
716static void
717clear_nbit_ximage( GLcontext *ctx, GLboolean all,
718                   GLint x, GLint y, GLint width, GLint height )
719{
720   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
721   XMesaImage *img = xmesa->xm_buffer->backimage;
722   if (all) {
723      register int i, j;
724      width = xmesa->xm_buffer->width;
725      height = xmesa->xm_buffer->height;
726      for (j=0;j<height;j++) {
727         for (i=0;i<width;i++) {
728            XMesaPutPixel( img, i, j, xmesa->clearpixel );
729         }
730      }
731   }
732   else {
733      /* TODO: optimize this */
734      register int i, j;
735      y = FLIP(xmesa->xm_buffer, y);
736      for (j=0;j<height;j++) {
737         for (i=0;i<width;i++) {
738            XMesaPutPixel( img, x+i, y-j, xmesa->clearpixel );
739         }
740      }
741   }
742}
743
744
745
746static void
747clear_buffers( GLcontext *ctx, GLbitfield mask,
748               GLboolean all, GLint x, GLint y, GLint width, GLint height )
749{
750   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
751   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
752
753   if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) &&
754       xmesa->xm_buffer->mesa_buffer.UseSoftwareAlphaBuffers &&
755       ctx->Color.ColorMask[ACOMP]) {
756      _mesa_clear_alpha_buffers(ctx);
757   }
758
759   /* we can't handle color or index masking */
760   if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
761      if (mask & DD_FRONT_LEFT_BIT) {
762	 ASSERT(xmesa->xm_buffer->front_clear_func);
763	 (*xmesa->xm_buffer->front_clear_func)( ctx, all, x, y, width, height );
764	 mask &= ~DD_FRONT_LEFT_BIT;
765      }
766      if (mask & DD_BACK_LEFT_BIT) {
767	 ASSERT(xmesa->xm_buffer->back_clear_func);
768	 (*xmesa->xm_buffer->back_clear_func)( ctx, all, x, y, width, height );
769	 mask &= ~DD_BACK_LEFT_BIT;
770      }
771   }
772
773   if (mask)
774      _swrast_Clear( ctx, mask, all, x, y, width, height );
775}
776
777
778static void
779resize_buffers( GLcontext *ctx )
780{
781   _swrast_alloc_buffers( ctx );
782}
783
784#if 0
785/*
786 * This function implements glDrawPixels() with an XPutImage call when
787 * drawing to the front buffer (X Window drawable).
788 * The image format must be GL_BGRA to match the PF_8R8G8B pixel format.
789 * XXX top/bottom edge clipping is broken!
790 */
791static GLboolean
792drawpixels_8R8G8B( GLcontext *ctx,
793                   GLint x, GLint y, GLsizei width, GLsizei height,
794                   GLenum format, GLenum type,
795                   const struct gl_pixelstore_attrib *unpack,
796                   const GLvoid *pixels )
797{
798   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
799   XMesaDisplay *dpy = xmesa->xm_visual->display;
800   XMesaDrawable buffer = xmesa->xm_buffer->buffer;
801   XMesaGC gc = xmesa->xm_buffer->gc;
802   assert(dpy);
803   assert(buffer);
804   assert(gc);
805
806   /* XXX also check for pixel scale/bias/lookup/zooming! */
807   if (format == GL_BGRA && type == GL_UNSIGNED_BYTE) {
808      int dstX = x;
809      int dstY = y;
810      int w = width;
811      int h = height;
812      int srcX = unpack->SkipPixels;
813      int srcY = unpack->SkipRows;
814      if (_mesa_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
815         XMesaImage ximage;
816         MEMSET(&ximage, 0, sizeof(XMesaImage));
817         ximage.width = width;
818         ximage.height = height;
819         ximage.format = ZPixmap;
820         ximage.data = (char *) pixels + (height - 1) * width * 4;
821         ximage.byte_order = LSBFirst;
822         ximage.bitmap_unit = 32;
823         ximage.bitmap_bit_order = LSBFirst;
824         ximage.bitmap_pad = 32;
825         ximage.depth = 24;
826         ximage.bytes_per_line = -width * 4;
827         ximage.bits_per_pixel = 32;
828         ximage.red_mask   = 0xff0000;
829         ximage.green_mask = 0x00ff00;
830         ximage.blue_mask  = 0x0000ff;
831         dstY = FLIP(xmesa->xm_buffer,dstY) - height + 1;
832         XPutImage(dpy, buffer, gc, &ximage, srcX, srcY, dstX, dstY, w, h);
833         return GL_TRUE;
834      }
835   }
836   return GL_FALSE;
837}
838#endif
839
840
841
842static const GLubyte *
843get_string( GLcontext *ctx, GLenum name )
844{
845   (void) ctx;
846   switch (name) {
847      case GL_RENDERER:
848#ifdef XFree86Server
849         return (const GLubyte *) "Mesa GLX Indirect";
850#else
851         return (const GLubyte *) "Mesa X11";
852#endif
853      case GL_VENDOR:
854#ifdef XFree86Server
855         return (const GLubyte *) "VA Linux Systems, Inc.";
856#else
857         return NULL;
858#endif
859      default:
860         return NULL;
861   }
862}
863
864
865static void
866enable( GLcontext *ctx, GLenum pname, GLboolean state )
867{
868   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
869
870   switch (pname) {
871      case GL_DITHER:
872         if (state)
873            xmesa->pixelformat = xmesa->xm_visual->dithered_pf;
874         else
875            xmesa->pixelformat = xmesa->xm_visual->undithered_pf;
876         break;
877      default:
878         ;  /* silence compiler warning */
879   }
880}
881
882
883void xmesa_update_state( GLcontext *ctx, GLuint new_state )
884{
885   const XMesaContext xmesa = (XMesaContext) ctx->DriverCtx;
886
887   /* Propogate statechange information to swrast and swrast_setup
888    * modules.  The X11 driver has no internal GL-dependent state.
889    */
890   _swrast_InvalidateState( ctx, new_state );
891   _ac_InvalidateState( ctx, new_state );
892   _tnl_InvalidateState( ctx, new_state );
893   _swsetup_InvalidateState( ctx, new_state );
894
895
896   /* setup pointers to front and back buffer clear functions */
897   xmesa->xm_buffer->front_clear_func = clear_front_pixmap;
898   if (xmesa->xm_buffer->backpixmap != XIMAGE) {
899      xmesa->xm_buffer->back_clear_func = clear_back_pixmap;
900   }
901   else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) {
902      xmesa->xm_buffer->back_clear_func = clear_nbit_ximage;
903   }
904   else switch (xmesa->xm_visual->BitsPerPixel) {
905   case 8:
906      if (xmesa->xm_visual->hpcr_clear_flag) {
907	 xmesa->xm_buffer->back_clear_func = clear_HPCR_ximage;
908      }
909      else {
910	 xmesa->xm_buffer->back_clear_func = clear_8bit_ximage;
911      }
912      break;
913   case 16:
914      xmesa->xm_buffer->back_clear_func = clear_16bit_ximage;
915      break;
916   case 24:
917      xmesa->xm_buffer->back_clear_func = clear_24bit_ximage;
918      break;
919   case 32:
920      xmesa->xm_buffer->back_clear_func = clear_32bit_ximage;
921      break;
922   default:
923      xmesa->xm_buffer->back_clear_func = clear_nbit_ximage;
924      break;
925   }
926
927   xmesa_update_span_funcs(ctx);
928}
929
930
931
932/* Setup pointers and other driver state that is constant for the life
933 * of a context.
934 */
935void xmesa_init_pointers( GLcontext *ctx )
936{
937   TNLcontext *tnl;
938
939   ctx->Driver.GetString = get_string;
940   ctx->Driver.GetBufferSize = get_buffer_size;
941   ctx->Driver.Flush = flush;
942   ctx->Driver.Finish = finish;
943
944   /* Software rasterizer pixel paths:
945    */
946   ctx->Driver.Accum = _swrast_Accum;
947   ctx->Driver.Bitmap = _swrast_Bitmap;
948   ctx->Driver.Clear = clear_buffers;
949   ctx->Driver.ResizeBuffersMESA = resize_buffers;
950   ctx->Driver.CopyPixels = _swrast_CopyPixels;
951   ctx->Driver.DrawPixels = _swrast_DrawPixels;
952   ctx->Driver.ReadPixels = _swrast_ReadPixels;
953
954   /* Software texture functions:
955    */
956   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
957   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
958   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
959   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
960   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
961   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
962   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
963   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
964
965   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
966   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
967   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
968   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
969   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
970
971
972   /* Swrast hooks for imaging extensions:
973    */
974   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
975   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
976   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
977   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
978
979
980   /* Statechange callbacks:
981    */
982   ctx->Driver.SetDrawBuffer = set_draw_buffer;
983   ctx->Driver.ClearIndex = clear_index;
984   ctx->Driver.ClearColor = clear_color;
985   ctx->Driver.IndexMask = index_mask;
986   ctx->Driver.ColorMask = color_mask;
987   ctx->Driver.Enable = enable;
988
989
990   /* Initialize the TNL driver interface:
991    */
992   tnl = TNL_CONTEXT(ctx);
993   tnl->Driver.RenderStart = _swsetup_RenderStart;
994   tnl->Driver.RenderFinish = _swsetup_RenderFinish;
995   tnl->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
996   tnl->Driver.RenderPrimitive = _swsetup_RenderPrimitive;
997   tnl->Driver.PointsFunc = _swsetup_Points;
998   tnl->Driver.LineFunc = _swsetup_Line;
999   tnl->Driver.TriangleFunc = _swsetup_Triangle;
1000   tnl->Driver.QuadFunc = _swsetup_Quad;
1001   tnl->Driver.ResetLineStipple = _swrast_ResetLineStipple;
1002   tnl->Driver.RenderInterp = _swsetup_RenderInterp;
1003   tnl->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
1004   tnl->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
1005   tnl->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
1006
1007   (void) DitherValues;  /* silenced unused var warning */
1008}
1009