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